bool BotanRSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) { // Check input if ((ppPublicKey == NULL) || (serialisedData.size() == 0)) { return false; } BotanRSAPublicKey* pub = new BotanRSAPublicKey(); if (!pub->deserialise(serialisedData)) { delete pub; return false; } *ppPublicKey = pub; return true; }
// Encryption functions bool BotanRSA::encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding) { // Check if the public key is the right type if (!publicKey->isOfType(BotanRSAPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } std::string eme; switch (padding) { case AsymMech::RSA_PKCS: eme = "PKCS1v15"; break; case AsymMech::RSA_PKCS_OAEP: eme = "EME1(SHA-160)"; break; case AsymMech::RSA: eme = "Raw"; break; default: ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); return false; } BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey; Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan public key"); return false; } Botan::PK_Encryptor_EME* encryptor = NULL; try { encryptor = new Botan::PK_Encryptor_EME(*botanKey, eme); } catch (...) { ERROR_MSG("Could not create the encryptor token"); return false; } // Perform the encryption operation #if BOTAN_VERSION_MINOR == 11 std::vector<Botan::byte> encResult; #else Botan::SecureVector<Botan::byte> encResult; #endif try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); encResult = encryptor->encrypt(data.const_byte_str(), data.size(), *rng->getRNG()); } catch (...) { ERROR_MSG("Could not encrypt the data"); delete encryptor; return false; } // Return the result encryptedData.resize(encResult.size()); #if BOTAN_VERSION_MINOR == 11 memcpy(&encryptedData[0], encResult.data(), encResult.size()); #else memcpy(&encryptedData[0], encResult.begin(), encResult.size()); #endif delete encryptor; return true; }
bool BotanRSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param /* = NULL */, const size_t paramLen /* = 0 */) { if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen)) { return false; } // Check if the public key is the right type if (!publicKey->isOfType(BotanRSAPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } std::string emsa; std::ostringstream request; size_t sLen; switch (mechanism) { case AsymMech::RSA_MD5_PKCS: emsa = "EMSA3(MD5)"; break; case AsymMech::RSA_SHA1_PKCS: emsa = "EMSA3(SHA-160)"; break; case AsymMech::RSA_SHA224_PKCS: emsa = "EMSA3(SHA-224)"; break; case AsymMech::RSA_SHA256_PKCS: emsa = "EMSA3(SHA-256)"; break; case AsymMech::RSA_SHA384_PKCS: emsa = "EMSA3(SHA-384)"; break; case AsymMech::RSA_SHA512_PKCS: emsa = "EMSA3(SHA-512)"; break; case AsymMech::RSA_SHA1_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((publicKey->getBitLength()+6)/8-2-20)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, publicKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } request << "EMSA4(SHA-160,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SHA224_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((publicKey->getBitLength()+6)/8-2-28)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, publicKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } request << "EMSA4(SHA-224,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SHA256_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((publicKey->getBitLength()+6)/8-2-32)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, publicKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } request << "EMSA4(SHA-256,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SHA384_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((publicKey->getBitLength()+6)/8-2-48)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, publicKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } request << "EMSA4(SHA-384,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SHA512_PKCS_PSS: if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 || ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512) { ERROR_MSG("Invalid parameters"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; if (sLen > ((publicKey->getBitLength()+6)/8-2-64)) { ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", (unsigned long)sLen, publicKey->getBitLength()); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } request << "EMSA4(SHA-512,MGF1," << sLen << ")"; emsa = request.str(); break; case AsymMech::RSA_SSL: emsa = "EMSA3(Parallel(MD5,SHA-160))"; break; default: ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } BotanRSAPublicKey* pk = (BotanRSAPublicKey*) currentPublicKey; Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan public key"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } try { verifier = new Botan::PK_Verifier(*botanKey, emsa); } catch (...) { ERROR_MSG("Could not create the verifier token"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } return true; }
// Verification functions bool BotanRSA::verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param /* = NULL */, const size_t paramLen /* = 0 */) { std::string emsa = ""; switch (mechanism) { case AsymMech::RSA: emsa = "Raw"; break; case AsymMech::RSA_PKCS: emsa = "EMSA3(Raw)"; break; default: // Call the generic function return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen); } // Check if the public key is the right type if (!publicKey->isOfType(BotanRSAPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey; Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan public key"); return false; } try { verifier = new Botan::PK_Verifier(*botanKey, emsa); } catch (...) { ERROR_MSG("Could not create the verifier token"); return false; } // Perform the verify operation bool verResult; try { verResult = verifier->verify_message(originalData.const_byte_str(), originalData.size(), signature.const_byte_str(), signature.size()); } catch (...) { ERROR_MSG("Could not check the signature"); delete verifier; verifier = NULL; return false; } delete verifier; verifier = NULL; return verResult; }
// Encryption functions bool BotanRSA::encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const std::string padding) { // Check if the public key is the right type if (!publicKey->isOfType(BotanRSAPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } std::string lowerPadding; lowerPadding.resize(padding.size()); std::transform(padding.begin(), padding.end(), lowerPadding.begin(), tolower); std::string eme; if (!lowerPadding.compare("rsa-pkcs")) { eme = "PKCS1v15"; } else if (!lowerPadding.compare("rsa-pkcs-oaep")) { eme = "EME1(SHA-160)"; } else if (!lowerPadding.compare("rsa-raw")) { eme = "Raw"; } else { ERROR_MSG("Invalid padding mechanism supplied (%s)", padding.c_str()); return false; } BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey; Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan public key"); return false; } Botan::PK_Encryptor_EME* encryptor = NULL; try { encryptor = new Botan::PK_Encryptor_EME(*botanKey, eme); } catch (...) { ERROR_MSG("Could not create the encryptor token"); return false; } // Perform the encryption operation Botan::SecureVector<Botan::byte> encResult; try { BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); encResult = encryptor->encrypt(data.const_byte_str(), data.size(), *rng->getRNG()); } catch (...) { ERROR_MSG("Could not encrypt the data"); delete encryptor; return false; } // Return the result encryptedData.resize(encResult.size()); memcpy(&encryptedData[0], encResult.begin(), encResult.size()); delete encryptor; return true; }
bool BotanRSA::verifyInit(PublicKey* publicKey, const std::string mechanism) { if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism)) { return false; } // Check if the public key is the right type if (!publicKey->isOfType(BotanRSAPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } std::string lowerMechanism; lowerMechanism.resize(mechanism.size()); std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower); std::string emsa; if (!lowerMechanism.compare("rsa-md5-pkcs")) { emsa = "EMSA3(MD5)"; } else if (!lowerMechanism.compare("rsa-sha1-pkcs")) { emsa = "EMSA3(SHA-160)"; } else if (!lowerMechanism.compare("rsa-sha224-pkcs")) { emsa = "EMSA3(SHA-224)"; } else if (!lowerMechanism.compare("rsa-sha256-pkcs")) { emsa = "EMSA3(SHA-256)"; } else if (!lowerMechanism.compare("rsa-sha384-pkcs")) { emsa = "EMSA3(SHA-384)"; } else if (!lowerMechanism.compare("rsa-sha512-pkcs")) { emsa = "EMSA3(SHA-512)"; } else if (!lowerMechanism.compare("rsa-ssl")) { emsa = "EMSA3(Parallel(MD5,SHA-160))"; } else { ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str()); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } BotanRSAPublicKey* pk = (BotanRSAPublicKey*) currentPublicKey; Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan public key"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } try { verifier = new Botan::PK_Verifier(*botanKey, emsa); } catch (...) { ERROR_MSG("Could not create the verifier token"); ByteString dummy; AsymmetricAlgorithm::verifyFinal(dummy); return false; } return true; }
// Verification functions bool BotanRSA::verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism) { std::string lowerMechanism; lowerMechanism.resize(mechanism.size()); std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower); std::string emsa = ""; if (!lowerMechanism.compare("rsa-pkcs")) { emsa = "EMSA3(Raw)"; } else if (!lowerMechanism.compare("rsa-raw")) { emsa = "Raw"; } else { // Call the generic function return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism); } // Check if the public key is the right type if (!publicKey->isOfType(BotanRSAPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey; Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); if (!botanKey) { ERROR_MSG("Could not get the Botan public key"); return false; } try { verifier = new Botan::PK_Verifier(*botanKey, emsa); } catch (...) { ERROR_MSG("Could not create the verifier token"); return false; } // Perform the verify operation bool verResult; try { verResult = verifier->verify_message(originalData.const_byte_str(), originalData.size(), signature.const_byte_str(), signature.size()); } catch (...) { ERROR_MSG("Could not check the signature"); delete verifier; verifier = NULL; return false; } delete verifier; verifier = NULL; return verResult; }