使用openssl C library(not,同名命令行工具)使用公钥文件并知道算法,将短std::string加密到另一个std::string的推荐方法是什么?(在这种情况下,字符串不超过~C library个字节,密钥文件为.pem格式,算法可以是任何不对称的,如RSA/ECDSA/等).

我正在寻找编写一个函数与接口如下:bool EncryptString(const std::string& InStr, const std::string& InPublicKey, std::string& OutString).

翻阅文档,似乎可以使用EVP_PKEY_encrypt,它需要EVP_PKEY_CTX *ctx变量.我的假设是,这个变量应该用EVP_PKEY_CTX_new初始化,这又需要EVP_PKEY *pkeyENGINE *e.这些我不知道如何初始化,在文档中搜索会让我非常困惑.

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

谢谢

推荐答案

正如 comments 中所证明的那样,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

    // 加密法
    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
}

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

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

C++相关问答推荐

根据工具链文件中的定义替换单个函数定义

为什么PLT表中没有push指令?

从内联程序集调用Rust函数和调用约定

C语言中字符数组声明中的标准

将整数的.csv文件解析为C语言中的二维数组

如何调试LD_PRELOAD库中的构造函数?

为什么GCC在每次循环迭代时都会生成一个数组的mov&S使用[]访问数组?(-03,x86)

在一个小型玩具项目中实现终端历史记录功能

为什么我一直收到分段错误?

如何在C中使printf不刷新标准输出?

VS代码';S C/C++扩展称C23真关键字和假关键字未定义

CGO:如何防止在使用CGO在包中包含C头文件时出现多个定义...&q;错误?

Zlib:解压缩大文件导致";无效代码长度设置";错误

如何将大写/小写土耳其字母相互转换?

S,在 struct 中创建匿名静态缓冲区的最佳方式是什么?

生成一个半RNG,结果用C表示(无随机/随机)

C中的数组下标和指针算法给出了不同的结果

可以对两种 struct 类型中的任何一种进行操作的C函数

通过GTK';传递回调参数;s g_signal_connect()导致C中出现意外值

为什么 C 字符串并不总是等同于字符数组?