WebAPI: Add a way to download .torrent file using search plugin
[qBittorrent.git] / src / base / utils / password.cpp
blobbec752530071862e141d06403d30884d1e52741c
1 /*
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.
30 #include "password.h"
32 #include <array>
34 #include <openssl/evp.h>
36 #include <QByteArray>
37 #include <QString>
38 #include <QVector>
40 #include "base/global.h"
41 #include "bytearray.h"
42 #include "random.h"
44 namespace Utils
46 namespace Password
48 namespace PBKDF2
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)
65 diff |= a[i] ^ b[i];
67 return (diff == 0);
70 QString Utils::Password::generate()
72 const QString alphanum = u"23456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz"_s;
73 const int passwordLength = 9;
74 QString pass;
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]);
82 return pass;
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());
100 if (hmacResult != 1)
101 return {};
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)
120 return false;
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());
130 if (hmacResult != 1)
131 return false;
133 const QByteArray outBufView = QByteArray::fromRawData(
134 reinterpret_cast<const char *>(outBuf.data()), static_cast<int>(outBuf.size()));
135 return slowEquals(key, outBufView);