File indexing completed on 2024-05-19 15:51:01
0001 /** 0002 * Copyright (C) 2005-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 RSAUnitTest : public QObject 0034 { 0035 Q_OBJECT 0036 0037 private Q_SLOTS: 0038 void initTestCase(); 0039 void cleanupTestCase(); 0040 void testrsa(); 0041 void testAsymmetricEncryption_data(); 0042 void testAsymmetricEncryption(); 0043 0044 private: 0045 QCA::Initializer *m_init; 0046 }; 0047 0048 void RSAUnitTest::initTestCase() 0049 { 0050 m_init = new QCA::Initializer; 0051 } 0052 0053 void RSAUnitTest::cleanupTestCase() 0054 { 0055 delete m_init; 0056 } 0057 0058 void RSAUnitTest::testrsa() 0059 { 0060 QStringList providersToTest; 0061 providersToTest.append(QStringLiteral("qca-ossl")); 0062 // providersToTest.append("qca-gcrypt"); 0063 0064 foreach (const QString provider, providersToTest) { 0065 if (!QCA::isSupported("pkey", provider) || !QCA::PKey::supportedTypes(provider).contains(QCA::PKey::RSA) || 0066 !QCA::PKey::supportedIOTypes(provider).contains(QCA::PKey::RSA)) 0067 QWARN((QStringLiteral("RSA not supported for ") + provider).toLocal8Bit().constData()); 0068 else { 0069 QCA::KeyGenerator keygen; 0070 QCOMPARE(keygen.isBusy(), false); 0071 QCOMPARE(keygen.blockingEnabled(), true); 0072 0073 QList<int> keySizes; 0074 keySizes << 512 << 1024 << 768 << 2048; 0075 foreach (int keysize, keySizes) { 0076 QCA::PrivateKey rsaKey = keygen.createRSA(keysize, 65537, provider); 0077 QCOMPARE(rsaKey.isNull(), false); 0078 QCOMPARE(rsaKey.isRSA(), true); 0079 QCOMPARE(rsaKey.isDSA(), false); 0080 QCOMPARE(rsaKey.isDH(), false); 0081 QCOMPARE(rsaKey.isPrivate(), true); 0082 QCOMPARE(rsaKey.isPublic(), false); 0083 QCOMPARE(rsaKey.canSign(), true); 0084 QCOMPARE(rsaKey.canDecrypt(), true); 0085 QCOMPARE(rsaKey.canEncrypt(), true); 0086 0087 QCA::RSAPrivateKey rsaPrivKey = rsaKey.toRSA(); 0088 QCOMPARE(rsaPrivKey.bitSize(), keysize); 0089 0090 QString rsaPEM = rsaKey.toPEM(); 0091 QCOMPARE(rsaPEM.isEmpty(), false); 0092 0093 QCA::ConvertResult checkResult; 0094 QCA::PrivateKey fromPEMkey = QCA::PrivateKey::fromPEM(rsaPEM, QCA::SecureArray(), &checkResult); 0095 QCOMPARE(checkResult, QCA::ConvertGood); 0096 QCOMPARE(fromPEMkey.isNull(), false); 0097 QCOMPARE(fromPEMkey.isRSA(), true); 0098 QCOMPARE(fromPEMkey.isDSA(), false); 0099 QCOMPARE(fromPEMkey.isDH(), false); 0100 QCOMPARE(fromPEMkey.isPrivate(), true); 0101 QCOMPARE(fromPEMkey.isPublic(), false); 0102 QCOMPARE(rsaKey == fromPEMkey, true); 0103 0104 QCA::SecureArray rsaDER = rsaKey.toDER(QCA::SecureArray("foo")); 0105 QCOMPARE(rsaDER.isEmpty(), false); 0106 0107 QCA::PrivateKey fromDERkey = QCA::PrivateKey::fromDER(rsaDER, QCA::SecureArray("foo"), &checkResult); 0108 QCOMPARE(checkResult, QCA::ConvertGood); 0109 QCOMPARE(fromDERkey.isNull(), false); 0110 QCOMPARE(fromDERkey.isRSA(), true); 0111 QCOMPARE(fromDERkey.isDSA(), false); 0112 QCOMPARE(fromDERkey.isDH(), false); 0113 QCOMPARE(fromDERkey.isPrivate(), true); 0114 QCOMPARE(fromDERkey.isPublic(), false); 0115 QCOMPARE(rsaKey == fromDERkey, true); 0116 0117 // same test, without passphrase 0118 rsaDER = rsaKey.toDER(); 0119 QCOMPARE(rsaDER.isEmpty(), false); 0120 0121 fromDERkey = QCA::PrivateKey::fromDER(rsaDER, QCA::SecureArray(), &checkResult); 0122 QCOMPARE(checkResult, QCA::ConvertGood); 0123 QCOMPARE(fromDERkey.isNull(), false); 0124 QCOMPARE(fromDERkey.isRSA(), true); 0125 QCOMPARE(fromDERkey.isDSA(), false); 0126 QCOMPARE(fromDERkey.isDH(), false); 0127 QCOMPARE(fromDERkey.isPrivate(), true); 0128 QCOMPARE(fromDERkey.isPublic(), false); 0129 QCOMPARE(rsaKey == fromDERkey, true); 0130 0131 QCA::PublicKey pubKey = rsaKey.toPublicKey(); 0132 QCOMPARE(pubKey.isNull(), false); 0133 QCOMPARE(pubKey.isRSA(), true); 0134 QCOMPARE(pubKey.isDSA(), false); 0135 QCOMPARE(pubKey.isDH(), false); 0136 QCOMPARE(pubKey.isPrivate(), false); 0137 QCOMPARE(pubKey.isPublic(), true); 0138 0139 QCA::RSAPublicKey RSApubKey = pubKey.toRSA(); 0140 QCOMPARE(RSApubKey.e(), QCA::BigInteger(65537)); 0141 QCOMPARE(RSApubKey.isNull(), false); 0142 QCOMPARE(RSApubKey.isRSA(), true); 0143 QCOMPARE(RSApubKey.isDSA(), false); 0144 QCOMPARE(RSApubKey.isDH(), false); 0145 QCOMPARE(RSApubKey.isPrivate(), false); 0146 QCOMPARE(RSApubKey.isPublic(), true); 0147 } 0148 } 0149 } 0150 } 0151 0152 Q_DECLARE_METATYPE(QCA::EncryptionAlgorithm) 0153 0154 void RSAUnitTest::testAsymmetricEncryption_data() 0155 { 0156 QTest::addColumn<QCA::EncryptionAlgorithm>("algorithm"); 0157 QTest::addColumn<bool>("errorOnFailure"); 0158 QTest::addColumn<bool>("encryptWithPrivate"); 0159 0160 QTest::newRow("PKCS1v15") << QCA::EME_PKCS1v15 << false << true; 0161 QTest::newRow("PKCS1_OAEP") << QCA::EME_PKCS1_OAEP << true << false; 0162 } 0163 0164 void RSAUnitTest::testAsymmetricEncryption() 0165 { 0166 if (!QCA::isSupported("pkey", QStringLiteral("qca-ossl")) || 0167 !QCA::PKey::supportedTypes(QStringLiteral("qca-ossl")).contains(QCA::PKey::RSA) || 0168 !QCA::PKey::supportedIOTypes(QStringLiteral("qca-ossl")).contains(QCA::PKey::RSA)) { 0169 QWARN("RSA not supported"); 0170 QSKIP("RSA not supported. skipping"); 0171 } 0172 0173 QFETCH(QCA::EncryptionAlgorithm, algorithm); 0174 QFETCH(bool, errorOnFailure); 0175 QFETCH(bool, encryptWithPrivate); 0176 0177 QCA::RSAPrivateKey rsaPrivKey1 = QCA::KeyGenerator().createRSA(512, 65537, QStringLiteral("qca-ossl")).toRSA(); 0178 QCA::RSAPublicKey rsaPubKey1 = rsaPrivKey1.toPublicKey().toRSA(); 0179 0180 QCA::RSAPrivateKey rsaPrivKey2 = QCA::KeyGenerator().createRSA(512, 65537, QStringLiteral("qca-ossl")).toRSA(); 0181 // QCA::RSAPublicKey rsaPubKey2 = rsaPrivKey2.toPublicKey().toRSA(); 0182 0183 const QCA::SecureArray clearText = "Hello World !"; 0184 QCA::SecureArray testText; 0185 QCA::SecureArray cipherText; 0186 0187 // Test keys #1: Enc with public, dec with private 0188 QVERIFY(rsaPubKey1.maximumEncryptSize(algorithm) >= clearText.size()); 0189 cipherText = rsaPubKey1.encrypt(clearText, algorithm); 0190 QVERIFY(rsaPrivKey1.decrypt(cipherText, &testText, algorithm)); 0191 QCOMPARE(clearText, testText); 0192 testText.clear(); 0193 // --- 0194 0195 // Test keys #2 to decipher key #1 0196 const bool success = rsaPrivKey2.decrypt(cipherText, &testText, algorithm); 0197 if (errorOnFailure) { 0198 QVERIFY(!success); 0199 QVERIFY(testText.isEmpty()); 0200 } else { 0201 QVERIFY(testText != clearText); 0202 testText.clear(); 0203 } 0204 // --- 0205 0206 if (encryptWithPrivate) { 0207 // Test keys #2: Enc with private, dec with public 0208 cipherText.clear(); 0209 QVERIFY(rsaPrivKey1.maximumEncryptSize(algorithm) >= clearText.size()); 0210 cipherText = rsaPrivKey1.encrypt(clearText, algorithm); 0211 QVERIFY(rsaPubKey1.decrypt(cipherText, &testText, algorithm)); 0212 QCOMPARE(clearText, testText); 0213 testText.clear(); 0214 // --- 0215 } 0216 } 0217 0218 QTEST_MAIN(RSAUnitTest) 0219 0220 #include "rsaunittest.moc"