File indexing completed on 2024-10-13 12:40:11

0001 /*
0002  Copyright (C) 2003 Justin Karneges <justin@affinix.com>
0003  Copyright (C) 2005-2006 Brad Hards <bradh@frogmouth.net>
0004 
0005  Permission is hereby granted, free of charge, to any person obtaining a copy
0006  of this software and associated documentation files (the "Software"), to deal
0007  in the Software without restriction, including without limitation the rights
0008  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0009  copies of the Software, and to permit persons to whom the Software is
0010  furnished to do so, subject to the following conditions:
0011 
0012  The above copyright notice and this permission notice shall be included in
0013  all copies or substantial portions of the Software.
0014 
0015  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
0018  AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
0019  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0020  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0021 */
0022 
0023 #include <QtCrypto>
0024 
0025 #include <QCoreApplication>
0026 #include <QDebug>
0027 
0028 #ifdef QT_STATICPLUGIN
0029 #include "import_plugins.h"
0030 #endif
0031 
0032 int main(int argc, char **argv)
0033 {
0034     // the Initializer object sets things up, and
0035     // also does cleanup when it goes out of scope
0036     QCA::Initializer init;
0037 
0038     QCoreApplication app(argc, argv);
0039 
0040     // We need to ensure that we have certificate handling support
0041     if (!QCA::isSupported("cert")) {
0042         qWarning() << "Sorry, no PKI certificate support";
0043         return 1;
0044     }
0045 
0046     // Read in a public key cert
0047     // you could also build this using the fromPEMFile() method
0048     QCA::Certificate pubCert(QStringLiteral("User.pem"));
0049     if (pubCert.isNull()) {
0050         qWarning() << "Sorry, could not import public key certificate";
0051         return 1;
0052     }
0053     // We are building the certificate into a SecureMessageKey object, via a
0054     // CertificateChain
0055     QCA::SecureMessageKey secMsgKey;
0056     QCA::CertificateChain chain;
0057     chain += pubCert;
0058     secMsgKey.setX509CertificateChain(chain);
0059 
0060     // build up a SecureMessage object, based on our public key certificate
0061     if (!QCA::isSupported("cms")) {
0062         qWarning() << "Sorry, no CMS support";
0063         return 1;
0064     }
0065     QCA::CMS           cms;
0066     QCA::SecureMessage msg(&cms);
0067     msg.setRecipient(secMsgKey);
0068 
0069     // Some plain text - we use the first command line argument if provided
0070     QByteArray plainText = (argc >= 2) ? argv[1] : "What do ya want for nuthin'";
0071 
0072     // Now use the SecureMessage object to encrypt the plain text.
0073     msg.startEncrypt();
0074     msg.update(plainText);
0075     msg.end();
0076     // I think it is reasonable to wait for 1 second for this
0077     msg.waitForFinished(1000);
0078 
0079     // check to see if it worked
0080     if (!msg.success()) {
0081         qWarning() << "Error encrypting: " << msg.errorCode();
0082         return 1;
0083     }
0084 
0085     // get the result
0086     QByteArray  cipherText = msg.read();
0087     QCA::Base64 enc;
0088     qDebug() << "'" << plainText.data() << "' encrypts to (in base 64): ";
0089     qDebug() << enc.arrayToString(cipherText);
0090     qDebug() << "Message uses" << msg.hashName() << "hashing algorithm";
0091     qDebug();
0092 
0093     // Show we can decrypt it with the private key
0094 
0095     // Read in a private key
0096     QCA::PrivateKey    privKey;
0097     QCA::ConvertResult convRes;
0098     QCA::SecureArray   passPhrase = "start";
0099     privKey                       = QCA::PrivateKey::fromPEMFile(QStringLiteral("Userkey.pem"), passPhrase, &convRes);
0100     if (convRes != QCA::ConvertGood) {
0101         qWarning() << "Sorry, could not import Private Key";
0102         return 1;
0103     }
0104 
0105     QCA::SecureMessageKey secMsgKey2;
0106     // needed?
0107     secMsgKey2.setX509CertificateChain(chain);
0108     secMsgKey2.setX509PrivateKey(privKey);
0109     QCA::SecureMessageKeyList privKeyList;
0110     privKeyList += secMsgKey2;
0111 
0112     // build up a SecureMessage object, based on the private key
0113     // you could re-use the existing QCA::CMS object (cms), but
0114     // this example simulates encryption and one end, and decryption
0115     // at the other
0116     QCA::CMS anotherCms;
0117     anotherCms.setPrivateKeys(privKeyList);
0118 
0119     QCA::SecureMessage msg2(&anotherCms);
0120 
0121     msg2.startDecrypt();
0122     msg2.update(cipherText);
0123     msg2.end();
0124 
0125     // I think it is reasonable to wait for 1 second for this
0126     msg2.waitForFinished(1000);
0127 
0128     // check to see if it worked
0129     if (!msg2.success()) {
0130         qWarning() << "Error encrypting: " << msg2.errorCode();
0131         return 1;
0132     }
0133 
0134     QCA::SecureArray plainTextResult = msg2.read();
0135 
0136     qDebug() << enc.arrayToString(cipherText) << " (in base 64) decrypts to: " << plainTextResult.data();
0137 
0138     if (msg2.wasSigned()) {
0139         qDebug() << "Message was signed at " << msg2.signer().timestamp();
0140     } else {
0141         qDebug() << "Message was not signed";
0142     }
0143 
0144     qDebug() << "Message used" << msg2.hashName() << "hashing algorithm";
0145 
0146     qDebug();
0147 
0148     // Now we want to try a signature
0149     QByteArray text("Got your message");
0150 
0151     // Re-use the CMS and SecureMessageKeyList objects from the decrypt...
0152     QCA::SecureMessage signing(&anotherCms);
0153     signing.setSigners(privKeyList);
0154 
0155     signing.startSign(QCA::SecureMessage::Detached);
0156     signing.update(text);
0157     signing.end();
0158 
0159     // I think it is reasonable to wait for 1 second for this
0160     signing.waitForFinished(1000);
0161 
0162     // check to see if it worked
0163     if (!signing.success()) {
0164         qWarning() << "Error signing: " << signing.errorCode();
0165         return 1;
0166     }
0167 
0168     // get the result
0169     QByteArray signature = signing.signature();
0170 
0171     qDebug() << "'" << text.data() << "', signature (converted to base 64), is: ";
0172     qDebug() << enc.arrayToString(signature);
0173     qDebug() << "Message uses" << signing.hashName() << "hashing algorithm";
0174     qDebug();
0175 
0176     // Now we go back to the first CMS, and re-use that.
0177     QCA::SecureMessage verifying(&cms);
0178 
0179     // You have to pass the signature to startVerify(),
0180     // and the message to update()
0181     verifying.startVerify(signature);
0182     verifying.update(text);
0183     verifying.end();
0184 
0185     verifying.waitForFinished(1000);
0186 
0187     // check to see if it worked
0188     if (!verifying.success()) {
0189         qWarning() << "Error verifying: " << verifying.errorCode();
0190         return 1;
0191     }
0192 
0193     QCA::SecureMessageSignature sign;
0194     sign = verifying.signer();
0195     // todo: dump some data out about the signer
0196 
0197     if (verifying.verifySuccess()) {
0198         qDebug() << "Message verified";
0199     } else {
0200         qDebug() << "Message failed to verify:" << verifying.errorCode();
0201     }
0202 
0203     return 0;
0204 }