c语言调用openssl对内存中的pem私钥加密

最近要使用paho mqtt+tls,由于paho不支持从内存中加载私钥,但是支持加载经过加密后的私钥文件,而我们的私钥是存储在内存中的,所以需要写代码,将内存中的明文私钥调用openssl的api进行加密,之后落盘提供给mqtt。

gdb跟踪了下openssl的rsa命令,摘了部分代码出来,实现如下,仅供参考。
注1:本实现写死了使用3DES加密,实际可以根据需要进行配置。
注2:代码中的私钥是使用openssl自行生成的,仅用于示例

#include <stdio.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/x509.h>

const char* g_key =
    "-----BEGIN RSA PRIVATE KEY-----\n" \
    "MIIEpAIBAAKCAQEAsVV+dJhw5F8kWuFkQFg4ysKvq2KTZeivMhCxdbAhuUah5yfh\n" \
    "N2bLhhECzO2JnIWrldII8c3v7kNOyNwWeawdtWoc/aS0fpP1/sNfB2Os3RPOLcuL\n" \
    "739rVMq94RHcUj1G4ws60R9oC6wjTc6VmRDyFK8Kp54ok8iTp1g1fLlD5URKTzjn\n" \
    "mF6DWbEmYOvhVteYrsbvfD9uR8x+5B++YsxtRNfIfp1SCrPeLXn+cY9FTJyOwicP\n" \
    "f1az/dqLQ7XNqQGnMXgDfxXflTaYWPR47P/kcN2guO+Y7YvUbTc8vXrgbteKCB4p\n" \
    "liln2X9s3Ccds/k4s6hgAPvpE7SePPu9gX4B2QIDAQABAoIBAHUfh17Q1DcxU5ym\n" \
    "owUQf6oDfe0PNVUoopXJiru1MgDh0ssOfuSNgzyv/Y6GEM6NRq+0Qm4aWy6dy+pD\n" \
    "2qBP+ms4g59O6ltztBSoyxnhTmnRy+pZNrpfCO++3DxMBJ1YlXodj6JRQPH8pnCc\n" \
    "Uhf/pjPdDId6oUhCQKtVSjZvUpWYM3m/nQYcPnf/U0Yg2QDmjAg/a8nNcAlwONMK\n" \
    "8bO4PNJuxwr5O9eue+ZJZFGshT79ZP6zCr3/mdXWia5ieqf11fNzl6oCvQZHmdKK\n" \
    "MdX08/R8Rskh13Nq4oSocRtljfm33/sMvBMFkU4dwcLbihcqee7d5PJUxbOZj/eb\n" \
    "Zzcj2EUCgYEA6ReNrsPZJ89coeAANtsy8kH+IX5roBfnrRT0yJ9g41FjMA7liFnA\n" \
    "tjOSZCc1dlmjUoZsg+nH3+OeIK9t9oz3JMB5qGAO4ZwSsQrWaPRTcVxl4kDMG8o7\n" \
    "jBNd3BspJ4LkpkhjXI03ZJ428OiXlLfVYWgQsMTzSUXnTuvRc4Ll3lcCgYEAwsMa\n" \
    "hLfROoN3AhQ6H8bShY95lSFV3hRa+UMMP6WKm/3U3AnHEMgOFh3L+rj3eleZ9kvZ\n" \
    "z72AQbcfRIPrtpEHWI3//NN81YZ4Zn88ScDKb3zFUfUZEf/CxZU0hiM0lhvKVMuM\n" \
    "Ud2K4huF5h18PLE889Xqu+tYwbngDIIcEnfLo08CgYEAtwkm2fCy6n7756Vlpa31\n" \
    "UKUfsR971ihPZevJ2GzHAVocwFVCSxLnsGvI7dqYMcpr5NboCaIfsSElP9diSzQg\n" \
    "snxuTBi6NtF/IAU5nwsVJzR+UO+/F6dzoShoEPpHE97GPAkl9TxzHhDbZcvPlBnT\n" \
    "dnzodlcCECzTWXb2b3V/mlsCgYAR/DpirybfJGzFAGEttgqS0uEDaISpcW/FPO/Q\n" \
    "oNTf+tzBRRXg8th6Kl4/1Pzli1loaTDAAlvptaNpjFUkEth+0P4mttD8VuKfdHh4\n" \
    "xxjqmrcODng2NUwjOtgS2wVsJzzT/8gBd1fv8WK4EVj7sdJTIhn/KIiVuzh5bzpw\n" \
    "aief+QKBgQDY+a0DgS+Ons6iVK1F+2ZyqL99dB/ficwnYYIr95F/SBumi/bBo1mx\n" \
    "6b2vjpyIMz4zy3M3Doc9hfciWySZjruTqzWU/5yF2b9sBofvD1T92KfVvl8+WUhp\n" \
    "wcIjsBWU0yS7Hamn1OULe/R1lHVkpdtTiBkgfu1HAORa5X77c9kzCQ==\n" \
    "-----END RSA PRIVATE KEY-----";

static void free_rsa(RSA* rsa) {
    if (NULL != rsa) {
        RSA_free(rsa);
    }
}

static void free_bio(BIO* bio) {
    if (NULL != bio) {
        BIO_free(bio);
    }
}

int encrypt_privatekey_pem(const char* password, const char* privatekey_plain, 
        char** privatekey_cipher, uint32_t* cipher_length) {

    const char* cipher_name = "des-ede3-cbc";
    const EVP_CIPHER* enc = EVP_get_cipherbyname(cipher_name);
    if (enc == NULL) {
        printf("get enc method failed failed\n");
        return -1;
    }
    
    BIO* ibio = BIO_new_mem_buf(g_key, -1);
    if (NULL == ibio) {
        printf("read rsa from key bio failed\n");
        return -2;
    }

    RSA* rsa = PEM_read_bio_RSAPrivateKey(ibio, NULL, 0, NULL);
    BIO* obio = NULL;

    int rtn = 0;
    do {
        if (rsa == NULL) {
            printf("read rsa from key bio failed\n");
            rtn = -3;
            break;
        }

        obio = BIO_new(BIO_s_mem());
        if (NULL == obio) {
            printf("read rsa from key bio failed\n");
            rtn = -4;
            break;
        }

        int i = PEM_write_bio_RSAPrivateKey(obio, rsa, enc, NULL, 0, NULL, (void*)password);
        if (i <= 0) {
            printf("bio write rsa key failed\n");
            rtn = -5;
            break;
        }

        char* buf = NULL;
        long size = BIO_get_mem_data(obio, &buf);
        if (size == 0) {
            printf("bio read failed\n");
            rtn = -6;
            break;
        }
        *privatekey_cipher = malloc(size);
        memcpy(*privatekey_cipher, buf, size);
        *cipher_length = size;
        rtn = 0;
    } while (0);

    free_rsa(rsa);
    free_bio(ibio);
    free_bio(obio);
    return rtn;            
}

int main() {
    const char* password = "12345678";
    char* cipher = NULL;
    uint32_t cipher_size = 0; 
    int rtn = encrypt_privatekey_pem(password, g_key, &cipher, &cipher_size);
    if (rtn != 0) {
        printf("failed, rtn is %d\n", rtn);
        return -1;
    } else {
        printf("--successfully!\n");
    }
    free(cipher);
    return 0;
}

改代码对应的openssl命令:

openssl  rsa -des-ede3-cbc -in key.key -out key_enc.key -passout pass:12345678

我用的openssl版本是1.1.0-stable

附:

openssl  rsa -des-ede3-cbc -in key.key -out key_enc.key -passout pass:12345678

该命令生成的私钥文件依然是PEM格式的,但是里面的扩展字段是OpenSsl自定义的,而不是标准格式。虽然像mbedtls也支持openssl自定义的这种格式,但是最好还是使用像PKCS#8这种标准格式。

附一篇讨论openssl加密私钥格式的帖子: https://security.stackexchange.com/questions/39279/stronger-encryption-for-ssh-keys

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值