如何使用 OpenSSL C 库和公钥文件加密字符串?

goo*_*ake 7 c c++ encryption openssl cryptography

使用C 库而不是同名的命令行工具)使用公钥文件将一个 Short 加密std::string为另一个Short 的推荐方法是什么,并且了解算法?(在这种情况下,字符串不大于 ~100 字节,密钥文件采用格式,算法可以是任何非对称算法,例如 RSA/ECDSA/等)。std::stringopenssl .pem

我希望编写一个具有如下接口的函数bool EncryptString(const std::string& InStr, const std::string& InPublicKey, std::string& OutString)

通过查看文档,似乎EVP_PKEY_encrypt是要使用的函数,它需要一个EVP_PKEY_CTX *ctx变量。我的假设是,这个变量应该用 初始化EVP_PKEY_CTX_new,而这又需要 anEVP_PKEY *pkey和 an ENGINE *e。那些我不知道如何初始化,并且搜索文档让我非常困惑。

也许这些函数不是最简单的方法,我对这个库根本不熟悉,也没有密码学知识。我只关心将字符串转换为加密字符串的黑盒方法。

谢谢

Top*_*aco 5

正如评论中所证明的那样,RSA 对您来说是一个可以接受的选择。

当使用 OpenSSL 实现 RSA 时,加密需要执行以下步骤:

  • 加载公钥
  • 创建并初始化上下文
  • 指定填充
  • 加密

下面使用 RSA 和 OpenSSL 进行加密的实现在我的计算机上成功运行,并显示了如何调用函数(为了简单起见,没有进行异常处理):

#include <openssl/pem.h>
#include <string>
...

bool EncryptString(const std::string& InStr /*plaintext*/, const std::string& InPublicKey /*path to public key pem file*/, std::string& OutString /*ciphertext*/) {
    
    // Load key
    FILE* f = fopen(InPublicKey.c_str(), "r");
    EVP_PKEY* pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL);
    fclose(f);
    
    // Create/initialize context
    EVP_PKEY_CTX* ctx;
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
    EVP_PKEY_encrypt_init(ctx);

    // Specify padding: default is PKCS#1 v1.5
    // EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING); // for OAEP with SHA1 for both digests

    // Encryption
    size_t ciphertextLen;
    EVP_PKEY_encrypt(ctx, NULL, &ciphertextLen, (const unsigned char*)InStr.c_str(), InStr.size());
    unsigned char* ciphertext = (unsigned char*)OPENSSL_malloc(ciphertextLen);
    EVP_PKEY_encrypt(ctx, ciphertext, &ciphertextLen, (const unsigned char*)InStr.c_str(), InStr.size());
    OutString.assign((char*)ciphertext, ciphertextLen);

    // Release memory
    EVP_PKEY_free(pkey);
    EVP_PKEY_CTX_free(ctx);
    OPENSSL_free(ciphertext);

    return true; // add exception/error handling
}
Run Code Online (Sandbox Code Playgroud)

对于密文,必须考虑它是不代表真实文本的字节序列(例如,它可能包含 0x00 值)。如果要将密文表示为真实文本,则必须执行额外的二进制到文本编码,例如 Base64 编码。

该代码需要 X.509/SPKI 格式的 PEM 编码公钥。如果公钥具有 PKCS#1 格式,则可以使用PEM_read_RSAPublicKey()和导入EVP_PKEY_set1_RSA()