我正在try 使用OpenSSL并与我共享公钥以C语言执行字符串数据加密.我已经在网上搜索过,但没有成功找到有用的信息.

我的加密应该使用RSA PKCS 1填充和SHA 1 OAEP哈希.

我创建这个函数来加密

int rsaEvpEncrypt(EVP_PKEY* pkey, const char * data){
    EVP_PKEY_CTX * ctx = NULL;
    //EVP_PKEY * pkey = NULL;
    unsigned char * encrypted = NULL;
    size_t outlen = 0;
    const size_t inlen = strlen(data);

    tappa_printf("Print %d", 1);
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
    tappa_printf("Print %d", 2);
    if (!ctx) {
        cleanup(ctx, NULL, NULL, NULL);
        return 1000;
    }

    // Init encryption context.
    if (EVP_PKEY_encrypt_init(ctx) <= 0) { // <-SEGFAULT LINE
        cleanup(ctx, pkey, encrypted, NULL);
        return 5;
    }

    tappa_printf("Print %d", 3);
    // Defines padding
    if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
        cleanup(ctx, pkey, encrypted, NULL);
        return 6;
    }

    // Evaluating size for encrypted buffer and encrypting
    if (EVP_PKEY_encrypt(ctx, NULL, &outlen, (const unsigned char *) data, inlen) <= 0) {
        cleanup(ctx, pkey, encrypted, NULL);
        return 7;
    }

    encrypted = (unsigned char *)OPENSSL_malloc(outlen);
    tappa_printf("Print %d", 5);
    if (!encrypted) {
        cleanup(ctx, pkey, encrypted, NULL);
        return 8;
    }

    tappa_printf("Print %d", 6);
    if (EVP_PKEY_encrypt(ctx, encrypted, &outlen, (const unsigned char *)data, inlen) <= 0) {
        cleanup(ctx, pkey, encrypted, NULL);
        return 9;
    }

    tappa_print("\"ENCRYPTED: %s", (char *)encrypted);
}

这个功能用于生成随机密钥

int rsaEvpKeyGen(EVP_PKEY **outPK){
    EVP_PKEY_CTX * ctx = NULL;
    EVP_PKEY * pkey = NULL;
    EVP_PKEY * rkey = NULL;

    // const size_t inlen = strlen(argv[1]);
    size_t outlen = 0;
    size_t doutlen = 0;

    unsigned char * encrypted = NULL;
    unsigned char * decrypted = NULL;

    // Create context
     ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
     if (!ctx) {
         cleanup(ctx, pkey, encrypted, decrypted);
         return 1;
     }
     // Init key generator
     if (EVP_PKEY_keygen_init(ctx) <= 0) {
         cleanup(ctx, pkey, encrypted, decrypted);
         return 2;
     }
     int KEY_BITS = 2048;
     // Configure key generation
     if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KEY_BITS) <= 0) {
         cleanup(ctx, pkey, encrypted, decrypted);
         return 3;
     }
 
     // Create keys
     if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
         cleanup(ctx, pkey, encrypted, decrypted);
         return 4;
     }
     
    *outPK =pkey;
    return 0;
}

该代码按预期工作并按预期加密数据.然而,为了让我的应用程序正常工作,我需要能够使用外部生成的公钥.

在下面的代码中,我try 使用EVP_PKEY_new_raw_public_key从pub_key_stat创建EVP_PKEY,但它返回空

int rsaEvpKeyGen(EVP_PKEY **outPK){
    EVP_PKEY_CTX * ctx = NULL;
    EVP_PKEY * pkey = NULL;
    EVP_PKEY * rkey = NULL;

    // const size_t inlen = strlen(argv[1]);
    size_t outlen = 0;
    size_t doutlen = 0;

    unsigned char * encrypted = NULL;
    unsigned char * decrypted = NULL;
    const char *pub_key_str = "-----BEGIN PUBLIC KEY-----\n"
                              "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1WRkqlsZbmaNWbOZr/M4\n"
                              "ddwXKjmHUJ8zn9hy0WE15A8T4xjNuzJ/ATKbz20/2wVgFEGTWPNCUjkUvFzr3mhN\n"
                              "v/YJXo5iXQDP3M6rVv/w3SXaiR9C8yhDxWUz7WX/clmj7vDvk5Iydgq07gVScx+\n"
                              "5DBVbGAx10jHSDSa7f/NXMn9yNHad4hN0i1l+tsTB39CFsNeVFr349y4R8HA5Zma\n"
                              "EKseLc8iKzkwEQcuyMn4znaFpnOL0CmSrYB5K1E9zmmtDhMvDs540ZotcH/xpJiV\n"
                              "XEdQOWGFN6rryeAKP8y+sMRfQLxoiTg37YfsxTscf0gzKBizoamTF3TjRUNM55aE\n"
                              "BwIDAQAB\n"
                              "-----END PUBLIC KEY-----";

    pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_RSA,NULL, (const unsigned char *) pub_key_str,
                                       strlen(pub_key_str) );

    tappa_printf("PKEY is null %d",pkey == NULL);
  
    *outPK =pkey;
    
    return 0;
}

推荐答案

发布的公钥似乎无效.判断是否存在复制/粘贴错误或将密钥与另一面进行比较.

EVP_PKEY_new_raw_public_key()旨在导入原始密钥,因为它们在Ed 25519或X25519的上下文中使用.

可以按以下方式导入公共MBE密钥:

const char* spkiPem = "-----BEGIN PUBLIC KEY-----\n"
    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunF5aDa6HCfLMMI/MZLT\n"
    "5hDk304CU+ypFMFiBjowQdUMQKYHZ+fklB7GpLxCatxYJ/hZ7rjfHH3Klq20/Y1E\n"
    "bYDRopyTSfkrTzPzwsX4Ur/l25CtdQldhHCTMgwf/Ev/buBNobfzdZE+Dhdv5lQw\n"
    "KtjI43lDKvAi5kEet2TFwfJcJrBiRJeEcLfVgWTXGRQn7gngWKykUu5rS83eAU1x\n"
    "H9FLojQfyia89/EykiOO7/3UWwd+MATZ9HLjSx2/Lf3g2jr81eifEmYDlri/OZp4\n"
    "OhZu+0Bo1LXloCTe+vmIQ2YCX7EatUOuyQMt2Vwx4uV+d/A3DP6PtMGBKpF8St4i\n"
    "GwIDAQAB\n"
    "-----END PUBLIC KEY-----";

const unsigned char* key = (const unsigned char*)spkiPem;
size_t keylen = strlen(spkiPem);

OSSL_DECODER_CTX* dctx;
EVP_PKEY* pkey = NULL;

dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, "RSA", OSSL_KEYMGMT_SELECT_PUBLIC_KEY, NULL, NULL);
if (dctx == NULL) {
    // Error handling
}

if (!OSSL_DECODER_from_data(dctx, &key, &keylen)) {
    // Error handling
}

// Use pkey
...

此处使用的函数自OpenSSL 3.0起即可使用,有关更多详细信息,请参阅OSSL_DECODER_CTX_new_for_pkeyOSSL_DECODER_from_data().


为了完整性起见:要导入private RSA密钥,请使用OSSL_KEYMGMT_SELECT_KEYPAIR(而不是OSSL_KEYMGMT_SELECT_PUBLIC_KEY)作为 Select 器.对于BER编码按键,必须应用输入类型"DER"(而不是"PEM").例如,可以在OSSL_DECODER_from_data()的文档中找到例子.

C++相关问答推荐

在CIL中运行时,sscanf返回0

strftime函数中%s的历史意义是什么?为什么没有记录?

为什么已经设置的值在C中被重置为for循环条件中的新值?

来自stdarg.h的c中的va_args无法正常工作<>

编译的时候g++通常会比GCC慢很多吗?

警告:C++中数组下标的类型为‘char’[-Wchar-subpts]

试图从CSV文件中获取双精度值,但在C++中始终为空

解决S随机内存分配问题,实现跨进程高效数据共享

在创建动态泛型数组时,通过realloc对故障进行分段

如何使用C++在控制台中以彩色打印被阻止的客户端

使用nmake for程序比Hello World稍微复杂一些

如何使用FSeek和文件流指针在C中查找文件的前一个元素和前一个减go 一个元素

pthread_create的用法

C程序向服务器发送TCPRST

条件跳转或移动取决于未初始化值(S)/未初始化值由堆分配创建(Realloc)

宏观;S C调深度

为什么会出现此错误?二进制表达式的操作数无效

强制GCC始终加载常量(即只读),即使启用了优化

如何在C中处理流水线中的a、n命令?

try 判断长整数是否为素数