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 std::cout << "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 std::cout << "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