rsatest.cpp

The code below shows some of the capabilities for how to use RSA. This example also shows how to export and import a key to a file, using PEM encoding.

00001 /*
00002  Copyright (C) 2003 Justin Karneges <justin@affinix.com>
00003  Copyright (C) 2005 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 #include <QtCrypto>
00024 #include <QCoreApplication>
00025 
00026 #include <iostream>
00027 
00028 int main(int argc, char **argv)
00029 {
00030     // The Initializer object sets things up, and also
00031     // does cleanup when it goes out of scope
00032     QCA::Initializer init;
00033 
00034     QCoreApplication app(argc, argv);
00035 
00036     // we use the first argument if provided, or
00037     // use "hello" if no arguments
00038     QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello";
00039 
00040     // We demonstrate PEM usage here, so we need to test for
00041     // supportedIOTypes, not just supportedTypes
00042     if(!QCA::isSupported("pkey") ||
00043        !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA))
00044         printf("RSA not supported!\n");
00045     else {
00046         // When creating a public / private key pair, you make the
00047         // private key, and then extract the public key component from it
00048         // Using RSA is very common, however DSA can provide equivalent
00049         // signature/verification. This example applies to DSA to the
00050         // extent that the operations work on that key type.
00051 
00052         // QCA provides KeyGenerator as a convenient source of new keys,
00053         // however you could also import an existing key instead.
00054         QCA::PrivateKey seckey = QCA::KeyGenerator().createRSA(1024);
00055         if(seckey.isNull()) {
00056             std::cout << "Failed to make private RSA key" << std::endl;
00057             return 1;
00058         }
00059 
00060         QCA::PublicKey pubkey = seckey.toPublicKey();
00061 
00062         // check if the key can encrypt
00063         if(!pubkey.canEncrypt()) {
00064             std::cout << "Error: this kind of key cannot encrypt" << std::endl;
00065             return 1;
00066         }
00067 
00068         // encrypt some data - note that only the public key is required
00069         // you must also choose the algorithm to be used
00070         QCA::SecureArray result = pubkey.encrypt(arg, QCA::EME_PKCS1_OAEP);
00071         if(result.isEmpty()) {
00072             std::cout << "Error encrypting" << std::endl;
00073             return 1;
00074         }
00075 
00076         // output the encrypted data
00077         QString rstr = QCA::arrayToHex(result.toByteArray());
00078         std::cout << "\"" << arg.data() << "\" encrypted with RSA is \"";
00079         std::cout << qPrintable(rstr) << "\"" << std::endl;
00080 
00081         // save the private key - in a real example, make sure this goes
00082         // somewhere secure and has a good pass phrase
00083         // You can use the same technique with the public key too.
00084         QCA::SecureArray passPhrase = "pass phrase";
00085         seckey.toPEMFile("keyprivate.pem", passPhrase);
00086 
00087         // Read that key back in, checking if the read succeeded
00088         QCA::ConvertResult conversionResult;
00089         QCA::PrivateKey privateKey = QCA::PrivateKey::fromPEMFile( "keyprivate.pem",
00090                                                                    passPhrase,
00091                                                                    &conversionResult);
00092         if (! (QCA::ConvertGood == conversionResult) ) {
00093             std::cout << "Private key read failed" << std::endl;
00094         }
00095 
00096         // now decrypt that encrypted data using the private key that
00097         // we read in. The algorithm is the same.
00098         QCA::SecureArray decrypt;
00099         if(0 == privateKey.decrypt(result, &decrypt, QCA::EME_PKCS1_OAEP)) {
00100             printf("Error decrypting.\n");
00101             return 1;
00102         }
00103 
00104         // output the resulting decrypted string
00105         std::cout << "\"" << qPrintable(rstr) << "\" decrypted with RSA is \"";
00106         std::cout << decrypt.data() << "\"" << std::endl;
00107 
00108 
00109         // Some private keys can also be used for producing signatures
00110         if(!privateKey.canSign()) {
00111             std::cout << "Error: this kind of key cannot sign" << std::endl;
00112             return 1;
00113         }
00114         privateKey.startSign( QCA::EMSA3_MD5 );
00115         privateKey.update( arg ); // just reuse the same message
00116         QByteArray argSig = privateKey.signature();
00117 
00118         // instead of using the startSign(), update(), signature() calls,
00119         // you may be better doing the whole thing in one go, using the
00120         // signMessage call. Of course you need the whole message in one
00121         // hit, which may or may not be a problem
00122 
00123         // output the resulting signature
00124         rstr = QCA::arrayToHex(argSig);
00125         std::cout << "Signature for \"" << arg.data() << "\" using RSA, is ";
00126         std::cout << "\"" << qPrintable( rstr ) << "\"" << std::endl;
00127 
00128         // to check a signature, we must check that the key is
00129         // appropriate
00130         if(pubkey.canVerify()) {
00131             pubkey.startVerify( QCA::EMSA3_MD5 );
00132             pubkey.update( arg );
00133             if ( pubkey.validSignature( argSig ) ) {
00134                 std::cout << "Signature is valid" << std::endl;
00135             } else {
00136                 std::cout << "Bad signature" << std::endl;
00137             }
00138         }
00139 
00140         // We can also do the verification in a single step if we
00141         // have all the message
00142         if ( pubkey.canVerify() &&
00143              pubkey.verifyMessage( arg, argSig, QCA::EMSA3_MD5 ) ) {
00144             std::cout << "Signature is valid" << std::endl;
00145         } else {
00146             std::cout << "Signature could not be verified" << std::endl;
00147         }
00148 
00149     }
00150 
00151     return 0;
00152 }
00153 

Generated on Fri Jul 6 13:22:42 2007 for Qt Cryptographic Architecture by  doxygen 1.4.6