带有 EVP 方法的 OpenSSL RSA Encryption/Decryption
OpenSSL RSA Encryption/Decryption with EVP Methods
我使用 Openssl EVP (OpenSSL Ref) 方法创建了一个 rsa class。
rsa.h
#ifndef RSA_RSA_H
#define RSA_RSA_H
#include <string>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include "utils.h"
#define PADDING RSA_PKCS1_OAEP_PADDING
#define LOGGING
namespace tools
{
class CryptoRSA
{
private:
int _keysize;
char *_rsaPrivateKeyStr, *_privateKeyStr, *_publicKeyStr;
unsigned char* _encryptedKey, *_iv;
EVP_PKEY *_pkey;
EVP_CIPHER_CTX *rsaEncryptContext, *rsaDecryptContext;
static std::string getOpenSSLError();
bool generateRSAKey();
bool loadKeyFromFile(const std::string &filepath);
bool loadKeyFromStr(const std::string &str);
public:
explicit CryptoRSA(int keysize);
explicit CryptoRSA(const std::string &key);
virtual ~CryptoRSA();
inline unsigned char* getRSAIV() const { return _iv; }
inline unsigned char* getRSAEncryptedKey() const { return _encryptedKey; }
inline EVP_PKEY *getEvpPkey() { return _pkey; }
inline int getEvpPkeySize(EVP_PKEY *key) { return EVP_PKEY_size(key); }
char *getRSAPrivateKeyStr();
char *getPrivateKeyStr();
char *getPublicKeyStr();
int encryptEVP(EVP_PKEY *key, const unsigned char *message, size_t messageLength, unsigned char **encryptedMessage, unsigned char **encryptedKey, size_t *encryptedKeyLength, unsigned char **iv);
int decryptEVP(EVP_PKEY *key, unsigned char *encryptedMessage, size_t encryptedMessageLength, unsigned char *encryptedKey, size_t encryptedKeyLength, unsigned char *iv, unsigned char **decryptedMessage);
};
} // namespace tools
#endif //RSA_RSA_H
和rsa.cpp
#include "rsa.h"
namespace tools
{
CryptoRSA::CryptoRSA(int keysize) : _keysize(keysize), _pkey(nullptr)
{
// Initalize contexts
rsaEncryptContext = EVP_CIPHER_CTX_new();
rsaDecryptContext = EVP_CIPHER_CTX_new();
// Generate the RSA Key
if ( !generateRSAKey() )
{
#ifdef LOGGING
std::cerr << "Error at generating the RSA key!" << std::endl;
#endif
throw std::runtime_error("Error at generating the RSA key!");
}
}
CryptoRSA::CryptoRSA(const std::string &key) : _keysize(-1), _pkey(nullptr)
{
// Initalize contexts
rsaEncryptContext = EVP_CIPHER_CTX_new();
rsaDecryptContext = EVP_CIPHER_CTX_new();
// Load pkey from file or string
if ( !loadKeyFromFile(key) )
{
#ifdef LOGGING
std::cerr << "Could not load key from file/string!" << std::endl;
#endif
}
}
CryptoRSA::~CryptoRSA()
{
EVP_PKEY_free(_pkey);
EVP_CIPHER_CTX_free(rsaEncryptContext);
EVP_CIPHER_CTX_free(rsaDecryptContext);
}
std::string CryptoRSA::getOpenSSLError()
{
char *buf;
BIO *bio = BIO_new(BIO_s_mem());
ERR_print_errors(bio);
size_t len = static_cast<size_t >(BIO_get_mem_data(bio, &buf));
std::string err(buf, len);
BIO_free(bio);
return err;
}
bool CryptoRSA::generateRSAKey()
{
EVP_PKEY_CTX *context = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if(EVP_PKEY_keygen_init(context) <= 0)
{
return false;
}
if(EVP_PKEY_CTX_set_rsa_keygen_bits(context, _keysize) <= 0)
{
return false;
}
if(EVP_PKEY_keygen(context, &_pkey) <= 0)
{
return false;
}
EVP_PKEY_CTX_free(context);
return true;
}
bool CryptoRSA::loadKeyFromFile(const std::string &filepath)
{
if ( existsFile(filepath) )
{
if ( loadKeyFromStr(readBinFile(filepath)) )
{
#ifdef LOGGING
std::cerr << "Loaded successfully rsa key from file " << filepath << std::endl;
#endif
return true;
}
} else
{
if ( loadKeyFromStr(filepath) )
{
#ifdef LOGGING
std::cerr << "Loaded successfully rsa key from string!" << std::endl;
#endif
return true;
}
}
return false;
}
bool CryptoRSA::loadKeyFromStr(const std::string &str)
{
std::string fLine;
std::istringstream f(str);
std::getline(f, fLine);
BIO *bioPrivate = BIO_new(BIO_s_mem());
BIO_write(bioPrivate, str.c_str(), static_cast<int>(str.length()));
if (fLine == "-----BEGIN RSA PRIVATE KEY-----")
{
_pkey = PEM_read_bio_PrivateKey(bioPrivate, nullptr, nullptr, nullptr);
} else if (fLine == "-----BEGIN PUBLIC KEY-----")
{
_pkey = PEM_read_bio_PUBKEY(bioPrivate, nullptr, nullptr, nullptr);
} else
{
#ifdef LOGGING
std::cerr << "Unsupported file provided with file header: " << fLine << std::endl;
#endif
BIO_free(bioPrivate);
return false;
}
BIO_free(bioPrivate);
return true;
}
char* CryptoRSA::getRSAPrivateKeyStr()
{
RSA *rsaPrivateKey = EVP_PKEY_get0_RSA(_pkey);
BIO *bioPrivate = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(bioPrivate, rsaPrivateKey, nullptr, nullptr, 0, nullptr, nullptr);
BIO_flush(bioPrivate);
BIO_get_mem_data(bioPrivate, &_rsaPrivateKeyStr);
return _rsaPrivateKeyStr;
}
char* CryptoRSA::getPrivateKeyStr()
{
BIO *bioPrivate = BIO_new(BIO_s_mem());
PEM_write_bio_PrivateKey(bioPrivate, _pkey, NULL, NULL, 0, 0, NULL);
BIO_flush(bioPrivate);
BIO_get_mem_data(bioPrivate, &_privateKeyStr);
return _privateKeyStr;
}
char* CryptoRSA::getPublicKeyStr()
{
BIO *bioPublic = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bioPublic, _pkey);
BIO_flush(bioPublic);
BIO_get_mem_data(bioPublic, &_publicKeyStr);
return _publicKeyStr;
}
int CryptoRSA::encryptEVP(EVP_PKEY *key, const unsigned char *message, size_t messageLength, unsigned char **encryptedMessage,
unsigned char **encryptedKey, size_t *encryptedKeyLength, unsigned char **iv)
{
// Allocate memory for everything
size_t encryptedMessageLength = 0;
size_t blockLength = 0;
*encryptedKey = (unsigned char*)malloc(EVP_PKEY_size(key));
*iv = (unsigned char*)malloc(EVP_MAX_IV_LENGTH);
*encryptedMessage = (unsigned char*)malloc(messageLength + EVP_MAX_IV_LENGTH);
if(!EVP_SealInit(rsaEncryptContext, EVP_aes_256_cbc(), encryptedKey, (int*)encryptedKeyLength, *iv, &key, 1))
{
#ifdef LOGGING
std::cerr << "Error during EVP_SealInit in RSA encrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
if(!EVP_SealUpdate(rsaEncryptContext, *encryptedMessage + encryptedMessageLength, (int*)&blockLength, (const unsigned char*)message, (int)messageLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_SealUpdate in RSA encrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
encryptedMessageLength += blockLength;
if(!EVP_SealFinal(rsaEncryptContext, *encryptedMessage + encryptedMessageLength, (int*)&blockLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_SealFinal in RSA encrypt: " << getOpenSSLError() <<std::endl;
#endif
return -1;
}
encryptedMessageLength += blockLength;
return (int)encryptedMessageLength;
}
int CryptoRSA::decryptEVP(EVP_PKEY *key, unsigned char *encryptedMessage, size_t encryptedMessageLength, unsigned char *encryptedKey,
size_t encryptedKeyLength, unsigned char *iv, unsigned char **decryptedMessage)
{
// Allocate memory for everything
size_t decryptedMessageLength = 0;
size_t blockLength = 0;
*decryptedMessage = (unsigned char*)malloc(encryptedMessageLength + EVP_MAX_IV_LENGTH);
// Decrypt it!
if(!EVP_OpenInit(rsaDecryptContext, EVP_aes_256_cbc(), encryptedKey, getEvpPkeySize(key), iv, key))
{
#ifdef LOGGING
std::cerr << "Error during EVP_OpenInit in RSA decrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
if(!EVP_OpenUpdate(rsaDecryptContext, (unsigned char*)*decryptedMessage + decryptedMessageLength, (int*)&blockLength, encryptedMessage, (int)encryptedMessageLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_OpenUpdate in RSA decrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
decryptedMessageLength += blockLength;
if(!EVP_OpenFinal(rsaDecryptContext, (unsigned char*)*decryptedMessage + decryptedMessageLength, (int*)&blockLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_OpenFinal in RSA decrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
decryptedMessageLength += blockLength;
return (int)decryptedMessageLength;
}
} // namespace tools
main.cpp
#include <iostream>
#include <memory>
#include <cstring>
#include "rsa.h"
bool writeBinFile(const std::string &filepath, const char* content, long contentLength, bool append=false)
{
std::fstream out;
if (append)
{
out.open(filepath, std::ios::out | std::ios::app | std::ios::binary);
} else
{
out.open(filepath, std::ios::out | std::ios::binary);
}
if (out.is_open())
{
out.write(content, contentLength);
return true;
} else
{
return false;
}
}
void encrypt_decrypt_with_evp(std::string msg_to_encrypt)
{
std::unique_ptr<tools::CryptoRSA> cryptoRSA = std::unique_ptr<tools::CryptoRSA>(new tools::CryptoRSA(2048));
unsigned char *encryptedMessage = nullptr;
char *decryptedMessage = nullptr;
unsigned char *encryptedKey;
unsigned char *iv;
size_t encryptedKeyLength;
std::string priv = cryptoRSA->getRSAPrivateKeyStr();
std::string pub = cryptoRSA->getPublicKeyStr();
// Save RSA KeyPair
writeBinFile("RSAPrivateKey.pem", priv.c_str(), priv.length());
writeBinFile("PublicKey.pem", pub.c_str(), pub.length());
// Start RSA Encryption
int encryptedMessageLength = cryptoRSA->encryptEVP(cryptoRSA->getEvpPkey(), (const unsigned char*)msg_to_encrypt.c_str(), msg_to_encrypt.size()+1,
&encryptedMessage, &encryptedKey, &encryptedKeyLength, &iv);
if(encryptedMessageLength == -1)
{
std::cerr << "Encryption failed" << std::endl;
exit(1);
}
std::cout << "Encrypted message: " << encryptedMessage << std::endl;
writeBinFile("enc_msg.bin", reinterpret_cast<const char *>(encryptedMessage), encryptedMessageLength);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Start RSA Decryption
int decryptedMessageLength = cryptoRSA->decryptEVP(cryptoRSA->getEvpPkey(), encryptedMessage, (size_t)encryptedMessageLength,
encryptedKey, encryptedKeyLength, iv, (unsigned char**)&decryptedMessage);
if(decryptedMessageLength == -1)
{
std::cerr << "Decryption failed" << std::endl;
exit(1);
}
std::cout << "Decrypted message: " << decryptedMessage << std::endl;
}
int main(int argc, char* argv[])
{
encrypt_decrypt_with_evp("abcdef");
return 0;
}
使用 class 实现的 RSA 加密和解密完全可以正常工作。
我想要实现的是:
- 用我实现的解决方案加密像
abcdef
这样的消息,并将内容保存在文件中 enc_msg.bin
- 使用openssl命令行界面(例如:
openssl rsautl
)解密消息
或者:
- 使用openssl命令行接口
加密消息abcdef
- 用我实现的解决方案解密创建的文件
如您所见,EVP_SealInit
使用带有 encryptedKey 和 IV 的 EVP_aes_256_cbc。但是我没有找到将这些参数提供给 openssl rsautl cli 的可能性。
有谁知道如何解密使用 EVP 方法创建的消息(使用 Openssl cli)(EVP_SealInit、EVP_SealUpdate、EVP_SealFinal)?
非常感谢您的帮助!
在@Topaco 的帮助下,我找到了解决方案。这是一个Hybrid Encryption
我还保存了 EncryptedKey 和 IV 到 rsa_ek.bin
和 rsa_iv.txt
文件。
使用openssl rsautl
cli
解密rsa_ek.bin
openssl rsautl -decrypt -inkey RSAPrivateKey.pem -in rsa_ek.bin -out rsa_ek.txt
- 使用
AES-256-CBC
密码 解密 enc_msg.bin
文件
openssl enc -aes-256-cbc -d -in enc_msg.bin -K $(xxd -p -c 256 rsa_ek.txt) -iv $(xxd -p -c 256 rsa_iv.txt) -out enc_msg.dec.txt
我使用 Openssl EVP (OpenSSL Ref) 方法创建了一个 rsa class。
rsa.h
#ifndef RSA_RSA_H
#define RSA_RSA_H
#include <string>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include "utils.h"
#define PADDING RSA_PKCS1_OAEP_PADDING
#define LOGGING
namespace tools
{
class CryptoRSA
{
private:
int _keysize;
char *_rsaPrivateKeyStr, *_privateKeyStr, *_publicKeyStr;
unsigned char* _encryptedKey, *_iv;
EVP_PKEY *_pkey;
EVP_CIPHER_CTX *rsaEncryptContext, *rsaDecryptContext;
static std::string getOpenSSLError();
bool generateRSAKey();
bool loadKeyFromFile(const std::string &filepath);
bool loadKeyFromStr(const std::string &str);
public:
explicit CryptoRSA(int keysize);
explicit CryptoRSA(const std::string &key);
virtual ~CryptoRSA();
inline unsigned char* getRSAIV() const { return _iv; }
inline unsigned char* getRSAEncryptedKey() const { return _encryptedKey; }
inline EVP_PKEY *getEvpPkey() { return _pkey; }
inline int getEvpPkeySize(EVP_PKEY *key) { return EVP_PKEY_size(key); }
char *getRSAPrivateKeyStr();
char *getPrivateKeyStr();
char *getPublicKeyStr();
int encryptEVP(EVP_PKEY *key, const unsigned char *message, size_t messageLength, unsigned char **encryptedMessage, unsigned char **encryptedKey, size_t *encryptedKeyLength, unsigned char **iv);
int decryptEVP(EVP_PKEY *key, unsigned char *encryptedMessage, size_t encryptedMessageLength, unsigned char *encryptedKey, size_t encryptedKeyLength, unsigned char *iv, unsigned char **decryptedMessage);
};
} // namespace tools
#endif //RSA_RSA_H
和rsa.cpp
#include "rsa.h"
namespace tools
{
CryptoRSA::CryptoRSA(int keysize) : _keysize(keysize), _pkey(nullptr)
{
// Initalize contexts
rsaEncryptContext = EVP_CIPHER_CTX_new();
rsaDecryptContext = EVP_CIPHER_CTX_new();
// Generate the RSA Key
if ( !generateRSAKey() )
{
#ifdef LOGGING
std::cerr << "Error at generating the RSA key!" << std::endl;
#endif
throw std::runtime_error("Error at generating the RSA key!");
}
}
CryptoRSA::CryptoRSA(const std::string &key) : _keysize(-1), _pkey(nullptr)
{
// Initalize contexts
rsaEncryptContext = EVP_CIPHER_CTX_new();
rsaDecryptContext = EVP_CIPHER_CTX_new();
// Load pkey from file or string
if ( !loadKeyFromFile(key) )
{
#ifdef LOGGING
std::cerr << "Could not load key from file/string!" << std::endl;
#endif
}
}
CryptoRSA::~CryptoRSA()
{
EVP_PKEY_free(_pkey);
EVP_CIPHER_CTX_free(rsaEncryptContext);
EVP_CIPHER_CTX_free(rsaDecryptContext);
}
std::string CryptoRSA::getOpenSSLError()
{
char *buf;
BIO *bio = BIO_new(BIO_s_mem());
ERR_print_errors(bio);
size_t len = static_cast<size_t >(BIO_get_mem_data(bio, &buf));
std::string err(buf, len);
BIO_free(bio);
return err;
}
bool CryptoRSA::generateRSAKey()
{
EVP_PKEY_CTX *context = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if(EVP_PKEY_keygen_init(context) <= 0)
{
return false;
}
if(EVP_PKEY_CTX_set_rsa_keygen_bits(context, _keysize) <= 0)
{
return false;
}
if(EVP_PKEY_keygen(context, &_pkey) <= 0)
{
return false;
}
EVP_PKEY_CTX_free(context);
return true;
}
bool CryptoRSA::loadKeyFromFile(const std::string &filepath)
{
if ( existsFile(filepath) )
{
if ( loadKeyFromStr(readBinFile(filepath)) )
{
#ifdef LOGGING
std::cerr << "Loaded successfully rsa key from file " << filepath << std::endl;
#endif
return true;
}
} else
{
if ( loadKeyFromStr(filepath) )
{
#ifdef LOGGING
std::cerr << "Loaded successfully rsa key from string!" << std::endl;
#endif
return true;
}
}
return false;
}
bool CryptoRSA::loadKeyFromStr(const std::string &str)
{
std::string fLine;
std::istringstream f(str);
std::getline(f, fLine);
BIO *bioPrivate = BIO_new(BIO_s_mem());
BIO_write(bioPrivate, str.c_str(), static_cast<int>(str.length()));
if (fLine == "-----BEGIN RSA PRIVATE KEY-----")
{
_pkey = PEM_read_bio_PrivateKey(bioPrivate, nullptr, nullptr, nullptr);
} else if (fLine == "-----BEGIN PUBLIC KEY-----")
{
_pkey = PEM_read_bio_PUBKEY(bioPrivate, nullptr, nullptr, nullptr);
} else
{
#ifdef LOGGING
std::cerr << "Unsupported file provided with file header: " << fLine << std::endl;
#endif
BIO_free(bioPrivate);
return false;
}
BIO_free(bioPrivate);
return true;
}
char* CryptoRSA::getRSAPrivateKeyStr()
{
RSA *rsaPrivateKey = EVP_PKEY_get0_RSA(_pkey);
BIO *bioPrivate = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(bioPrivate, rsaPrivateKey, nullptr, nullptr, 0, nullptr, nullptr);
BIO_flush(bioPrivate);
BIO_get_mem_data(bioPrivate, &_rsaPrivateKeyStr);
return _rsaPrivateKeyStr;
}
char* CryptoRSA::getPrivateKeyStr()
{
BIO *bioPrivate = BIO_new(BIO_s_mem());
PEM_write_bio_PrivateKey(bioPrivate, _pkey, NULL, NULL, 0, 0, NULL);
BIO_flush(bioPrivate);
BIO_get_mem_data(bioPrivate, &_privateKeyStr);
return _privateKeyStr;
}
char* CryptoRSA::getPublicKeyStr()
{
BIO *bioPublic = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bioPublic, _pkey);
BIO_flush(bioPublic);
BIO_get_mem_data(bioPublic, &_publicKeyStr);
return _publicKeyStr;
}
int CryptoRSA::encryptEVP(EVP_PKEY *key, const unsigned char *message, size_t messageLength, unsigned char **encryptedMessage,
unsigned char **encryptedKey, size_t *encryptedKeyLength, unsigned char **iv)
{
// Allocate memory for everything
size_t encryptedMessageLength = 0;
size_t blockLength = 0;
*encryptedKey = (unsigned char*)malloc(EVP_PKEY_size(key));
*iv = (unsigned char*)malloc(EVP_MAX_IV_LENGTH);
*encryptedMessage = (unsigned char*)malloc(messageLength + EVP_MAX_IV_LENGTH);
if(!EVP_SealInit(rsaEncryptContext, EVP_aes_256_cbc(), encryptedKey, (int*)encryptedKeyLength, *iv, &key, 1))
{
#ifdef LOGGING
std::cerr << "Error during EVP_SealInit in RSA encrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
if(!EVP_SealUpdate(rsaEncryptContext, *encryptedMessage + encryptedMessageLength, (int*)&blockLength, (const unsigned char*)message, (int)messageLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_SealUpdate in RSA encrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
encryptedMessageLength += blockLength;
if(!EVP_SealFinal(rsaEncryptContext, *encryptedMessage + encryptedMessageLength, (int*)&blockLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_SealFinal in RSA encrypt: " << getOpenSSLError() <<std::endl;
#endif
return -1;
}
encryptedMessageLength += blockLength;
return (int)encryptedMessageLength;
}
int CryptoRSA::decryptEVP(EVP_PKEY *key, unsigned char *encryptedMessage, size_t encryptedMessageLength, unsigned char *encryptedKey,
size_t encryptedKeyLength, unsigned char *iv, unsigned char **decryptedMessage)
{
// Allocate memory for everything
size_t decryptedMessageLength = 0;
size_t blockLength = 0;
*decryptedMessage = (unsigned char*)malloc(encryptedMessageLength + EVP_MAX_IV_LENGTH);
// Decrypt it!
if(!EVP_OpenInit(rsaDecryptContext, EVP_aes_256_cbc(), encryptedKey, getEvpPkeySize(key), iv, key))
{
#ifdef LOGGING
std::cerr << "Error during EVP_OpenInit in RSA decrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
if(!EVP_OpenUpdate(rsaDecryptContext, (unsigned char*)*decryptedMessage + decryptedMessageLength, (int*)&blockLength, encryptedMessage, (int)encryptedMessageLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_OpenUpdate in RSA decrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
decryptedMessageLength += blockLength;
if(!EVP_OpenFinal(rsaDecryptContext, (unsigned char*)*decryptedMessage + decryptedMessageLength, (int*)&blockLength))
{
#ifdef LOGGING
std::cerr << "Error during EVP_OpenFinal in RSA decrypt: " << getOpenSSLError() << std::endl;
#endif
return -1;
}
decryptedMessageLength += blockLength;
return (int)decryptedMessageLength;
}
} // namespace tools
main.cpp
#include <iostream>
#include <memory>
#include <cstring>
#include "rsa.h"
bool writeBinFile(const std::string &filepath, const char* content, long contentLength, bool append=false)
{
std::fstream out;
if (append)
{
out.open(filepath, std::ios::out | std::ios::app | std::ios::binary);
} else
{
out.open(filepath, std::ios::out | std::ios::binary);
}
if (out.is_open())
{
out.write(content, contentLength);
return true;
} else
{
return false;
}
}
void encrypt_decrypt_with_evp(std::string msg_to_encrypt)
{
std::unique_ptr<tools::CryptoRSA> cryptoRSA = std::unique_ptr<tools::CryptoRSA>(new tools::CryptoRSA(2048));
unsigned char *encryptedMessage = nullptr;
char *decryptedMessage = nullptr;
unsigned char *encryptedKey;
unsigned char *iv;
size_t encryptedKeyLength;
std::string priv = cryptoRSA->getRSAPrivateKeyStr();
std::string pub = cryptoRSA->getPublicKeyStr();
// Save RSA KeyPair
writeBinFile("RSAPrivateKey.pem", priv.c_str(), priv.length());
writeBinFile("PublicKey.pem", pub.c_str(), pub.length());
// Start RSA Encryption
int encryptedMessageLength = cryptoRSA->encryptEVP(cryptoRSA->getEvpPkey(), (const unsigned char*)msg_to_encrypt.c_str(), msg_to_encrypt.size()+1,
&encryptedMessage, &encryptedKey, &encryptedKeyLength, &iv);
if(encryptedMessageLength == -1)
{
std::cerr << "Encryption failed" << std::endl;
exit(1);
}
std::cout << "Encrypted message: " << encryptedMessage << std::endl;
writeBinFile("enc_msg.bin", reinterpret_cast<const char *>(encryptedMessage), encryptedMessageLength);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Start RSA Decryption
int decryptedMessageLength = cryptoRSA->decryptEVP(cryptoRSA->getEvpPkey(), encryptedMessage, (size_t)encryptedMessageLength,
encryptedKey, encryptedKeyLength, iv, (unsigned char**)&decryptedMessage);
if(decryptedMessageLength == -1)
{
std::cerr << "Decryption failed" << std::endl;
exit(1);
}
std::cout << "Decrypted message: " << decryptedMessage << std::endl;
}
int main(int argc, char* argv[])
{
encrypt_decrypt_with_evp("abcdef");
return 0;
}
使用 class 实现的 RSA 加密和解密完全可以正常工作。 我想要实现的是:
- 用我实现的解决方案加密像
abcdef
这样的消息,并将内容保存在文件中enc_msg.bin
- 使用openssl命令行界面(例如:
openssl rsautl
)解密消息
或者:
- 使用openssl命令行接口 加密消息
- 用我实现的解决方案解密创建的文件
abcdef
如您所见,EVP_SealInit
使用带有 encryptedKey 和 IV 的 EVP_aes_256_cbc。但是我没有找到将这些参数提供给 openssl rsautl cli 的可能性。
有谁知道如何解密使用 EVP 方法创建的消息(使用 Openssl cli)(EVP_SealInit、EVP_SealUpdate、EVP_SealFinal)?
非常感谢您的帮助!
在@Topaco 的帮助下,我找到了解决方案。这是一个Hybrid Encryption
我还保存了 EncryptedKey 和 IV 到
rsa_ek.bin
和rsa_iv.txt
文件。使用
解密openssl rsautl
clirsa_ek.bin
openssl rsautl -decrypt -inkey RSAPrivateKey.pem -in rsa_ek.bin -out rsa_ek.txt
- 使用
AES-256-CBC
密码 解密
enc_msg.bin
文件
openssl enc -aes-256-cbc -d -in enc_msg.bin -K $(xxd -p -c 256 rsa_ek.txt) -iv $(xxd -p -c 256 rsa_iv.txt) -out enc_msg.dec.txt