File indexing completed on 2024-10-13 10:11: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 }