QCA

cmsexample.cpp
1 /*
2  Copyright (C) 2003 Justin Karneges <[email protected]>
3  Copyright (C) 2005-2006 Brad Hards <[email protected]>
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 
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
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;
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 
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 }
ConvertResult
Return value from a format conversion.
Key for SecureMessage system.
Generic private key.
QString arrayToString(const MemoryRegion &a)
Process an array in the "forward" direction, returning a QString.
Base64 encoding / decoding
void setX509CertificateChain(const CertificateChain &c)
Set the public key part of this X.509 key.
Conversion succeeded, results should be valid.
char * data()
Pointer to the data in the secure array.
QCA_EXPORT bool isSupported(const char *features, const QString &provider=QString())
Test if a capability (algorithm) is available.
void setPrivateKeys(const SecureMessageKeyList &keys)
Set the private keys to use for the messages built using this CMS object.
QCA_EXPORT void init()
Initialise QCA.
Secure array of bytes.
Definition: qca_tools.h:316
the signature is detached
SecureMessage signature.
void setX509PrivateKey(const PrivateKey &k)
Set the private key part of this X.509 key.
A chain of related Certificates.
Definition: qca_cert.h:1225
char * data()
Convenience method for initialising and cleaning up QCA.
Definition: qca_core.h:659
Public Key (X.509) certificate.
Definition: qca_cert.h:856
static PrivateKey fromPEMFile(const QString &fileName, const SecureArray &passphrase=SecureArray(), ConvertResult *result=nullptr, const QString &provider=QString())
Import the key in Privacy Enhanced Mail (PEM) format from a file.
Class representing a secure message.
QByteArray::iterator end()
Cryptographic Message Syntax messaging system.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Sep 25 2021 23:05:35 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.