/** * Copyright (C) 2005-2006 Brad Hards * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #ifdef QT_STATICPLUGIN #include "import_plugins.h" #endif class RSAUnitTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void testrsa(); void testAsymmetricEncryption_data(); void testAsymmetricEncryption(); private: QCA::Initializer *m_init; }; void RSAUnitTest::initTestCase() { m_init = new QCA::Initializer; } void RSAUnitTest::cleanupTestCase() { delete m_init; } void RSAUnitTest::testrsa() { QStringList providersToTest; providersToTest.append(QStringLiteral("qca-ossl")); // providersToTest.append("qca-gcrypt"); foreach (const QString provider, providersToTest) { if (!QCA::isSupported("pkey", provider) || !QCA::PKey::supportedTypes(provider).contains(QCA::PKey::RSA) || !QCA::PKey::supportedIOTypes(provider).contains(QCA::PKey::RSA)) QWARN((QStringLiteral("RSA not supported for ") + provider).toLocal8Bit().constData()); else { QCA::KeyGenerator keygen; QCOMPARE(keygen.isBusy(), false); QCOMPARE(keygen.blockingEnabled(), true); QList keySizes; keySizes << 512 << 1024 << 768 << 2048; foreach (int keysize, keySizes) { QCA::PrivateKey rsaKey = keygen.createRSA(keysize, 65537, provider); QCOMPARE(rsaKey.isNull(), false); QCOMPARE(rsaKey.isRSA(), true); QCOMPARE(rsaKey.isDSA(), false); QCOMPARE(rsaKey.isDH(), false); QCOMPARE(rsaKey.isPrivate(), true); QCOMPARE(rsaKey.isPublic(), false); QCOMPARE(rsaKey.canSign(), true); QCOMPARE(rsaKey.canDecrypt(), true); QCOMPARE(rsaKey.canEncrypt(), true); QCA::RSAPrivateKey rsaPrivKey = rsaKey.toRSA(); QCOMPARE(rsaPrivKey.bitSize(), keysize); QString rsaPEM = rsaKey.toPEM(); QCOMPARE(rsaPEM.isEmpty(), false); QCA::ConvertResult checkResult; QCA::PrivateKey fromPEMkey = QCA::PrivateKey::fromPEM(rsaPEM, QCA::SecureArray(), &checkResult); QCOMPARE(checkResult, QCA::ConvertGood); QCOMPARE(fromPEMkey.isNull(), false); QCOMPARE(fromPEMkey.isRSA(), true); QCOMPARE(fromPEMkey.isDSA(), false); QCOMPARE(fromPEMkey.isDH(), false); QCOMPARE(fromPEMkey.isPrivate(), true); QCOMPARE(fromPEMkey.isPublic(), false); QCOMPARE(rsaKey == fromPEMkey, true); QCA::SecureArray rsaDER = rsaKey.toDER(QCA::SecureArray("foo")); QCOMPARE(rsaDER.isEmpty(), false); QCA::PrivateKey fromDERkey = QCA::PrivateKey::fromDER(rsaDER, QCA::SecureArray("foo"), &checkResult); QCOMPARE(checkResult, QCA::ConvertGood); QCOMPARE(fromDERkey.isNull(), false); QCOMPARE(fromDERkey.isRSA(), true); QCOMPARE(fromDERkey.isDSA(), false); QCOMPARE(fromDERkey.isDH(), false); QCOMPARE(fromDERkey.isPrivate(), true); QCOMPARE(fromDERkey.isPublic(), false); QCOMPARE(rsaKey == fromDERkey, true); // same test, without passphrase rsaDER = rsaKey.toDER(); QCOMPARE(rsaDER.isEmpty(), false); fromDERkey = QCA::PrivateKey::fromDER(rsaDER, QCA::SecureArray(), &checkResult); QCOMPARE(checkResult, QCA::ConvertGood); QCOMPARE(fromDERkey.isNull(), false); QCOMPARE(fromDERkey.isRSA(), true); QCOMPARE(fromDERkey.isDSA(), false); QCOMPARE(fromDERkey.isDH(), false); QCOMPARE(fromDERkey.isPrivate(), true); QCOMPARE(fromDERkey.isPublic(), false); QCOMPARE(rsaKey == fromDERkey, true); QCA::PublicKey pubKey = rsaKey.toPublicKey(); QCOMPARE(pubKey.isNull(), false); QCOMPARE(pubKey.isRSA(), true); QCOMPARE(pubKey.isDSA(), false); QCOMPARE(pubKey.isDH(), false); QCOMPARE(pubKey.isPrivate(), false); QCOMPARE(pubKey.isPublic(), true); QCA::RSAPublicKey RSApubKey = pubKey.toRSA(); QCOMPARE(RSApubKey.e(), QCA::BigInteger(65537)); QCOMPARE(RSApubKey.isNull(), false); QCOMPARE(RSApubKey.isRSA(), true); QCOMPARE(RSApubKey.isDSA(), false); QCOMPARE(RSApubKey.isDH(), false); QCOMPARE(RSApubKey.isPrivate(), false); QCOMPARE(RSApubKey.isPublic(), true); } } } } Q_DECLARE_METATYPE(QCA::EncryptionAlgorithm) void RSAUnitTest::testAsymmetricEncryption_data() { QTest::addColumn("algorithm"); QTest::addColumn("errorOnFailure"); QTest::addColumn("encryptWithPrivate"); QTest::newRow("PKCS1v15") << QCA::EME_PKCS1v15 << false << true; QTest::newRow("PKCS1_OAEP") << QCA::EME_PKCS1_OAEP << true << false; } void RSAUnitTest::testAsymmetricEncryption() { if (!QCA::isSupported("pkey", QStringLiteral("qca-ossl")) || !QCA::PKey::supportedTypes(QStringLiteral("qca-ossl")).contains(QCA::PKey::RSA) || !QCA::PKey::supportedIOTypes(QStringLiteral("qca-ossl")).contains(QCA::PKey::RSA)) { QWARN("RSA not supported"); QSKIP("RSA not supported. skipping"); } QFETCH(QCA::EncryptionAlgorithm, algorithm); QFETCH(bool, errorOnFailure); QFETCH(bool, encryptWithPrivate); QCA::RSAPrivateKey rsaPrivKey1 = QCA::KeyGenerator().createRSA(512, 65537, QStringLiteral("qca-ossl")).toRSA(); QCA::RSAPublicKey rsaPubKey1 = rsaPrivKey1.toPublicKey().toRSA(); QCA::RSAPrivateKey rsaPrivKey2 = QCA::KeyGenerator().createRSA(512, 65537, QStringLiteral("qca-ossl")).toRSA(); // QCA::RSAPublicKey rsaPubKey2 = rsaPrivKey2.toPublicKey().toRSA(); const QCA::SecureArray clearText = "Hello World !"; QCA::SecureArray testText; QCA::SecureArray cipherText; // Test keys #1: Enc with public, dec with private QVERIFY(rsaPubKey1.maximumEncryptSize(algorithm) >= clearText.size()); cipherText = rsaPubKey1.encrypt(clearText, algorithm); QVERIFY(rsaPrivKey1.decrypt(cipherText, &testText, algorithm)); QCOMPARE(clearText, testText); testText.clear(); // --- // Test keys #2 to decipher key #1 const bool success = rsaPrivKey2.decrypt(cipherText, &testText, algorithm); if (errorOnFailure) { QVERIFY(!success); QVERIFY(testText.isEmpty()); } else { QVERIFY(testText != clearText); testText.clear(); } // --- if (encryptWithPrivate) { // Test keys #2: Enc with private, dec with public cipherText.clear(); QVERIFY(rsaPrivKey1.maximumEncryptSize(algorithm) >= clearText.size()); cipherText = rsaPrivKey1.encrypt(clearText, algorithm); QVERIFY(rsaPubKey1.decrypt(cipherText, &testText, algorithm)); QCOMPARE(clearText, testText); testText.clear(); // --- } } QTEST_MAIN(RSAUnitTest) #include "rsaunittest.moc"