00001 /* 00002 Copyright (C) 2003 Justin Karneges <justin@affinix.com> 00003 Copyright (C) 2005-2006 Brad Hards <bradh@frogmouth.net> 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy 00006 of this software and associated documentation files (the "Software"), to deal 00007 in the Software without restriction, including without limitation the rights 00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 copies of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00019 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00021 */ 00022 00023 00024 #include <QtCrypto> 00025 00026 #include <QCoreApplication> 00027 #include <QDebug> 00028 00029 int main(int argc, char** argv) 00030 { 00031 // the Initializer object sets things up, and 00032 // also does cleanup when it goes out of scope 00033 QCA::Initializer init; 00034 00035 QCoreApplication app(argc, argv); 00036 00037 // We need to ensure that we have certificate handling support 00038 if ( !QCA::isSupported( "cert" ) ) { 00039 qWarning() << "Sorry, no PKI certificate support"; 00040 return 1; 00041 } 00042 00043 // Read in a public key cert 00044 // you could also build this using the fromPEMFile() method 00045 QCA::Certificate pubCert( "User.pem" ); 00046 if ( pubCert.isNull() ) { 00047 qWarning() << "Sorry, could not import public key certificate"; 00048 return 1; 00049 } 00050 // We are building the certificate into a SecureMessageKey object, via a 00051 // CertificateChain 00052 QCA::SecureMessageKey secMsgKey; 00053 QCA::CertificateChain chain; 00054 chain += pubCert; 00055 secMsgKey.setX509CertificateChain( chain ); 00056 00057 // build up a SecureMessage object, based on our public key certificate 00058 if ( !QCA::isSupported( "cms" ) ) { 00059 qWarning() << "Sorry, no CMS support"; 00060 return 1; 00061 } 00062 QCA::CMS cms; 00063 QCA::SecureMessage msg(&cms); 00064 msg.setRecipient(secMsgKey); 00065 00066 // Some plain text - we use the first command line argument if provided 00067 QByteArray plainText = (argc >= 2) ? argv[1] : "What do ya want for nuthin'"; 00068 00069 // Now use the SecureMessage object to encrypt the plain text. 00070 msg.startEncrypt(); 00071 msg.update(plainText); 00072 msg.end(); 00073 // I think it is reasonable to wait for 1 second for this 00074 msg.waitForFinished(1000); 00075 00076 // check to see if it worked 00077 if(!msg.success()) 00078 { 00079 qWarning() << "Error encrypting: " << msg.errorCode(); 00080 return 1; 00081 } 00082 00083 // get the result 00084 QByteArray cipherText = msg.read(); 00085 QCA::Base64 enc; 00086 qDebug() << "'" << plainText.data() << "' encrypts to (in base 64): "; 00087 qDebug() << enc.arrayToString( cipherText ); 00088 qDebug() << "Message uses" << msg.hashName() << "hashing algorithm"; 00089 qDebug(); 00090 00091 // Show we can decrypt it with the private key 00092 00093 // Read in a private key 00094 QCA::PrivateKey privKey; 00095 QCA::ConvertResult convRes; 00096 QCA::SecureArray passPhrase = "start"; 00097 privKey = QCA::PrivateKey::fromPEMFile( "Userkey.pem", passPhrase, &convRes ); 00098 if ( convRes != QCA::ConvertGood ) { 00099 qWarning() << "Sorry, could not import Private Key"; 00100 return 1; 00101 } 00102 00103 QCA::SecureMessageKey secMsgKey2; 00104 // needed? 00105 secMsgKey2.setX509CertificateChain( chain ); 00106 secMsgKey2.setX509PrivateKey(privKey); 00107 QCA::SecureMessageKeyList privKeyList; 00108 privKeyList += secMsgKey2; 00109 00110 // build up a SecureMessage object, based on the private key 00111 // you could re-use the existing QCA::CMS object (cms), but 00112 // this example simulates encryption and one end, and decryption 00113 // at the other 00114 QCA::CMS anotherCms; 00115 anotherCms.setPrivateKeys( privKeyList ); 00116 00117 QCA::SecureMessage msg2( &anotherCms ); 00118 00119 msg2.startDecrypt(); 00120 msg2.update( cipherText ); 00121 msg2.end(); 00122 00123 // I think it is reasonable to wait for 1 second for this 00124 msg2.waitForFinished(1000); 00125 00126 // check to see if it worked 00127 if(!msg2.success()) 00128 { 00129 qWarning() << "Error encrypting: " << msg2.errorCode(); 00130 return 1; 00131 } 00132 00133 QCA::SecureArray plainTextResult = msg2.read(); 00134 00135 qDebug() << enc.arrayToString( cipherText ) 00136 << " (in base 64) decrypts to: " 00137 << plainTextResult.data(); 00138 00139 if (msg2.wasSigned()) { 00140 qDebug() << "Message was signed at " 00141 << msg2.signer().timestamp(); 00142 } else { 00143 qDebug() << "Message was not signed"; 00144 } 00145 00146 qDebug() << "Message used" << msg2.hashName() << "hashing algorithm"; 00147 00148 qDebug(); 00149 00150 // Now we want to try a signature 00151 QByteArray text("Got your message"); 00152 00153 // Re-use the CMS and SecureMessageKeyList objects from the decrypt... 00154 QCA::SecureMessage signing( &anotherCms ); 00155 signing.setSigners(privKeyList); 00156 00157 signing.startSign(QCA::SecureMessage::Detached); 00158 signing.update(text); 00159 signing.end(); 00160 00161 // I think it is reasonable to wait for 1 second for this 00162 signing.waitForFinished(1000); 00163 00164 // check to see if it worked 00165 if(!signing.success()) 00166 { 00167 qWarning() << "Error signing: " << signing.errorCode(); 00168 return 1; 00169 } 00170 00171 // get the result 00172 QByteArray signature = signing.signature(); 00173 00174 qDebug() << "'" << text.data() << "', signature (converted to base 64), is: "; 00175 qDebug() << enc.arrayToString( signature ); 00176 qDebug() << "Message uses" << signing.hashName() << "hashing algorithm"; 00177 qDebug(); 00178 00179 00180 // Now we go back to the first CMS, and re-use that. 00181 QCA::SecureMessage verifying( &cms ); 00182 00183 // You have to pass the signature to startVerify(), 00184 // and the message to update() 00185 verifying.startVerify(signature); 00186 verifying.update(text); 00187 verifying.end(); 00188 00189 verifying.waitForFinished(1000); 00190 00191 // check to see if it worked 00192 if(!verifying.success()) 00193 { 00194 qWarning() << "Error verifying: " << verifying.errorCode(); 00195 return 1; 00196 } 00197 00198 QCA::SecureMessageSignature sign; 00199 sign = verifying.signer(); 00200 // todo: dump some data out about the signer 00201 00202 if(verifying.verifySuccess()) 00203 { 00204 qDebug() << "Message verified"; 00205 } else { 00206 qDebug() << "Message failed to verify:" << verifying.errorCode(); 00207 } 00208 00209 return 0; 00210 } 00211