File indexing completed on 2024-04-28 04:44:11

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"