keepassxc

Форк
0
/
Crypto.cpp 
276 строк · 10.1 Кб
1
/*
2
 *  Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
3
 *  Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
4
 *
5
 *  This program is free software: you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation, either version 2 or (at your option)
8
 *  version 3 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
#include "Crypto.h"
20

21
#include "config-keepassx.h"
22

23
#include "crypto/CryptoHash.h"
24
#include "crypto/SymmetricCipher.h"
25

26
#include <botan/version.h>
27

28
namespace
29
{
30
    QString g_cryptoError;
31

32
    bool testSha256()
33
    {
34
        if (CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha256)
35
            != QByteArray::fromHex("248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")) {
36
            g_cryptoError = "SHA-256 mismatch.";
37
            return false;
38
        }
39

40
        return true;
41
    }
42

43
    bool testSha512()
44
    {
45
        if (CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", CryptoHash::Sha512)
46
            != QByteArray::fromHex("204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335"
47
                                   "96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445")) {
48
            g_cryptoError = "SHA-512 mismatch.";
49
            return false;
50
        }
51

52
        return true;
53
    }
54

55
    bool testAes256Cbc()
56
    {
57
        QByteArray key = QByteArray::fromHex("603deb1015ca71be2b73aef0857d7781"
58
                                             "1f352c073b6108d72d9810a30914dff4");
59
        QByteArray iv = QByteArray::fromHex("000102030405060708090a0b0c0d0e0f");
60
        QByteArray plainText = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a"
61
                                                   "ae2d8a571e03ac9c9eb76fac45af8e51");
62
        QByteArray cipherText = QByteArray::fromHex("f58c4c04d6e5f1ba779eabfb5f7bfbd6"
63
                                                    "9cfc4e967edb808d679f777bc6702c7d");
64

65
        QByteArray data = plainText;
66
        SymmetricCipher aes256;
67
        if (!aes256.init(SymmetricCipher::Aes256_CBC, SymmetricCipher::Encrypt, key, iv)) {
68
            g_cryptoError = aes256.errorString();
69
            return false;
70
        }
71
        if (!aes256.process(data)) {
72
            g_cryptoError = aes256.errorString();
73
            return false;
74
        }
75
        if (data != cipherText) {
76
            g_cryptoError = "AES-256 CBC encryption mismatch.";
77
            return false;
78
        }
79

80
        if (!aes256.init(SymmetricCipher::Aes256_CBC, SymmetricCipher::Decrypt, key, iv)) {
81
            g_cryptoError = aes256.errorString();
82
            return false;
83
        }
84
        if (!aes256.process(data)) {
85
            g_cryptoError = aes256.errorString();
86
            return false;
87
        }
88
        if (data != plainText) {
89
            g_cryptoError = "AES-256 CBC decryption mismatch.";
90
            return false;
91
        }
92

93
        return true;
94
    }
95

96
    bool testAesKdf()
97
    {
98
        QByteArray key = QByteArray::fromHex("000102030405060708090A0B0C0D0E0F"
99
                                             "101112131415161718191A1B1C1D1E1F");
100
        QByteArray plainText = QByteArray::fromHex("00112233445566778899AABBCCDDEEFF");
101
        QByteArray cipherText = QByteArray::fromHex("8EA2B7CA516745BFEAFC49904B496089");
102

103
        if (!SymmetricCipher::aesKdf(key, 1, plainText)) {
104
            g_cryptoError = "AES KDF Failed.";
105
        }
106

107
        if (plainText != cipherText) {
108
            g_cryptoError = "AES KDF encryption mismatch.";
109
            return false;
110
        }
111

112
        return true;
113
    }
114

115
    bool testTwofish()
116
    {
117
        QByteArray key = QByteArray::fromHex("603deb1015ca71be2b73aef0857d7781"
118
                                             "1f352c073b6108d72d9810a30914dff4");
119
        QByteArray iv = QByteArray::fromHex("000102030405060708090a0b0c0d0e0f");
120
        QByteArray plainText = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a"
121
                                                   "ae2d8a571e03ac9c9eb76fac45af8e51");
122
        QByteArray cipherText = QByteArray::fromHex("e0227c3cc80f3cb1b2ed847cc6f57d3c"
123
                                                    "657b1e7960b30fb7c8d62e72ae37c3a0");
124
        QByteArray data = plainText;
125
        SymmetricCipher twofish;
126
        if (!twofish.init(SymmetricCipher::Twofish_CBC, SymmetricCipher::Encrypt, key, iv)) {
127
            g_cryptoError = twofish.errorString();
128
            return false;
129
        }
130
        if (!twofish.process(data)) {
131
            g_cryptoError = twofish.errorString();
132
            return false;
133
        }
134
        if (data != cipherText) {
135
            g_cryptoError = "Twofish encryption mismatch.";
136
            return false;
137
        }
138

139
        if (!twofish.init(SymmetricCipher::Twofish_CBC, SymmetricCipher::Decrypt, key, iv)) {
140
            g_cryptoError = twofish.errorString();
141
            return false;
142
        }
143
        if (!twofish.process(data)) {
144
            g_cryptoError = twofish.errorString();
145
            return false;
146
        }
147
        if (data != plainText) {
148
            g_cryptoError = "Twofish encryption mismatch.";
149
            return false;
150
        }
151

152
        return true;
153
    }
154

155
    bool testSalsa20()
156
    {
157
        QByteArray salsa20Key = QByteArray::fromHex("F3F4F5F6F7F8F9FAFBFCFDFEFF000102"
158
                                                    "030405060708090A0B0C0D0E0F101112");
159
        QByteArray salsa20iv = QByteArray::fromHex("0000000000000000");
160
        QByteArray salsa20Plain = QByteArray::fromHex("00000000000000000000000000000000");
161
        QByteArray salsa20Cipher = QByteArray::fromHex("B4C0AFA503BE7FC29A62058166D56F8F");
162

163
        QByteArray data = salsa20Plain;
164
        SymmetricCipher salsa20Stream;
165
        if (!salsa20Stream.init(SymmetricCipher::Salsa20, SymmetricCipher::Encrypt, salsa20Key, salsa20iv)) {
166
            g_cryptoError = salsa20Stream.errorString();
167
            return false;
168
        }
169
        if (!salsa20Stream.process(data)) {
170
            g_cryptoError = salsa20Stream.errorString();
171
            return false;
172
        }
173
        if (data != salsa20Cipher) {
174
            g_cryptoError = "Salsa20 stream cipher encrypt mismatch.";
175
            return false;
176
        }
177

178
        if (!salsa20Stream.init(SymmetricCipher::Salsa20, SymmetricCipher::Decrypt, salsa20Key, salsa20iv)) {
179
            g_cryptoError = salsa20Stream.errorString();
180
            return false;
181
        }
182
        if (!salsa20Stream.process(data)) {
183
            g_cryptoError = salsa20Stream.errorString();
184
            return false;
185
        }
186
        if (data != salsa20Plain) {
187
            g_cryptoError = "Salsa20 stream cipher decrypt mismatch.";
188
            return false;
189
        }
190

191
        return true;
192
    }
193

194
    bool testChaCha20()
195
    {
196
        QByteArray chacha20Key = QByteArray::fromHex("00000000000000000000000000000000"
197
                                                     "00000000000000000000000000000000");
198
        QByteArray chacha20iv = QByteArray::fromHex("0000000000000000");
199
        QByteArray chacha20Plain =
200
            QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000"
201
                                "0000000000000000000000000000000000000000000000000000000000000000");
202
        QByteArray chacha20Cipher =
203
            QByteArray::fromHex("76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7"
204
                                "da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586");
205

206
        QByteArray data = chacha20Plain;
207
        SymmetricCipher chacha20Stream;
208
        if (!chacha20Stream.init(SymmetricCipher::ChaCha20, SymmetricCipher::Encrypt, chacha20Key, chacha20iv)) {
209
            g_cryptoError = chacha20Stream.errorString();
210
            return false;
211
        }
212
        if (!chacha20Stream.process(data)) {
213
            g_cryptoError = chacha20Stream.errorString();
214
            return false;
215
        }
216
        if (data != chacha20Cipher) {
217
            g_cryptoError = "ChaCha20 stream cipher encrypt mismatch.";
218
            return false;
219
        }
220

221
        if (!chacha20Stream.init(SymmetricCipher::ChaCha20, SymmetricCipher::Decrypt, chacha20Key, chacha20iv)) {
222
            g_cryptoError = chacha20Stream.errorString();
223
            return false;
224
        }
225
        if (!chacha20Stream.process(data)) {
226
            g_cryptoError = chacha20Stream.errorString();
227
            return false;
228
        }
229
        if (data != chacha20Plain) {
230
            g_cryptoError = "ChaCha20 stream cipher decrypt mismatch.";
231
            return false;
232
        }
233

234
        return true;
235
    }
236
} // namespace
237

238
namespace Crypto
239
{
240
    bool init()
241
    {
242
#ifdef WITH_XC_BOTAN3
243
        unsigned int version_major = 3, min_version_minor = 0;
244
        QString versionString = "3.x";
245
#else
246
        unsigned int version_major = 2, min_version_minor = 11;
247
        QString versionString = "2.11.x";
248
#endif
249
        if (Botan::version_major() != version_major || Botan::version_minor() < min_version_minor) {
250
            g_cryptoError = QObject::tr("Botan library must be at least %1, found %2.%3.%4")
251
                                .arg(versionString)
252
                                .arg(Botan::version_major())
253
                                .arg(Botan::version_minor())
254
                                .arg(Botan::version_patch());
255
            return false;
256
        }
257

258
        return testSha256() && testSha512() && testAes256Cbc() && testAesKdf() && testTwofish() && testSalsa20()
259
               && testChaCha20();
260
    }
261

262
    QString errorString()
263
    {
264
        return g_cryptoError;
265
    }
266

267
    QString debugInfo()
268
    {
269
        QString debugInfo = QObject::tr("Cryptographic libraries:").append("\n");
270
        debugInfo.append(QString("- Botan %1.%2.%3\n")
271
                             .arg(Botan::version_major())
272
                             .arg(Botan::version_minor())
273
                             .arg(Botan::version_patch()));
274
        return debugInfo;
275
    }
276
} // namespace Crypto
277

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.