QByteArray PgpManager::SignPresence (const QByteArray& status) { QCA::SecureMessageKey msgKey; if (PrivateKey_.isNull ()) { warning (QString ("Cannot sign: private key is null")); return QByteArray(); } msgKey.setPGPSecretKey (PrivateKey_); QCA::OpenPGP pgp; QCA::SecureMessage msg (&pgp); msg.setFormat (QCA::SecureMessage::Ascii); msg.setSigner (msgKey); msg.startSign (QCA::SecureMessage::Detached); msg.update (status); msg.end (); msg.waitForFinished (); if (msg.success ()) return msg.signature (); else { info (QString { "Error signing: %1" } .arg (msg.errorCode ()) .arg (msg.diagnosticText ())); return QByteArray (); } }
bool PgpManager::IsValidSignature (const QCA::PGPKey& pubkey, const QByteArray& message, const QByteArray& signature) { if (pubkey.isNull ()) { warning (QString ("Cannot encrypt: public key is null")); return false; } QCA::OpenPGP pgp; QCA::SecureMessageKey key; QCA::SecureMessage msg (&pgp); key.setPGPPublicKey (pubkey); msg.setSigner (key); msg.setFormat (QCA::SecureMessage::Binary); msg.startVerify (WrapPGP (signature, PGPType::Signature).toUtf8 ()); msg.update (message); msg.end (); msg.waitForFinished (); if (msg.verifySuccess ()) return true; else { info (QString ("Invalid signature: %1").arg (msg.errorCode ())); return false; } }
QByteArray PgpManager::EncryptBody (const QCA::PGPKey& pubkey, const QByteArray& body) { if (pubkey.isNull ()) { warning ("Cannot encrypt: public key is null"); throw GPGExceptions::NullPubkey {}; } QCA::SecureMessageKey msgKey; msgKey.setPGPPublicKey (pubkey); QCA::OpenPGP pgp; QCA::SecureMessage msg (&pgp); msg.setRecipient (msgKey); msg.setFormat (QCA::SecureMessage::Ascii); msg.startEncrypt (); msg.update (body); msg.end (); msg.waitForFinished (); if (!msg.success ()) { info (QString { "Error encrypting: %1 (%2)." } .arg (msg.errorCode ()) .arg (msg.diagnosticText ())); throw GPGExceptions::Encryption { msg.errorCode (), msg.diagnosticText () }; } return msg.read (); }
QByteArray PgpManager::SignMessage (const QByteArray& body) { QCA::SecureMessageKey msgKey; if (PrivateKey_.isNull ()) { warning (QString ("Cannot sign: private key is null")); return QByteArray (); } msgKey.setPGPSecretKey (PrivateKey_); QCA::OpenPGP pgp; QCA::SecureMessage msg (&pgp); msg.setFormat (QCA::SecureMessage::Ascii); msg.setSigner (msgKey); msg.startSign (QCA::SecureMessage::Detached); msg.update (body); msg.end (); msg.waitForFinished (); if (!msg.success ()) { warning (QString { "Error signing: %1 (%2)." } .arg (msg.errorCode ()) .arg (msg.diagnosticText ())); return QByteArray (); } const auto& sig = msg.signature (); const auto& arrs = sig.split ('\n'); auto it = arrs.begin (); ++it; if (it == arrs.end ()) return sig; for (; it != arrs.end (); ++it) if (it->isEmpty ()) break; if (++it >= arrs.end ()) return sig; QByteArray result; for (; it != arrs.end (); ++it) { if (it->at (0) == '-') break; result += *it; result += '\n'; } result.chop (1); return result; }
WP::err QCACryptoInterface::decryptAsymmetric(const QByteArray &input, QByteArray &plain, const QString &privateKey, const SecureArray &keyPassword, const QString &certificate) { QCA::PrivateKey privKey; QCA::ConvertResult convRes; privKey = QCA::PrivateKey::fromPEM(privateKey, keyPassword, &convRes); if (convRes != QCA::ConvertGood) { std::cout << "Sorry, could not import Private Key" << std::endl; return (WP::err)convRes; } // Read in a matching public key cert // you could also build this using the fromPEMFile() method QCA::Certificate pubCert = QCA::Certificate::fromPEM(certificate, &convRes); if (convRes != QCA::ConvertGood) { std::cout << "Sorry, could not import public key certificate" << std::endl; return (WP::err)convRes; } // We are building the certificate into a SecureMessageKey object, via a // CertificateChain QCA::CertificateChain chain; chain += pubCert; QCA::SecureMessageKeyList skeys; QCA::SecureMessageKey skey; skey.setX509CertificateChain(chain); skey.setX509PrivateKey(privKey); skeys += skey; QCA::CMS sms; sms.setPrivateKeys(skeys); QCA::SecureMessage decryptedMessage(&sms); decryptedMessage.startDecrypt(); decryptedMessage.update(input); decryptedMessage.end(); decryptedMessage.waitForFinished(-1); plain = decryptedMessage.read(); return WP::kOk; }
WP::err QCACryptoInterface::encyrptAsymmetric(const QByteArray &input, QByteArray &encrypted, const QString &certificate) { // Read in a matching public key cert // you could also build this using the fromPEMFile() method QCA::ConvertResult convRes; QCA::Certificate pubCert = QCA::Certificate::fromPEM(certificate, &convRes); if (convRes != QCA::ConvertGood) { std::cout << "Sorry, could not import public key certificate" << std::endl; return (WP::err)convRes; } // We are building the certificate into a SecureMessageKey object, via a // CertificateChain QCA::SecureMessageKey secMsgKey; QCA::CertificateChain chain; chain += pubCert; secMsgKey.setX509CertificateChain(chain); // build up a SecureMessage object, based on our public key certificate QCA::CMS cms; QCA::SecureMessage msg(&cms); msg.setRecipient(secMsgKey); // Now use the SecureMessage object to encrypt the plain text. msg.startEncrypt(); msg.update(input); msg.end(); // I think it is reasonable to wait for 1 second for this msg.waitForFinished(1000); // check to see if it worked if(!msg.success()) { std::cout << "Error encrypting: " << msg.errorCode() << std::endl; return (WP::err)msg.errorCode(); } // get the result encrypted = msg.read(); return WP::kOk; }
int main(int argc, char** argv) { // the Initializer object sets things up, and // also does cleanup when it goes out of scope QCA::Initializer init; QCoreApplication app(argc, argv); // We need to ensure that we have certificate handling support if ( !QCA::isSupported( "cert" ) ) { std::cout << "Sorry, no PKI certificate support" << std::endl; return 1; } // Read in a private key QCA::PrivateKey privKey; QCA::ConvertResult convRes; QCA::SecureArray passPhrase = "start"; privKey = QCA::PrivateKey::fromPEMFile( "Userkey.pem", passPhrase, &convRes ); if ( convRes != QCA::ConvertGood ) { std::cout << "Sorry, could not import Private Key" << std::endl; return 1; } // Read in a matching public key cert // you could also build this using the fromPEMFile() method QCA::Certificate pubCert( "User.pem" ); if ( pubCert.isNull() ) { std::cout << "Sorry, could not import public key certificate" << std::endl; return 1; } // We are building the certificate into a SecureMessageKey object, via a // CertificateChain QCA::SecureMessageKey secMsgKey; QCA::CertificateChain chain; chain += pubCert; secMsgKey.setX509CertificateChain( chain ); // build up a SecureMessage object, based on our public key certificate QCA::CMS cms; QCA::SecureMessage msg(&cms); msg.setRecipient(secMsgKey); // Some plain text - we use the first command line argument if provided QByteArray plainText = (argc >= 2) ? argv[1] : "What do ya want for nuthin'"; // Now use the SecureMessage object to encrypt the plain text. msg.startEncrypt(); msg.update(plainText); msg.end(); // I think it is reasonable to wait for 1 second for this msg.waitForFinished(1000); // check to see if it worked if(!msg.success()) { std::cout << "Error encrypting: " << msg.errorCode() << std::endl; return 1; } // get the result QCA::SecureArray cipherText = msg.read(); QCA::Base64 enc; std::cout << plainText.data() << " encrypts to (in base 64): "; std::cout << qPrintable( enc.arrayToString( cipherText ) ) << std::endl; // Show we can decrypt it with the private key if ( !privKey.canDecrypt() ) { std::cout << "Private key cannot be used to decrypt" << std::endl; return 1; } QCA::SecureArray plainTextResult; if ( 0 == privKey.decrypt(cipherText, &plainTextResult, QCA::EME_PKCS1_OAEP ) ) { std::cout << "Decryption process failed" << std::endl; return 1; } std::cout << qPrintable( enc.arrayToString( cipherText ) ); std::cout << " (in base 64) decrypts to: "; std::cout << plainTextResult.data() << std::endl; return 0; }