1/**
2 * Copyright (C) 2005-2006 Brad Hards <bradh@frogmouth.net>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <QtCrypto>
27#include <QtTest/QtTest>
28
29#ifdef QT_STATICPLUGIN
30#include "import_plugins.h"
31#endif
32
33class RSAUnitTest : public QObject
34{
35 Q_OBJECT
36
37private Q_SLOTS:
38 void initTestCase();
39 void cleanupTestCase();
40 void testrsa();
41 void testAsymmetricEncryption_data();
42 void testAsymmetricEncryption();
43
44private:
45 QCA::Initializer *m_init;
46};
47
48void RSAUnitTest::initTestCase()
49{
50 m_init = new QCA::Initializer;
51}
52
53void RSAUnitTest::cleanupTestCase()
54{
55 delete m_init;
56}
57
58void RSAUnitTest::testrsa()
59{
60 QStringList providersToTest;
61 providersToTest.append(QStringLiteral("qca-ossl"));
62 // providersToTest.append("qca-gcrypt");
63
64 foreach (const QString provider, providersToTest) {
65 if (!QCA::isSupported(features: "pkey", provider) || !QCA::PKey::supportedTypes(provider).contains(t: QCA::PKey::RSA) ||
66 !QCA::PKey::supportedIOTypes(provider).contains(t: QCA::PKey::RSA))
67 QWARN((QStringLiteral("RSA not supported for ") + provider).toLocal8Bit().constData());
68 else {
69 QCA::KeyGenerator keygen;
70 QCOMPARE(keygen.isBusy(), false);
71 QCOMPARE(keygen.blockingEnabled(), true);
72
73 QList<int> keySizes;
74 keySizes << 512 << 1024 << 768 << 2048;
75 foreach (int keysize, keySizes) {
76 QCA::PrivateKey rsaKey = keygen.createRSA(bits: keysize, exp: 65537, provider);
77 QCOMPARE(rsaKey.isNull(), false);
78 QCOMPARE(rsaKey.isRSA(), true);
79 QCOMPARE(rsaKey.isDSA(), false);
80 QCOMPARE(rsaKey.isDH(), false);
81 QCOMPARE(rsaKey.isPrivate(), true);
82 QCOMPARE(rsaKey.isPublic(), false);
83 QCOMPARE(rsaKey.canSign(), true);
84 QCOMPARE(rsaKey.canDecrypt(), true);
85 QCOMPARE(rsaKey.canEncrypt(), true);
86
87 QCA::RSAPrivateKey rsaPrivKey = rsaKey.toRSA();
88 QCOMPARE(rsaPrivKey.bitSize(), keysize);
89
90 QString rsaPEM = rsaKey.toPEM();
91 QCOMPARE(rsaPEM.isEmpty(), false);
92
93 QCA::ConvertResult checkResult;
94 QCA::PrivateKey fromPEMkey = QCA::PrivateKey::fromPEM(s: rsaPEM, passphrase: QCA::SecureArray(), result: &checkResult);
95 QCOMPARE(checkResult, QCA::ConvertGood);
96 QCOMPARE(fromPEMkey.isNull(), false);
97 QCOMPARE(fromPEMkey.isRSA(), true);
98 QCOMPARE(fromPEMkey.isDSA(), false);
99 QCOMPARE(fromPEMkey.isDH(), false);
100 QCOMPARE(fromPEMkey.isPrivate(), true);
101 QCOMPARE(fromPEMkey.isPublic(), false);
102 QCOMPARE(rsaKey == fromPEMkey, true);
103
104 QCA::SecureArray rsaDER = rsaKey.toDER(passphrase: QCA::SecureArray("foo"));
105 QCOMPARE(rsaDER.isEmpty(), false);
106
107 QCA::PrivateKey fromDERkey = QCA::PrivateKey::fromDER(a: rsaDER, passphrase: QCA::SecureArray("foo"), result: &checkResult);
108 QCOMPARE(checkResult, QCA::ConvertGood);
109 QCOMPARE(fromDERkey.isNull(), false);
110 QCOMPARE(fromDERkey.isRSA(), true);
111 QCOMPARE(fromDERkey.isDSA(), false);
112 QCOMPARE(fromDERkey.isDH(), false);
113 QCOMPARE(fromDERkey.isPrivate(), true);
114 QCOMPARE(fromDERkey.isPublic(), false);
115 QCOMPARE(rsaKey == fromDERkey, true);
116
117 // same test, without passphrase
118 rsaDER = rsaKey.toDER();
119 QCOMPARE(rsaDER.isEmpty(), false);
120
121 fromDERkey = QCA::PrivateKey::fromDER(a: rsaDER, passphrase: QCA::SecureArray(), result: &checkResult);
122 QCOMPARE(checkResult, QCA::ConvertGood);
123 QCOMPARE(fromDERkey.isNull(), false);
124 QCOMPARE(fromDERkey.isRSA(), true);
125 QCOMPARE(fromDERkey.isDSA(), false);
126 QCOMPARE(fromDERkey.isDH(), false);
127 QCOMPARE(fromDERkey.isPrivate(), true);
128 QCOMPARE(fromDERkey.isPublic(), false);
129 QCOMPARE(rsaKey == fromDERkey, true);
130
131 QCA::PublicKey pubKey = rsaKey.toPublicKey();
132 QCOMPARE(pubKey.isNull(), false);
133 QCOMPARE(pubKey.isRSA(), true);
134 QCOMPARE(pubKey.isDSA(), false);
135 QCOMPARE(pubKey.isDH(), false);
136 QCOMPARE(pubKey.isPrivate(), false);
137 QCOMPARE(pubKey.isPublic(), true);
138
139 QCA::RSAPublicKey RSApubKey = pubKey.toRSA();
140 QCOMPARE(RSApubKey.e(), QCA::BigInteger(65537));
141 QCOMPARE(RSApubKey.isNull(), false);
142 QCOMPARE(RSApubKey.isRSA(), true);
143 QCOMPARE(RSApubKey.isDSA(), false);
144 QCOMPARE(RSApubKey.isDH(), false);
145 QCOMPARE(RSApubKey.isPrivate(), false);
146 QCOMPARE(RSApubKey.isPublic(), true);
147 }
148 }
149 }
150}
151
152Q_DECLARE_METATYPE(QCA::EncryptionAlgorithm)
153
154void RSAUnitTest::testAsymmetricEncryption_data()
155{
156 QTest::addColumn<QCA::EncryptionAlgorithm>(name: "algorithm");
157 QTest::addColumn<bool>(name: "errorOnFailure");
158 QTest::addColumn<bool>(name: "encryptWithPrivate");
159
160 QTest::newRow(dataTag: "PKCS1v15") << QCA::EME_PKCS1v15 << false << true;
161 QTest::newRow(dataTag: "PKCS1_OAEP") << QCA::EME_PKCS1_OAEP << true << false;
162}
163
164void RSAUnitTest::testAsymmetricEncryption()
165{
166 if (!QCA::isSupported(features: "pkey", QStringLiteral("qca-ossl")) ||
167 !QCA::PKey::supportedTypes(QStringLiteral("qca-ossl")).contains(t: QCA::PKey::RSA) ||
168 !QCA::PKey::supportedIOTypes(QStringLiteral("qca-ossl")).contains(t: QCA::PKey::RSA)) {
169 QWARN("RSA not supported");
170 QSKIP("RSA not supported. skipping");
171 }
172
173 QFETCH(QCA::EncryptionAlgorithm, algorithm);
174 QFETCH(bool, errorOnFailure);
175 QFETCH(bool, encryptWithPrivate);
176
177 QCA::RSAPrivateKey rsaPrivKey1 = QCA::KeyGenerator().createRSA(bits: 512, exp: 65537, QStringLiteral("qca-ossl")).toRSA();
178 QCA::RSAPublicKey rsaPubKey1 = rsaPrivKey1.toPublicKey().toRSA();
179
180 QCA::RSAPrivateKey rsaPrivKey2 = QCA::KeyGenerator().createRSA(bits: 512, exp: 65537, QStringLiteral("qca-ossl")).toRSA();
181 // QCA::RSAPublicKey rsaPubKey2 = rsaPrivKey2.toPublicKey().toRSA();
182
183 const QCA::SecureArray clearText = "Hello World !";
184 QCA::SecureArray testText;
185 QCA::SecureArray cipherText;
186
187 // Test keys #1: Enc with public, dec with private
188 QVERIFY(rsaPubKey1.maximumEncryptSize(algorithm) >= clearText.size());
189 cipherText = rsaPubKey1.encrypt(a: clearText, alg: algorithm);
190 QVERIFY(rsaPrivKey1.decrypt(cipherText, &testText, algorithm));
191 QCOMPARE(clearText, testText);
192 testText.clear();
193 // ---
194
195 // Test keys #2 to decipher key #1
196 const bool success = rsaPrivKey2.decrypt(in: cipherText, out: &testText, alg: algorithm);
197 if (errorOnFailure) {
198 QVERIFY(!success);
199 QVERIFY(testText.isEmpty());
200 } else {
201 QVERIFY(testText != clearText);
202 testText.clear();
203 }
204 // ---
205
206 if (encryptWithPrivate) {
207 // Test keys #2: Enc with private, dec with public
208 cipherText.clear();
209 QVERIFY(rsaPrivKey1.maximumEncryptSize(algorithm) >= clearText.size());
210 cipherText = rsaPrivKey1.encrypt(a: clearText, alg: algorithm);
211 QVERIFY(rsaPubKey1.decrypt(cipherText, &testText, algorithm));
212 QCOMPARE(clearText, testText);
213 testText.clear();
214 // ---
215 }
216}
217
218QTEST_MAIN(RSAUnitTest)
219
220#include "rsaunittest.moc"
221

source code of qca/unittest/rsaunittest/rsaunittest.cpp