Skip to content

Instantly share code, notes, and snippets.

@NorbertFenk
Created June 21, 2017 07:46
Show Gist options
  • Save NorbertFenk/b98e3a0f51f4b737817eae3657ee16b0 to your computer and use it in GitHub Desktop.
Save NorbertFenk/b98e3a0f51f4b737817eae3657ee16b0 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <QString>
#include <QByteArray>
#include <QDebug>
#include <QFile>
#include <QCryptographicHash>
#include <botan/pkcs8.h>
#include <botan/hex.h>
#include <botan/pk_keys.h>
#include <botan/pubkey.h>
#include <botan/auto_rng.h>
#include <botan/rng.h>
#include <botan/rsa.h>
#include <botan/data_src.h>
#include <botan/x509self.h>
QString readInput (const QString &filePath)
{
QFile input(filePath);
QString rawText;
if (!input.open(QIODevice::ReadOnly)) {
qDebug() << "File reading error" << endl;
}
rawText = input.readAll();
input.close();
return rawText;
}
std::vector<uint8_t> convertQStringToStdVector(const QString &string)
{
std::string stdString = string.toStdString();
std::vector<uint8_t> rawTextVector(stdString.data(), stdString.data()+stdString.length());
// std::cout << "vec: " << plaintextVector.size() << std::endl;
// for (auto it : rawTextVector) {
// std::cout << it << std::endl;
// }
return rawTextVector;
}
std::vector<uint8_t> convertQByteArrayToStdVector(const QByteArray &array)
{
std::string stdString = array.toStdString();
std::vector<uint8_t> rawStdVector(stdString.data(), stdString.data()+stdString.length());
// std::cout << "vec: " << plaintextVector.size() << std::endl;
// for (auto it : rawTextVector) {
// std::cout << it << std::endl;
// }
return rawStdVector;
}
Botan::Private_Key *generateKeys(Botan::RSA_PrivateKey RSAKey, Botan::AutoSeeded_RNG *rng)
{
//Public-key cryptography standard 8
QString privateKeyPEM = QString::fromStdString(Botan::PKCS8::PEM_encode(RSAKey));
QString publicKeyPEM = QString::fromStdString(Botan::X509::PEM_encode(RSAKey));
qDebug() << privateKeyPEM << endl;
qDebug() << publicKeyPEM << endl;
//store in memory
Botan::DataSource_Memory privateKeySource(privateKeyPEM.toStdString());
//load keypair, Private_Key is child of Public_Key
Botan::Private_Key *keys(Botan::PKCS8::load_key(privateKeySource, *rng));
return keys;
}
QString makeCert(Botan::Private_Key *keys, Botan::AutoSeeded_RNG *rng)
{
Botan::X509_Cert_Options certOptions;
certOptions.email = "hello@opswat.com";
certOptions.common_name = "Opswat Inc.";
Botan::X509_Certificate cert = Botan::X509::create_self_signed_cert(certOptions, *keys, "SHA-256", *rng);
QString certString = QString::fromStdString(cert.PEM_encode());
return certString;
}
QByteArray generateHash(const QString &data)
{
QCryptographicHash hash(QCryptographicHash::Sha256);
hash.addData(data.toUtf8());
return hash.result();
}
std::vector<uint8_t> encryptData(Botan::Private_Key *keys, Botan::AutoSeeded_RNG *rng, const std::vector<uint8_t> &dataVector)
{
//create encryptor with pk
Botan::PK_Encryptor_EME encryptor(*keys, *rng, "EME1(SHA-256)"); //With key being the key you want to encrypt messages to. The padding method to use is specified in eme.
qDebug() << "maximum_input_size: " << encryptor.maximum_input_size() << endl;
//encrypt hash
return encryptor.encrypt(dataVector, *rng);
}
std::vector<uint8_t> signData(Botan::Private_Key *keys, Botan::AutoSeeded_RNG *rng, const std::vector<uint8_t> &dataVector)
{
Botan::PK_Signer signer(*keys, *rng, "EMSA4(SHA-256)"); //signature format
// signer.update(ciphertext);
// std::vector<uint8_t> signature = signer.signature(rng);
return signer.sign_message(dataVector, *rng);
}
bool verifyData(Botan::Private_Key *keys, const std::vector<uint8_t> &dataVector, const std::vector<uint8_t> &signature)
{
Botan::PK_Verifier verifier(*keys, "EMSA4(SHA-256)");
// verifier.update(ciphertext);
// std::cout << "is " << (verifier.check_signature(signature)? "valid" : "invalid");
return verifier.verify_message(dataVector, signature);
}
QByteArray decryptData(Botan::Private_Key *keys, Botan::AutoSeeded_RNG *rng, const std::vector<uint8_t> &dataVector)
{
Botan::PK_Decryptor_EME decryptor(*keys, *rng, "EME1(SHA-256)");
return QByteArray::fromHex(Botan::hex_encode(decryptor.decrypt(dataVector)).data());
}
int main (int argc, char* argv[])
{
if (argc != 2) {
qDebug() << "Please add a valid file path";
qDebug() << argv[0] << " <file path>";
return 1;
}
Q_UNUSED(argc);
QString rawInput = readInput(argv[1]);
qDebug() << rawInput << endl;
Botan::AutoSeeded_RNG rng;
Botan::RSA_PrivateKey RSAKey(rng, 2048);
Botan::RSA_PrivateKey RSAKey2(rng, 2048);
Botan::Private_Key *keys = generateKeys(RSAKey, &rng);
Botan::Private_Key *keys2 = generateKeys(RSAKey2, &rng);
qDebug() << makeCert(keys, &rng) << endl;
QByteArray hash = generateHash(rawInput);
qDebug() << "hashed data: " << hash.toHex() << endl;
std::vector<uint8_t> hashVector = convertQByteArrayToStdVector(hash);
std::vector<uint8_t> dataVector = convertQStringToStdVector(rawInput);
std::vector<uint8_t> ciphertext = encryptData(keys, &rng, hashVector);
std::vector<uint8_t> ciphertextOfStringInput = encryptData(keys, &rng, dataVector);
std::vector<uint8_t> signature = signData(keys, &rng, ciphertext);
std::vector<uint8_t> signatureOfStringInput = signData(keys, &rng, ciphertextOfStringInput);
qDebug() << "Signature: " << Botan::hex_encode(signature).c_str() << endl;
qDebug() << "Message is { " << (verifyData(keys, ciphertext, signature) ? "valid" : "invalid") << " }" << endl;
qDebug() << "Message is { " << (verifyData(keys2, ciphertext, signature) ? "valid" : "invalid") << " }" << endl;
qDebug() << "Message is { " << (verifyData(keys, ciphertextOfStringInput, signatureOfStringInput) ? "valid" : "invalid") << " }" << endl;
qDebug() << "decoded: " << decryptData(keys, &rng, ciphertext).toHex() << endl;
qDebug() << "hash: " << hash.toHex() << endl;
qDebug() << "decoded text: " << QString::fromUtf8(decryptData(keys, &rng, ciphertextOfStringInput)) << endl;
qDebug() << "original text: " << rawInput << endl;
delete keys;
delete keys2;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment