1 /*
2  Copyright (C) 2003 Justin Karneges <justin@affinix.com>
3  Copyright (C) 2005-2006 Brad Hards <bradh@frogmouth.net>
4 
5  Permission is hereby granted, free of charge, to any person obtaining a copy
6  of this software and associated documentation files (the "Software"), to deal
7  in the Software without restriction, including without limitation the rights
8  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  copies of the Software, and to permit persons to whom the Software is
10  furnished to do so, subject to the following conditions:
11 
12  The above copyright notice and this permission notice shall be included in
13  all copies or substantial portions of the Software.
14 
15  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18  AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22 
23 #include <QtCrypto>
24 
25 #include <QCoreApplication>
26 #include <QDebug>
27 
28 #ifdef QT_STATICPLUGIN
29 #include "import_plugins.h"
30 #endif
31 
main(int argc,char ** argv)32 int main(int argc, char **argv)
33 {
34     // the Initializer object sets things up, and
35     // also does cleanup when it goes out of scope
36     QCA::Initializer init;
37 
38     QCoreApplication app(argc, argv);
39 
40     // We need to ensure that we have certificate handling support
41     if (!QCA::isSupported("cert")) {
42         qWarning() << "Sorry, no PKI certificate support";
43         return 1;
44     }
45 
46     // Read in a public key cert
47     // you could also build this using the fromPEMFile() method
48     QCA::Certificate pubCert(QStringLiteral("User.pem"));
49     if (pubCert.isNull()) {
50         qWarning() << "Sorry, could not import public key certificate";
51         return 1;
52     }
53     // We are building the certificate into a SecureMessageKey object, via a
54     // CertificateChain
55     QCA::SecureMessageKey secMsgKey;
56     QCA::CertificateChain chain;
57     chain += pubCert;
58     secMsgKey.setX509CertificateChain(chain);
59 
60     // build up a SecureMessage object, based on our public key certificate
61     if (!QCA::isSupported("cms")) {
62         qWarning() << "Sorry, no CMS support";
63         return 1;
64     }
65     QCA::CMS           cms;
66     QCA::SecureMessage msg(&cms);
67     msg.setRecipient(secMsgKey);
68 
69     // Some plain text - we use the first command line argument if provided
70     QByteArray plainText = (argc >= 2) ? argv[1] : "What do ya want for nuthin'";
71 
72     // Now use the SecureMessage object to encrypt the plain text.
73     msg.startEncrypt();
74     msg.update(plainText);
75     msg.end();
76     // I think it is reasonable to wait for 1 second for this
77     msg.waitForFinished(1000);
78 
79     // check to see if it worked
80     if (!msg.success()) {
81         qWarning() << "Error encrypting: " << msg.errorCode();
82         return 1;
83     }
84 
85     // get the result
86     QByteArray  cipherText = msg.read();
87     QCA::Base64 enc;
88     qDebug() << "'" << plainText.data() << "' encrypts to (in base 64): ";
89     qDebug() << enc.arrayToString(cipherText);
90     qDebug() << "Message uses" << msg.hashName() << "hashing algorithm";
91     qDebug();
92 
93     // Show we can decrypt it with the private key
94 
95     // Read in a private key
96     QCA::PrivateKey    privKey;
97     QCA::ConvertResult convRes;
98     QCA::SecureArray   passPhrase = "start";
99     privKey                       = QCA::PrivateKey::fromPEMFile(QStringLiteral("Userkey.pem"), passPhrase, &convRes);
100     if (convRes != QCA::ConvertGood) {
101         qWarning() << "Sorry, could not import Private Key";
102         return 1;
103     }
104 
105     QCA::SecureMessageKey secMsgKey2;
106     // needed?
107     secMsgKey2.setX509CertificateChain(chain);
108     secMsgKey2.setX509PrivateKey(privKey);
109     QCA::SecureMessageKeyList privKeyList;
110     privKeyList += secMsgKey2;
111 
112     // build up a SecureMessage object, based on the private key
113     // you could re-use the existing QCA::CMS object (cms), but
114     // this example simulates encryption and one end, and decryption
115     // at the other
116     QCA::CMS anotherCms;
117     anotherCms.setPrivateKeys(privKeyList);
118 
119     QCA::SecureMessage msg2(&anotherCms);
120 
121     msg2.startDecrypt();
122     msg2.update(cipherText);
123     msg2.end();
124 
125     // I think it is reasonable to wait for 1 second for this
126     msg2.waitForFinished(1000);
127 
128     // check to see if it worked
129     if (!msg2.success()) {
130         qWarning() << "Error encrypting: " << msg2.errorCode();
131         return 1;
132     }
133 
134     QCA::SecureArray plainTextResult = msg2.read();
135 
136     qDebug() << enc.arrayToString(cipherText) << " (in base 64) decrypts to: " << plainTextResult.data();
137 
138     if (msg2.wasSigned()) {
139         qDebug() << "Message was signed at " << msg2.signer().timestamp();
140     } else {
141         qDebug() << "Message was not signed";
142     }
143 
144     qDebug() << "Message used" << msg2.hashName() << "hashing algorithm";
145 
146     qDebug();
147 
148     // Now we want to try a signature
149     QByteArray text("Got your message");
150 
151     // Re-use the CMS and SecureMessageKeyList objects from the decrypt...
152     QCA::SecureMessage signing(&anotherCms);
153     signing.setSigners(privKeyList);
154 
155     signing.startSign(QCA::SecureMessage::Detached);
156     signing.update(text);
157     signing.end();
158 
159     // I think it is reasonable to wait for 1 second for this
160     signing.waitForFinished(1000);
161 
162     // check to see if it worked
163     if (!signing.success()) {
164         qWarning() << "Error signing: " << signing.errorCode();
165         return 1;
166     }
167 
168     // get the result
169     QByteArray signature = signing.signature();
170 
171     qDebug() << "'" << text.data() << "', signature (converted to base 64), is: ";
172     qDebug() << enc.arrayToString(signature);
173     qDebug() << "Message uses" << signing.hashName() << "hashing algorithm";
174     qDebug();
175 
176     // Now we go back to the first CMS, and re-use that.
177     QCA::SecureMessage verifying(&cms);
178 
179     // You have to pass the signature to startVerify(),
180     // and the message to update()
181     verifying.startVerify(signature);
182     verifying.update(text);
183     verifying.end();
184 
185     verifying.waitForFinished(1000);
186 
187     // check to see if it worked
188     if (!verifying.success()) {
189         qWarning() << "Error verifying: " << verifying.errorCode();
190         return 1;
191     }
192 
193     QCA::SecureMessageSignature sign;
194     sign = verifying.signer();
195     // todo: dump some data out about the signer
196 
197     if (verifying.verifySuccess()) {
198         qDebug() << "Message verified";
199     } else {
200         qDebug() << "Message failed to verify:" << verifying.errorCode();
201     }
202 
203     return 0;
204 }
205