18 #include "credentialpassword_p.h"
19 #include "authenticationrealm.h"
21 #include <QLoggingCategory>
22 #include <QMessageAuthenticationCode>
26 using namespace Cutelyst;
28 Q_LOGGING_CATEGORY(C_CREDENTIALPASSWORD,
"cutelyst.plugin.credentialpassword", QtWarningMsg)
31 , d_ptr(new CredentialPasswordPrivate)
36 CredentialPassword::~CredentialPassword()
47 if (d->checkPassword(_user, authinfo)) {
50 qCDebug(C_CREDENTIALPASSWORD) <<
"Password didn't match";
53 qCDebug(C_CREDENTIALPASSWORD) <<
"Unable to locate a user matching user info provided in realm";
61 return d->passwordField;
67 d->passwordField = fieldName;
73 return d->passwordType;
79 d->passwordType = type;
85 return d->passwordPreSalt;
97 return d->passwordPostSalt;
110 for(
int i = 0; i < a.
size() && i < b.
size(); i++) {
116 #define HASH_SECTIONS 4
117 #define HASH_ALGORITHM_INDEX 0
118 #define HASH_ITERATION_INDEX 1
119 #define HASH_SALT_INDEX 2
120 #define HASH_PBKDF2_INDEX 3
124 if (params.
size() < HASH_SECTIONS) {
128 int method = CredentialPasswordPrivate::cryptoStrToEnum(params.
at(HASH_ALGORITHM_INDEX));
137 static_cast<QCryptographicHash::Algorithm>(method),
139 params.
at(HASH_SALT_INDEX),
140 params.
at(HASH_ITERATION_INDEX).toInt(),
150 QFile random(QStringLiteral(
"/dev/urandom"));
151 if (random.
open(QIODevice::ReadOnly)) {
152 salt = random.
read(saltByteSize).toBase64();
160 const QByteArray methodStr = CredentialPasswordPrivate::cryptoEnumToStr(method);
173 return createPassword(password, QCryptographicHash::Sha512, 10000, 16, 16);
184 if (rounds <= 0 || keyLength <= 0) {
185 qCCritical(C_CREDENTIALPASSWORD,
"PBKDF2 ERROR: Invalid parameters.");
189 if (salt.
size() == 0 || salt.
size() > std::numeric_limits<int>::max() - 4) {
194 int saltSize = salt.
size();
196 asalt.
resize(saltSize + 4);
202 for (
int count = 1, remainingBytes = keyLength; remainingBytes > 0; ++count) {
203 asalt[saltSize + 0] =
static_cast<char>((count >> 24) & 0xff);
204 asalt[saltSize + 1] =
static_cast<char>((count >> 16) & 0xff);
205 asalt[saltSize + 2] =
static_cast<char>((count >> 8) & 0xff);
206 asalt[saltSize + 3] =
static_cast<char>(count & 0xff);
210 obuf = d1 = code.
result();
212 for (
int i = 1; i < rounds; ++i) {
216 auto it = obuf.
begin();
218 while (d1It != d1.
cend()) {
226 remainingBytes -= obuf.
size();
229 key = key.
mid(0, keyLength);
243 if (Q_LIKELY(passwordType == CredentialPassword::Hashed)) {
244 if (!passwordPreSalt.isEmpty()) {
248 if (!passwordPostSalt.isEmpty()) {
249 password.
append(password);
253 }
else if (passwordType == CredentialPassword::Clear) {
254 return storedPassword == password;
255 }
else if (passwordType == CredentialPassword::None) {
256 qCDebug(C_CREDENTIALPASSWORD) <<
"CredentialPassword is set to ignore password check";
263 QByteArray CredentialPasswordPrivate::cryptoEnumToStr(QCryptographicHash::Algorithm method)
267 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
268 if (method == QCryptographicHash::Md4) {
269 hashmethod = QByteArrayLiteral(
"Md4");
270 }
else if (method == QCryptographicHash::Md5) {
271 hashmethod = QByteArrayLiteral(
"Md5");
274 if (method == QCryptographicHash::Sha1) {
275 hashmethod = QByteArrayLiteral(
"Sha1");
277 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
278 if (method == QCryptographicHash::Sha224) {
279 hashmethod = QByteArrayLiteral(
"Sha224");
280 }
else if (method == QCryptographicHash::Sha256) {
281 hashmethod = QByteArrayLiteral(
"Sha256");
282 }
else if (method == QCryptographicHash::Sha384) {
283 hashmethod = QByteArrayLiteral(
"Sha384");
284 }
else if (method == QCryptographicHash::Sha512) {
285 hashmethod = QByteArrayLiteral(
"Sha512");
286 }
else if (method == QCryptographicHash::Sha3_224) {
287 hashmethod = QByteArrayLiteral(
"Sha3_224");
288 }
else if (method == QCryptographicHash::Sha3_256) {
289 hashmethod = QByteArrayLiteral(
"Sha3_256");
290 }
else if (method == QCryptographicHash::Sha3_384) {
291 hashmethod = QByteArrayLiteral(
"Sha3_384");
292 }
else if (method == QCryptographicHash::Sha3_512) {
293 hashmethod = QByteArrayLiteral(
"Sha3_512");
300 int CredentialPasswordPrivate::cryptoStrToEnum(
const QByteArray &hashMethod)
305 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
306 if (hashmethod ==
"Md4") {
307 method = QCryptographicHash::Md4;
308 }
else if (hashmethod ==
"Md5") {
309 method = QCryptographicHash::Md5;
312 if (hashmethod ==
"Sha1") {
313 method = QCryptographicHash::Sha1;
315 #ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
316 if (hashmethod ==
"Sha224") {
317 method = QCryptographicHash::Sha224;
318 }
else if (hashmethod ==
"Sha256") {
319 method = QCryptographicHash::Sha256;
320 }
else if (hashmethod ==
"Sha384") {
321 method = QCryptographicHash::Sha384;
322 }
else if (hashmethod ==
"Sha512") {
323 method = QCryptographicHash::Sha512;
324 }
else if (hashmethod ==
"Sha3_224") {
325 method = QCryptographicHash::Sha3_224;
326 }
else if (hashmethod ==
"Sha3_256") {
327 method = QCryptographicHash::Sha3_256;
328 }
else if (hashmethod ==
"Sha3_384") {
329 method = QCryptographicHash::Sha3_384;
330 }
else if (hashmethod ==
"Sha3_512") {
331 method = QCryptographicHash::Sha3_512;
338 #include "moc_credentialpassword.cpp"
const_iterator cbegin() const
QString & append(QChar ch)
QList< QByteArray > split(char sep) const
virtual AuthenticationUser findUser(Context *c, const ParamsMultiMap &userinfo)
Tries to find the user with authinfo returning a non null AuthenticationUser on success.
const_iterator cend() const
void setPasswordPreSalt(const QString &passwordPreSalt)
Sets the salt string to be prepended to the password.
QString & prepend(QChar ch)
const T & at(int i) const
QByteArray fromBase64(const QByteArray &base64, Base64Options options)
static QByteArray hmac(QCryptographicHash::Algorithm method, const QByteArray &key, const QByteArray &message)
Generates the Hash-based message authentication code.
PasswordType passwordType() const
Returns the type of password this class will be dealing with.
QString passwordPreSalt() const
Returns the salt string to be prepended to the password.
QString passwordPostSalt() const
Returns the salt string to be appended to the password.
void setPasswordType(PasswordType type)
Sets the type of password this class will be dealing with.
static QByteArray createPassword(const QByteArray &password, QCryptographicHash::Algorithm method, int iterations, int saltByteSize, int hashByteSize)
Creates a password hash string.
QByteArray result() const
void addData(const char *data, int length)
QByteArray number(int n, int base)
qint64 read(char *data, qint64 maxSize)
QByteArray mid(int pos, int len) const
virtual bool open(OpenMode mode)
QByteArray & append(char ch)
QByteArray hash(const QByteArray &message, const QByteArray &key, QCryptographicHash::Algorithm method)
void setPasswordField(const QString &fieldName)
Sets the field to look for when authenticating the user.
bool isNull() const
Returns true if the object is null.
static QByteArray pbkdf2(QCryptographicHash::Algorithm method, const QByteArray &password, const QByteArray &salt, int rounds, int keyLength)
Generates a pbkdf2 string for the given password.
QString passwordField() const
Returns the field to look for when authenticating the user.
void setPasswordPostSalt(const QString &passwordPostSalt)
Sets the salt string to be appended to the password.
AuthenticationUser authenticate(Context *c, AuthenticationRealm *realm, const ParamsMultiMap &authinfo) final
Tries to authenticate the authinfo using the give realm.
QByteArray toRfc4122() const
QByteArray toBase64(Base64Options options) const
static bool validatePassword(const QByteArray &password, const QByteArray &correctHash)
Validates the given password against the correct hash.
const T value(const Key &key, const T &defaultValue) const
QByteArray toUtf8() const