File indexing completed on 2024-04-28 04:44:09
0001 /** 0002 * Copyright (C) 2004-2006 Brad Hards <bradh@frogmouth.net> 0003 * 0004 * Redistribution and use in source and binary forms, with or without 0005 * modification, are permitted provided that the following conditions 0006 * are met: 0007 * 0008 * 1. Redistributions of source code must retain the above copyright 0009 * notice, this list of conditions and the following disclaimer. 0010 * 2. Redistributions in binary form must reproduce the above copyright 0011 * notice, this list of conditions and the following disclaimer in the 0012 * documentation and/or other materials provided with the distribution. 0013 * 0014 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0017 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0024 */ 0025 0026 #include <QtCrypto> 0027 #include <QtTest/QtTest> 0028 0029 #ifdef QT_STATICPLUGIN 0030 #include "import_plugins.h" 0031 #endif 0032 0033 class KDFUnitTest : public QObject 0034 { 0035 Q_OBJECT 0036 0037 private Q_SLOTS: 0038 void initTestCase(); 0039 void cleanupTestCase(); 0040 void pbkdf1md2Tests_data(); 0041 void pbkdf1md2Tests(); 0042 void pbkdf1sha1Tests_data(); 0043 void pbkdf1sha1Tests(); 0044 void pbkdf1sha1TimeTest(); 0045 void pbkdf2Tests_data(); 0046 void pbkdf2Tests(); 0047 void pbkdf2TimeTest(); 0048 void pbkdf2extraTests(); 0049 void hkdfTests_data(); 0050 void hkdfTests(); 0051 0052 private: 0053 QCA::Initializer *m_init; 0054 QStringList providersToTest; 0055 }; 0056 0057 void KDFUnitTest::initTestCase() 0058 { 0059 m_init = new QCA::Initializer; 0060 0061 const auto providers = QCA::providers(); 0062 for (QCA::Provider *provider : providers) 0063 providersToTest << provider->name(); 0064 } 0065 0066 void KDFUnitTest::cleanupTestCase() 0067 { 0068 delete m_init; 0069 } 0070 0071 void KDFUnitTest::pbkdf1md2Tests_data() 0072 { 0073 QTest::addColumn<QString>("secret"); // usually a password or passphrase 0074 QTest::addColumn<QString>("output"); // the key you get back 0075 QTest::addColumn<QString>("salt"); // a salt or initialisation vector 0076 QTest::addColumn<unsigned int>("outputLength"); // if the algo supports variable length keys, len 0077 QTest::addColumn<unsigned int>("iterationCount"); // number of iterations 0078 0079 // These are from Botan's test suite 0080 QTest::newRow("1") << QStringLiteral("71616c7a73656774") << QStringLiteral("7c1991f3f38a09d70cf3b1acadb70bc6") 0081 << QStringLiteral("40cf117c3865e0cf") << static_cast<unsigned int>(16) 0082 << static_cast<unsigned int>(1000); 0083 0084 QTest::newRow("2") << QStringLiteral("766e68617a6a66736978626f6d787175") 0085 << QStringLiteral("677500eda9f0c5e96e0a11f90fb9") << QStringLiteral("3a2484ce5d3e1b4d") 0086 << static_cast<unsigned int>(14) << static_cast<unsigned int>(1); 0087 0088 QTest::newRow("3") << QStringLiteral("66686565746e657162646d7171716e797977696f716a666c6f6976636371756a") 0089 << QStringLiteral("91a5b689156b441bf27dd2bdd276") 0090 << QStringLiteral("5d838b0f4fa22bfa2157f9083d87f8752e0495bb2113012761ef11b66e87c3cb") 0091 << static_cast<unsigned int>(14) << static_cast<unsigned int>(15); 0092 0093 QTest::newRow("4") << QStringLiteral("736e6279696e6a7075696b7176787867726c6b66") 0094 << QStringLiteral("49516935cc9f438bafa30ff038fb") 0095 << QStringLiteral("f22d341361b47e3390107bd973fdc0d3e0bc02a3") << static_cast<unsigned int>(14) 0096 << static_cast<unsigned int>(2); 0097 } 0098 0099 void KDFUnitTest::pbkdf1md2Tests() 0100 { 0101 QFETCH(QString, secret); 0102 QFETCH(QString, output); 0103 QFETCH(QString, salt); 0104 QFETCH(unsigned int, outputLength); 0105 QFETCH(unsigned int, iterationCount); 0106 0107 bool anyProviderTested = false; 0108 foreach (QString provider, providersToTest) { 0109 if (QCA::isSupported("pbkdf1(md2)", provider)) { 0110 anyProviderTested = true; 0111 QCA::SecureArray password = QCA::hexToArray(secret); 0112 QCA::InitializationVector iv(QCA::hexToArray(salt)); 0113 QCA::SymmetricKey key = 0114 QCA::PBKDF1(QStringLiteral("md2"), provider).makeKey(password, iv, outputLength, iterationCount); 0115 QCOMPARE(QCA::arrayToHex(key.toByteArray()), output); 0116 } 0117 } 0118 if (!anyProviderTested) 0119 qWarning() << "NONE of the providers supports PBKDF version 1 with MD2:" << providersToTest; 0120 } 0121 0122 void KDFUnitTest::pbkdf1sha1Tests_data() 0123 { 0124 QTest::addColumn<QString>("secret"); // usually a password or passphrase 0125 QTest::addColumn<QString>("output"); // the key you get back 0126 QTest::addColumn<QString>("salt"); // a salt or initialisation vector 0127 QTest::addColumn<unsigned int>("outputLength"); // if the algo supports variable length keys, len 0128 QTest::addColumn<unsigned int>("iterationCount"); // number of iterations 0129 0130 // These are from Botan's test suite 0131 QTest::newRow("1") << QStringLiteral("66746c6b6662786474626a62766c6c7662776977") 0132 << QStringLiteral("768b277dc970f912dbdd3edad48ad2f065d25d") 0133 << QStringLiteral("40ac5837560251c275af5e30a6a3074e57ced38e") << static_cast<unsigned int>(19) 0134 << static_cast<unsigned int>(6); 0135 0136 QTest::newRow("2") << QStringLiteral("786e736f736d6b766867677a7370636e63706f63") 0137 << QStringLiteral("4d90e846a4b6aaa02ac548014a00e97e506b2afb") 0138 << QStringLiteral("7008a9dc1b9a81470a2360275c19dab77f716824") << static_cast<unsigned int>(20) 0139 << static_cast<unsigned int>(6); 0140 0141 QTest::newRow("3") << QStringLiteral("6f74696c71776c756b717473") 0142 << QStringLiteral("71ed1a995e693efcd33155935e800037da74ea28") 0143 << QStringLiteral("ccfc44c09339040e55d3f7f76ca6ef838fde928717241deb9ac1a4ef45a27711") 0144 << static_cast<unsigned int>(20) << static_cast<unsigned int>(2001); 0145 0146 QTest::newRow("4") << QStringLiteral("6b7a6e657166666c6274767374686e6663746166") 0147 << QStringLiteral("f345fb8fbd880206b650266661f6") 0148 << QStringLiteral("8108883fc04a01feb10661651516425dad1c93e0") << static_cast<unsigned int>(14) 0149 << static_cast<unsigned int>(10000); 0150 0151 QTest::newRow("5") << QStringLiteral("716b78686c7170656d7868796b6d7975636a626f") 0152 << QStringLiteral("2d54dfed0c7ef7d20b0945ba414a") 0153 << QStringLiteral("bc8bc53d4604977c3adb1d19c15e87b77a84c2f6") << static_cast<unsigned int>(14) 0154 << static_cast<unsigned int>(10000); 0155 } 0156 0157 void KDFUnitTest::pbkdf1sha1Tests() 0158 { 0159 QFETCH(QString, secret); 0160 QFETCH(QString, output); 0161 QFETCH(QString, salt); 0162 QFETCH(unsigned int, outputLength); 0163 QFETCH(unsigned int, iterationCount); 0164 0165 bool anyProviderTested = false; 0166 foreach (QString provider, providersToTest) { 0167 if (QCA::isSupported("pbkdf1(sha1)", provider)) { 0168 anyProviderTested = true; 0169 QCA::SecureArray password = QCA::hexToArray(secret); 0170 QCA::InitializationVector iv(QCA::hexToArray(salt)); 0171 QCA::PBKDF1 pbkdf = QCA::PBKDF1(QStringLiteral("sha1"), provider); 0172 QCA::PBKDF1 copy = pbkdf; 0173 copy.context(); // detach 0174 QCA::SymmetricKey key = pbkdf.makeKey(password, iv, outputLength, iterationCount); 0175 QCOMPARE(QCA::arrayToHex(key.toByteArray()), output); 0176 } 0177 } 0178 if (!anyProviderTested) 0179 qWarning() << "NONE of the providers supports PBKDF version 1 with SHA1:" << providersToTest; 0180 } 0181 0182 void KDFUnitTest::pbkdf1sha1TimeTest() 0183 { 0184 QCA::SecureArray password("secret"); 0185 QCA::InitializationVector iv(QByteArray("salt")); 0186 unsigned int outputLength = 20; 0187 int timeInterval = 200; 0188 unsigned int iterationCount; 0189 0190 foreach (QString provider, providersToTest) { 0191 if (QCA::isSupported("pbkdf1(sha1)", provider)) { 0192 QCA::SymmetricKey key1(QCA::PBKDF1(QStringLiteral("sha1"), provider) 0193 .makeKey(password, iv, outputLength, timeInterval, &iterationCount)); 0194 0195 QCA::SymmetricKey key2( 0196 QCA::PBKDF1(QStringLiteral("sha1"), provider).makeKey(password, iv, outputLength, iterationCount)); 0197 0198 QCOMPARE(key1, key2); 0199 } 0200 } 0201 } 0202 0203 void KDFUnitTest::pbkdf2Tests_data() 0204 { 0205 QTest::addColumn<QString>("secret"); // usually a password or passphrase 0206 QTest::addColumn<QString>("output"); // the key you get back 0207 QTest::addColumn<QString>("salt"); // a salt or initialisation vector 0208 QTest::addColumn<unsigned int>("outputLength"); // if the algo supports variable length keys, len 0209 QTest::addColumn<unsigned int>("iterationCount"); // number of iterations 0210 0211 // These are from Botan's test suite 0212 QTest::newRow("1") << QStringLiteral("6a79756571677872736367676c707864796b6366") 0213 << QStringLiteral("df6d9d72872404bf73e708cf3b7d") 0214 << QStringLiteral("9b56e55328a4c97a250738f8dba1b992e8a1b508") << static_cast<unsigned int>(14) 0215 << static_cast<unsigned int>(10000); 0216 0217 QTest::newRow("2") << QStringLiteral("61717271737a6e7a76767a67746b73616d6d676f") 0218 << QStringLiteral( 0219 "fa13f40af1ade2a30f2fffd66fc8a659ef95e6388c1682fc0fe4d15a70109517a32942e39c371440") 0220 << QStringLiteral("57487813cdd2220dfc485d932a2979ee8769ea8b") << static_cast<unsigned int>(40) 0221 << static_cast<unsigned int>(101); 0222 0223 QTest::newRow("3") << QStringLiteral("6c7465786d666579796c6d6c62727379696b6177") 0224 << QStringLiteral("027afadd48f4be8dcc4f") 0225 << QStringLiteral("ed1f39a0a7f3889aaf7e60743b3bc1cc2c738e60") << static_cast<unsigned int>(10) 0226 << static_cast<unsigned int>(1000); 0227 0228 QTest::newRow("4") << QStringLiteral("6378676e7972636772766c6c796c6f6c736a706f") 0229 << QStringLiteral("7c0d009fc91b48cb6d19bafbfccff3e2ccabfe725eaa234e56bde1d551c132f2") 0230 << QStringLiteral("94ac88200743fb0f6ac51be62166cbef08d94c15") << static_cast<unsigned int>(32) 0231 << static_cast<unsigned int>(1); 0232 0233 QTest::newRow("5") << QStringLiteral("7871796668727865686965646c6865776e76626a") 0234 << QStringLiteral("4661301d3517ca4443a6a607b32b2a63f69996299df75db75f1e0b98dd0eb7d8") 0235 << QStringLiteral("24a1a50b17d63ee8394b69fc70887f4f94883d68") << static_cast<unsigned int>(32) 0236 << static_cast<unsigned int>(5); 0237 0238 QTest::newRow("6") << QStringLiteral("616e6461716b706a7761627663666e706e6a6b6c") 0239 << QStringLiteral("82fb44a521448d5aac94b5158ead1e4dcd7363081a747b9f7626752bda2d") 0240 << QStringLiteral("9316c80801623cc2734af74bec42cf4dbaa3f6d5") << static_cast<unsigned int>(30) 0241 << static_cast<unsigned int>(100); 0242 0243 QTest::newRow("7") << QStringLiteral("687361767679766f636c6f79757a746c736e6975") 0244 << QStringLiteral("f8ec2b0ac817896ac8189d787c6424ed24a6d881436687a4629802c0ecce") 0245 << QStringLiteral("612cc61df3cf2bdb36e10c4d8c9d73192bddee05") << static_cast<unsigned int>(30) 0246 << static_cast<unsigned int>(100); 0247 0248 QTest::newRow("8") << QStringLiteral("6561696d72627a70636f706275736171746b6d77") 0249 << QStringLiteral("c9a0b2622f13916036e29e7462e206e8ba5b50ce9212752eb8ea2a4aa7b40a4cc1bf") 0250 << QStringLiteral("45248f9d0cebcb86a18243e76c972a1f3b36772a") << static_cast<unsigned int>(34) 0251 << static_cast<unsigned int>(100); 0252 0253 QTest::newRow("9") << QStringLiteral("67777278707178756d7364736d626d6866686d666463766c63766e677a6b6967") 0254 << QStringLiteral( 0255 "4c9db7ba24955225d5b845f65ef24ef1b0c6e86f2e39c8ddaa4b8abd26082d1f350381fadeaeb560dc447afc" 0256 "68a6b47e6ea1e7412f6cf7b2d82342fccd11d3b4") 0257 << QStringLiteral("a39b76c6eec8374a11493ad08c246a3e40dfae5064f4ee3489c273646178") 0258 << static_cast<unsigned int>(64) << static_cast<unsigned int>(1000); 0259 } 0260 0261 void KDFUnitTest::pbkdf2Tests() 0262 { 0263 QFETCH(QString, secret); 0264 QFETCH(QString, output); 0265 QFETCH(QString, salt); 0266 QFETCH(unsigned int, outputLength); 0267 QFETCH(unsigned int, iterationCount); 0268 0269 bool anyProviderTested = false; 0270 foreach (QString provider, providersToTest) { 0271 if (QCA::isSupported("pbkdf2(sha1)", provider)) { 0272 anyProviderTested = true; 0273 QCA::SecureArray password = QCA::hexToArray(secret); 0274 QCA::InitializationVector iv(QCA::hexToArray(salt)); 0275 QCA::PBKDF2 pbkdf = QCA::PBKDF2(QStringLiteral("sha1"), provider); 0276 QCA::PBKDF2 copy = pbkdf; 0277 copy.context(); // detach 0278 QCA::SymmetricKey key = pbkdf.makeKey(password, iv, outputLength, iterationCount); 0279 QCOMPARE(QCA::arrayToHex(key.toByteArray()), output); 0280 } 0281 } 0282 0283 if (!anyProviderTested) 0284 qWarning() << "NONE of the providers supports PBKDF version 2 with SHA1:" << providersToTest; 0285 } 0286 0287 void KDFUnitTest::pbkdf2TimeTest() 0288 { 0289 QCA::SecureArray password("secret"); 0290 QCA::InitializationVector iv(QByteArray("salt")); 0291 unsigned int outputLength = 20; 0292 int timeInterval = 200; 0293 unsigned int iterationCount; 0294 0295 foreach (QString provider, providersToTest) { 0296 if (QCA::isSupported("pbkdf2(sha1)", provider)) { 0297 QCA::SymmetricKey key1(QCA::PBKDF2(QStringLiteral("sha1"), provider) 0298 .makeKey(password, iv, outputLength, timeInterval, &iterationCount)); 0299 0300 QCA::SymmetricKey key2( 0301 QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, iv, outputLength, iterationCount)); 0302 0303 QCOMPARE(key1, key2); 0304 } 0305 } 0306 } 0307 0308 void KDFUnitTest::pbkdf2extraTests() 0309 { 0310 foreach (QString provider, providersToTest) { 0311 if (QCA::isSupported("pbkdf2(sha1)", provider)) { 0312 // Not sure where this one came from... 0313 { 0314 QCA::InitializationVector salt(QCA::SecureArray("what do ya want for nothing?")); 0315 QCA::SecureArray password("Jefe"); 0316 int iterations = 1000; 0317 QCA::SymmetricKey passwordOut = 0318 QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 16, iterations); 0319 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0320 QStringLiteral("6349e09cb6b8c1485cfa9780ee3264df")); 0321 } 0322 0323 // RFC3962, Appendix B 0324 { 0325 QCA::InitializationVector salt(QCA::SecureArray("ATHENA.MIT.EDUraeburn")); 0326 QCA::SecureArray password("password"); 0327 int iterations = 1; 0328 QCA::SymmetricKey passwordOut = 0329 QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 16, iterations); 0330 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0331 QStringLiteral("cdedb5281bb2f801565a1122b2563515")); 0332 passwordOut = QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 32, iterations); 0333 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0334 QStringLiteral("cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837")); 0335 } 0336 0337 // RFC3962, Appendix B 0338 { 0339 QCA::InitializationVector salt(QCA::SecureArray("ATHENA.MIT.EDUraeburn")); 0340 QCA::SecureArray password("password"); 0341 int iterations = 2; 0342 QCA::SymmetricKey passwordOut = 0343 QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 16, iterations); 0344 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0345 QStringLiteral("01dbee7f4a9e243e988b62c73cda935d")); 0346 passwordOut = QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 32, iterations); 0347 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0348 QStringLiteral("01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86")); 0349 } 0350 0351 // RFC3962, Appendix B 0352 { 0353 QCA::InitializationVector salt(QCA::SecureArray("ATHENA.MIT.EDUraeburn")); 0354 QCA::SecureArray password("password"); 0355 int iterations = 1200; 0356 QCA::SymmetricKey passwordOut = 0357 QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 16, iterations); 0358 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0359 QStringLiteral("5c08eb61fdf71e4e4ec3cf6ba1f5512b")); 0360 passwordOut = QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 32, iterations); 0361 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0362 QStringLiteral("5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13")); 0363 } 0364 0365 // RFC3211 and RFC3962, Appendix B 0366 { 0367 QCA::InitializationVector salt(QCA::hexToArray(QStringLiteral("1234567878563412"))); 0368 QCA::SecureArray password("password"); 0369 int iterations = 5; 0370 QCA::SymmetricKey passwordOut = 0371 QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 16, iterations); 0372 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0373 QStringLiteral("d1daa78615f287e6a1c8b120d7062a49")); 0374 passwordOut = QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 32, iterations); 0375 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0376 QStringLiteral("d1daa78615f287e6a1c8b120d7062a493f98d203e6be49a6adf4fa574b6e64ee")); 0377 passwordOut = QCA::PBKDF2().makeKey(password, salt, 8, iterations); 0378 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), QStringLiteral("d1daa78615f287e6")); 0379 } 0380 0381 // RFC3962, Appendix B 0382 { 0383 QCA::InitializationVector salt(QCA::SecureArray("pass phrase equals block size")); 0384 QCA::SecureArray password("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); 0385 int iterations = 1200; 0386 QCA::SymmetricKey passwordOut = 0387 QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 16, iterations); 0388 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0389 QStringLiteral("139c30c0966bc32ba55fdbf212530ac9")); 0390 passwordOut = QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 32, iterations); 0391 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0392 QStringLiteral("139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1")); 0393 } 0394 0395 // RFC3962, Appendix B 0396 { 0397 try { 0398 QCA::InitializationVector salt(QCA::SecureArray("pass phrase exceeds block size")); 0399 QCA::SecureArray password("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); 0400 int iterations = 1200; 0401 QCA::SymmetricKey passwordOut = 0402 QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 16, iterations); 0403 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0404 QStringLiteral("9ccad6d468770cd51b10e6a68721be61")); 0405 passwordOut = QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 32, iterations); 0406 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0407 QStringLiteral("9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a")); 0408 } catch (std::exception &) { 0409 if (provider == QLatin1String("qca-botan")) 0410 qDebug() << "You should use a later version of Botan"; 0411 else 0412 QFAIL("exception"); 0413 } 0414 } 0415 0416 // RFC3962, Appendix B 0417 { 0418 QCA::InitializationVector salt(QCA::SecureArray("EXAMPLE.COMpianist")); 0419 QCA::SecureArray password(QCA::hexToArray(QStringLiteral("f09d849e"))); 0420 int iterations = 50; 0421 QCA::SymmetricKey passwordOut = 0422 QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 16, iterations); 0423 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0424 QStringLiteral("6b9cf26d45455a43a5b8bb276a403b39")); 0425 passwordOut = QCA::PBKDF2(QStringLiteral("sha1"), provider).makeKey(password, salt, 32, iterations); 0426 QCOMPARE(QCA::arrayToHex(passwordOut.toByteArray()), 0427 QStringLiteral("6b9cf26d45455a43a5b8bb276a403b39e7fe37a0c41e02c281ff3069e1e94f52")); 0428 } 0429 } 0430 } 0431 } 0432 0433 void KDFUnitTest::hkdfTests_data() 0434 { 0435 QTest::addColumn<QString>("secret"); // usually a password or passphrase 0436 QTest::addColumn<QString>("salt"); // a salt or initialisation vector 0437 QTest::addColumn<QString>("info"); // an additional info 0438 QTest::addColumn<QString>("output"); // the key you get back 0439 0440 // RFC 5869, Appendix A 0441 QTest::newRow("1") << QStringLiteral("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b") 0442 << QStringLiteral("000102030405060708090a0b0c") << QStringLiteral("f0f1f2f3f4f5f6f7f8f9") 0443 << QStringLiteral( 0444 "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"); 0445 0446 QTest::newRow("2") << QStringLiteral( 0447 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b" 0448 "2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f") 0449 << QStringLiteral( 0450 "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b" 0451 "8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf") 0452 << QStringLiteral( 0453 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadb" 0454 "dcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") 0455 << QStringLiteral( 0456 "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c6" 0457 "5e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"); 0458 0459 QTest::newRow("3") << QStringLiteral("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b") << QString() << QString() 0460 << QStringLiteral( 0461 "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"); 0462 } 0463 0464 void KDFUnitTest::hkdfTests() 0465 { 0466 QFETCH(QString, secret); 0467 QFETCH(QString, salt); 0468 QFETCH(QString, info); 0469 QFETCH(QString, output); 0470 0471 bool anyProviderTested = false; 0472 foreach (QString provider, providersToTest) { 0473 if (QCA::isSupported("hkdf(sha256)", provider)) { 0474 anyProviderTested = true; 0475 QCA::SecureArray password = QCA::hexToArray(secret); 0476 QCA::InitializationVector saltv(QCA::hexToArray(salt)); 0477 QCA::InitializationVector infov(QCA::hexToArray(info)); 0478 QCA::HKDF hkdf = QCA::HKDF(QStringLiteral("sha256"), provider); 0479 QCA::HKDF copy = hkdf; 0480 copy.context(); // detach 0481 0482 QCA::SymmetricKey key = hkdf.makeKey(password, saltv, infov, output.size() / 2); 0483 QCOMPARE(QCA::arrayToHex(key.toByteArray()), output); 0484 } 0485 } 0486 if (!anyProviderTested) 0487 qWarning() << "NONE of the providers supports HKDF version 1 with SHA256:" << providersToTest; 0488 } 0489 0490 QTEST_MAIN(KDFUnitTest) 0491 0492 #include "kdfunittest.moc"