2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2023 Vladimir Golovnev <glassez@yandex.ru>
4 * Copyright (C) 2018 Mike Tzou (Chocobo1)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, the copyright holders give permission to
21 * link this program with the OpenSSL project's "OpenSSL" library (or with
22 * modified versions of it that use the same license as the "OpenSSL" library),
23 * and distribute the linked executables. You must obey the GNU General Public
24 * License in all respects for all of the code used other than "OpenSSL". If you
25 * modify file(s), you may extend this exception to your version of the file(s),
26 * but you are not obligated to do so. If you do not wish to do so, delete this
27 * exception statement from your version.
34 #include <openssl/evp.h>
40 #include "base/global.h"
41 #include "bytearray.h"
50 const int hashIterations
= 100000;
51 const auto hashMethod
= EVP_sha512();
56 // Implements constant-time comparison to protect against timing attacks
57 // Taken from https://crackstation.net/hashing-security.htm
58 bool Utils::Password::slowEquals(const QByteArray
&a
, const QByteArray
&b
)
60 const int lengthA
= a
.length();
61 const int lengthB
= b
.length();
63 int diff
= lengthA
^ lengthB
;
64 for (int i
= 0; (i
< lengthA
) && (i
< lengthB
); ++i
)
70 QString
Utils::Password::generate()
72 const QString alphanum
= u
"23456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz"_s
;
73 const int passwordLength
= 9;
75 pass
.reserve(passwordLength
);
76 while (pass
.length() < passwordLength
)
78 const auto num
= Utils::Random::rand(0, (alphanum
.size() - 1));
79 pass
.append(alphanum
[num
]);
85 QByteArray
Utils::Password::PBKDF2::generate(const QString
&password
)
87 return generate(password
.toUtf8());
90 QByteArray
Utils::Password::PBKDF2::generate(const QByteArray
&password
)
92 const std::array
<uint32_t, 4> salt
{
93 {Random::rand(), Random::rand(), Random::rand(), Random::rand()}};
95 std::array
<unsigned char, 64> outBuf
{};
96 const int hmacResult
= PKCS5_PBKDF2_HMAC(password
.constData(), password
.size()
97 , reinterpret_cast<const unsigned char *>(salt
.data()), static_cast<int>(sizeof(salt
[0]) * salt
.size())
98 , hashIterations
, hashMethod
99 , static_cast<int>(outBuf
.size()), outBuf
.data());
103 const QByteArray saltView
= QByteArray::fromRawData(
104 reinterpret_cast<const char *>(salt
.data()), static_cast<int>(sizeof(salt
[0]) * salt
.size()));
105 const QByteArray outBufView
= QByteArray::fromRawData(
106 reinterpret_cast<const char *>(outBuf
.data()), static_cast<int>(outBuf
.size()));
108 return (saltView
.toBase64() + ':' + outBufView
.toBase64());
111 bool Utils::Password::PBKDF2::verify(const QByteArray
&secret
, const QString
&password
)
113 return verify(secret
, password
.toUtf8());
116 bool Utils::Password::PBKDF2::verify(const QByteArray
&secret
, const QByteArray
&password
)
118 const QList
<QByteArrayView
> list
= ByteArray::splitToViews(secret
, ":", Qt::SkipEmptyParts
);
119 if (list
.size() != 2)
122 const QByteArray salt
= QByteArray::fromBase64(Utils::ByteArray::asQByteArray(list
[0]));
123 const QByteArray key
= QByteArray::fromBase64(Utils::ByteArray::asQByteArray(list
[1]));
125 std::array
<unsigned char, 64> outBuf
{};
126 const int hmacResult
= PKCS5_PBKDF2_HMAC(password
.constData(), password
.size()
127 , reinterpret_cast<const unsigned char *>(salt
.constData()), salt
.size()
128 , hashIterations
, hashMethod
129 , static_cast<int>(outBuf
.size()), outBuf
.data());
133 const QByteArray outBufView
= QByteArray::fromRawData(
134 reinterpret_cast<const char *>(outBuf
.data()), static_cast<int>(outBuf
.size()));
135 return slowEquals(key
, outBufView
);