| 1 | /* |
| 2 | Copyright (C) 2003 Justin Karneges <justin@affinix.com> |
| 3 | Copyright (C) 2005-2006 Brad Hards <bradh@frogmouth.net> |
| 4 | |
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy |
| 6 | of this software and associated documentation files (the "Software"), to deal |
| 7 | in the Software without restriction, including without limitation the rights |
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 9 | copies of the Software, and to permit persons to whom the Software is |
| 10 | furnished to do so, subject to the following conditions: |
| 11 | |
| 12 | The above copyright notice and this permission notice shall be included in |
| 13 | all copies or substantial portions of the Software. |
| 14 | |
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 18 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 21 | */ |
| 22 | |
| 23 | // QtCrypto has the declarations for all of QCA |
| 24 | #include <QtCrypto> |
| 25 | #include <cstdio> |
| 26 | |
| 27 | #include <QCoreApplication> |
| 28 | |
| 29 | #ifdef QT_STATICPLUGIN |
| 30 | #include "import_plugins.h" |
| 31 | #endif |
| 32 | |
| 33 | int main(int argc, char **argv) |
| 34 | { |
| 35 | // the Initializer object sets things up, and |
| 36 | // also does cleanup when it goes out of scope |
| 37 | QCA::Initializer init; |
| 38 | |
| 39 | QCoreApplication app(argc, argv); |
| 40 | |
| 41 | // we use the first argument if provided, or |
| 42 | // use "hello" if no arguments |
| 43 | QCA::SecureArray arg = (argc >= 2) ? argv[1] : "hello" ; |
| 44 | |
| 45 | // AES128 testing |
| 46 | if (!QCA::isSupported(features: "aes128-cbc-pkcs7" )) |
| 47 | printf(format: "AES128-CBC not supported!\n" ); |
| 48 | else { |
| 49 | // Create a random key - you'd probably use one from another |
| 50 | // source in a real application |
| 51 | QCA::SymmetricKey key(16); |
| 52 | |
| 53 | // Create a random initialisation vector - you need this |
| 54 | // value to decrypt the resulting cipher text, but it |
| 55 | // need not be kept secret (unlike the key). |
| 56 | QCA::InitializationVector iv(16); |
| 57 | |
| 58 | // create a 128 bit AES cipher object using Cipher Block Chaining (CBC) mode |
| 59 | QCA::Cipher cipher(QStringLiteral("aes128" ), |
| 60 | QCA::Cipher::CBC, |
| 61 | // use Default padding, which is equivalent to PKCS7 for CBC |
| 62 | QCA::Cipher::DefaultPadding, |
| 63 | // this object will encrypt |
| 64 | QCA::Encode, |
| 65 | key, |
| 66 | iv); |
| 67 | |
| 68 | // we use the cipher object to encrypt the argument we passed in |
| 69 | // the result of that is returned - note that if there is less than |
| 70 | // 16 bytes (1 block), then nothing will be returned - it is buffered |
| 71 | // update() can be called as many times as required. |
| 72 | QCA::SecureArray u = cipher.update(a: arg); |
| 73 | |
| 74 | // We need to check if that update() call worked. |
| 75 | if (!cipher.ok()) { |
| 76 | printf(format: "Update failed\n" ); |
| 77 | } |
| 78 | // output the results of that stage |
| 79 | printf(format: "AES128 encryption of %s is [%s]\n" , arg.data(), qPrintable(QCA::arrayToHex(u.toByteArray()))); |
| 80 | |
| 81 | // Because we are using PKCS7 padding, we need to output the final (padded) block |
| 82 | // Note that we should always call final() even with no padding, to clean up |
| 83 | QCA::SecureArray f = cipher.final(); |
| 84 | |
| 85 | // Check if the final() call worked |
| 86 | if (!cipher.ok()) { |
| 87 | printf(format: "Final failed\n" ); |
| 88 | } |
| 89 | // and output the resulting block. The ciphertext is the results of update() |
| 90 | // and the result of final() |
| 91 | printf(format: "Final block for AES128 encryption is [0x%s]\n" , qPrintable(QCA::arrayToHex(f.toByteArray()))); |
| 92 | |
| 93 | // re-use the Cipher t decrypt. We need to use the same key and |
| 94 | // initialisation vector as in the encryption. |
| 95 | cipher.setup(dir: QCA::Decode, key, iv); |
| 96 | |
| 97 | // Build a single cipher text array. You could also call update() with |
| 98 | // each block as you receive it, if that is more useful. |
| 99 | QCA::SecureArray cipherText = u.append(a: f); |
| 100 | |
| 101 | // take that cipher text, and decrypt it |
| 102 | QCA::SecureArray plainText = cipher.update(a: cipherText); |
| 103 | |
| 104 | // check if the update() call worked |
| 105 | if (!cipher.ok()) { |
| 106 | printf(format: "Update failed\n" ); |
| 107 | } |
| 108 | |
| 109 | // output results |
| 110 | printf(format: "Decryption using AES128 of [0x%s] is %s\n" , |
| 111 | qPrintable(QCA::arrayToHex(cipherText.toByteArray())), |
| 112 | plainText.data()); |
| 113 | |
| 114 | // Again we need to call final(), to get the last block (with its padding removed) |
| 115 | plainText = cipher.final(); |
| 116 | |
| 117 | // check if the final() call worked |
| 118 | if (!cipher.ok()) { |
| 119 | printf(format: "Final failed\n" ); |
| 120 | } |
| 121 | |
| 122 | // output results |
| 123 | printf(format: "Final decryption block using AES128 is %s\n" , plainText.data()); |
| 124 | // instead of update() and final(), you can do the whole thing |
| 125 | // in one step, using process() |
| 126 | printf(format: "One step decryption using AES128: %s\n" , QCA::SecureArray(cipher.process(a: cipherText)).data()); |
| 127 | } |
| 128 | |
| 129 | return 0; |
| 130 | } |
| 131 | |