File indexing completed on 2024-04-28 04:43:39

0001 /*
0002  Copyright (C) 2003 Justin Karneges <justin@affinix.com>
0003  Copyright (C) 2005 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 <QCoreApplication>
0024 #include <QtCrypto>
0025 
0026 #include <iostream>
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 also
0035     // does cleanup when it goes out of scope
0036     QCA::Initializer init;
0037 
0038     QCoreApplication app(argc, argv);
0039 
0040     // we use the first argument if provided, or
0041     // use "hello" if no arguments
0042     QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello";
0043 
0044     // We demonstrate PEM usage here, so we need to test for
0045     // supportedIOTypes, not just supportedTypes
0046     if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA))
0047         std::cout << "RSA not supported!\n";
0048     else {
0049         // When creating a public / private key pair, you make the
0050         // private key, and then extract the public key component from it
0051         // Using RSA is very common, however DSA can provide equivalent
0052         // signature/verification. This example applies to DSA to the
0053         // extent that the operations work on that key type.
0054 
0055         // QCA provides KeyGenerator as a convenient source of new keys,
0056         // however you could also import an existing key instead.
0057         QCA::PrivateKey seckey = QCA::KeyGenerator().createRSA(1024);
0058         if (seckey.isNull()) {
0059             std::cout << "Failed to make private RSA key" << std::endl;
0060             return 1;
0061         }
0062 
0063         QCA::PublicKey pubkey = seckey.toPublicKey();
0064 
0065         // check if the key can encrypt
0066         if (!pubkey.canEncrypt()) {
0067             std::cout << "Error: this kind of key cannot encrypt" << std::endl;
0068             return 1;
0069         }
0070 
0071         // encrypt some data - note that only the public key is required
0072         // you must also choose the algorithm to be used
0073         QCA::SecureArray result = pubkey.encrypt(arg, QCA::EME_PKCS1_OAEP);
0074         if (result.isEmpty()) {
0075             std::cout << "Error encrypting" << std::endl;
0076             return 1;
0077         }
0078 
0079         // output the encrypted data
0080         QString rstr = QCA::arrayToHex(result.toByteArray());
0081         std::cout << "\"" << arg.data() << "\" encrypted with RSA is \"";
0082         std::cout << qPrintable(rstr) << "\"" << std::endl;
0083 
0084         // save the private key - in a real example, make sure this goes
0085         // somewhere secure and has a good pass phrase
0086         // You can use the same technique with the public key too.
0087         QCA::SecureArray passPhrase = "pass phrase";
0088         seckey.toPEMFile(QStringLiteral("keyprivate.pem"), passPhrase);
0089 
0090         // Read that key back in, checking if the read succeeded
0091         QCA::ConvertResult conversionResult;
0092         QCA::PrivateKey    privateKey =
0093             QCA::PrivateKey::fromPEMFile(QStringLiteral("keyprivate.pem"), passPhrase, &conversionResult);
0094         if (!(QCA::ConvertGood == conversionResult)) {
0095             std::cout << "Private key read failed" << std::endl;
0096         }
0097 
0098         // now decrypt that encrypted data using the private key that
0099         // we read in. The algorithm is the same.
0100         QCA::SecureArray decrypt;
0101         if (0 == privateKey.decrypt(result, &decrypt, QCA::EME_PKCS1_OAEP)) {
0102             std::cout << "Error decrypting.\n";
0103             return 1;
0104         }
0105 
0106         // output the resulting decrypted string
0107         std::cout << "\"" << qPrintable(rstr) << "\" decrypted with RSA is \"";
0108         std::cout << decrypt.data() << "\"" << std::endl;
0109 
0110         // Some private keys can also be used for producing signatures
0111         if (!privateKey.canSign()) {
0112             std::cout << "Error: this kind of key cannot sign" << std::endl;
0113             return 1;
0114         }
0115         privateKey.startSign(QCA::EMSA3_MD5);
0116         privateKey.update(arg); // just reuse the same message
0117         QByteArray argSig = privateKey.signature();
0118 
0119         // instead of using the startSign(), update(), signature() calls,
0120         // you may be better doing the whole thing in one go, using the
0121         // signMessage call. Of course you need the whole message in one
0122         // hit, which may or may not be a problem
0123 
0124         // output the resulting signature
0125         rstr = QCA::arrayToHex(argSig);
0126         std::cout << "Signature for \"" << arg.data() << "\" using RSA, is ";
0127         std::cout << "\"" << qPrintable(rstr) << "\"" << std::endl;
0128 
0129         // to check a signature, we must check that the key is
0130         // appropriate
0131         if (pubkey.canVerify()) {
0132             pubkey.startVerify(QCA::EMSA3_MD5);
0133             pubkey.update(arg);
0134             if (pubkey.validSignature(argSig)) {
0135                 std::cout << "Signature is valid" << std::endl;
0136             } else {
0137                 std::cout << "Bad signature" << std::endl;
0138             }
0139         }
0140 
0141         // We can also do the verification in a single step if we
0142         // have all the message
0143         if (pubkey.canVerify() && pubkey.verifyMessage(arg, argSig, QCA::EMSA3_MD5)) {
0144             std::cout << "Signature is valid" << std::endl;
0145         } else {
0146             std::cout << "Signature could not be verified" << std::endl;
0147         }
0148     }
0149 
0150     return 0;
0151 }