c - 函数未生成正确的 openssl rsa 密钥



这是我编写的用于生成openssl rsa 4096位密钥的c函数。

    bool rsa_gen_keys()
    {    
    int             ret = 0;
    RSA             *rsa = NULL;
    BIGNUM          *bignum = NULL;
    BIO             *bio_private = NULL;
    BIO             *bio_public = NULL;
    int              bits = 4096;
    unsigned long k = RSA_F4;
    bignum = BN_new();
    ret = BN_set_word(bignum,k);
    if(ret != 1){
        goto cleanup;
    }
    rsa = RSA_new();
    ret = RSA_generate_key_ex(rsa, bits, bignum, NULL);
    if(ret != 1){
        goto cleanup;
    }
    // write rsa private key to file
    bio_private = BIO_new_file("private_new.pem", "w+");
    ret = PEM_write_bio_RSAPrivateKey(bio_private, rsa, NULL, NULL, 0, NULL, NULL);
    BIO_flush(bio_private);
    // write rsa public key to file
    bio_public = BIO_new_file("public_new.pem", "w+");
    ret = PEM_write_bio_RSAPublicKey(bio_public, rsa);
    if(ret != 1){
        goto cleanup;
    }    
    BIO_flush(bio_public);
cleanup:
    BIO_free_all(bio_private);
    BIO_free_all(bio_public);
    RSA_free(rsa);
    BN_free(bignum);
    return ret;
}

上述函数生成的键似乎缺少某些内容。当我尝试在另一个程序中使用 public_new.pem 文件时,出现以下错误:

140286309791384:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:701:Expecting: PUBLIC KEY

但是,如果我使用 openssl 命令生成密钥文件,这些文件工作正常。

$openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:4096

我注意到从函数和命令行生成的密钥大小不匹配。这是一个线索,但是我需要在我的函数中更改什么来解决这个问题?

-rw-rw-r-- 1 3272 Feb  6 09:19 private_key.pem
-rw-rw-r-- 1  800 Feb  6 09:20 public_key.pem
-rw-rw-r-- 1 3243 Feb  6 10:43 private_new.pem
-rw-rw-r-- 1  775 Feb  6 10:43 public_new.pem
顺便说一句,我

用 2048 位密钥尝试了上述操作,我得到了相同的结果和相同的大小不匹配

openssl genpkey使用的是PEM_write_bio_PrivateKey(PKCS#8(而不是PEM_write_bio_RSAPrivateKey(PKCS#1(:https://github.com/openssl/openssl/blob/master/apps/genpkey.c#L161-L164。

没有展示你是如何生成public_key.pem的,但它可能是用PEM_write_bio_PUBKEY(X.509 SubjectPublicKeyInfo(和PEM_write_bio_RSAPublicKey(PKCS#1(编写的。

从PEM装甲的角度来看:

  • PKCS#1 公共:开始 RSA 公钥
  • X.509 主题公钥信息:开始公钥
  • PKCS#1 私有:开始 RSA 私钥
  • PKCS#8:开始私钥

我意识到我需要使用 PKCS#8 和 X.509 的键格式。所以我切换到EVP函数来生成它们。这是我最终使用的代码的一个非常简化的版本(没有错误检查(:

bool rsa_gen_keys() {
    int ret = 0;
    BIO *bio_private = NULL;
    BIO *bio_public = NULL;
    int bits = 4096;
    EVP_PKEY_CTX *ctx;
    EVP_PKEY *pkey = NULL;
    // Get the context
    ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
    if (!ctx)
        goto cleanup;
    // init keygen
    if (EVP_PKEY_keygen_init(ctx) <= 0)
        goto cleanup;
    // set the bit size 
    if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0)
    goto cleanup;
    /* Generate key */
    if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
        goto cleanup;

    // write rsa private key to file
    bio_private = BIO_new_file("private_new.pem", "w+");
    ret = PEM_write_bio_PrivateKey(bio_private, pkey, NULL, NULL, 0, NULL, NULL);
    if (ret != 1) {
        goto cleanup;
    }
    BIO_flush(bio_private);
    // write rsa public key to file
    bio_public = BIO_new_file("public_new.pem", "w+");
    //ret = PEM_write_bio_RSAPublicKey(bio_public, rsa);
    ret = PEM_write_bio_PUBKEY(bio_public, pkey);
    if (ret != 1) {
        goto cleanup;
    }
    BIO_flush(bio_public);

cleanup:
    if(bio_private) BIO_free_all(bio_private);
    if(bio_public) BIO_free_all(bio_public);
    if(pkey) EVP_PKEY_free(pkey);
    return ret;
}

相关内容

  • 没有找到相关文章

最新更新