0

这是我为生成 openssl rsa 4096 位密钥而编写的 ac 函数。

    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 位密钥尝试了上述方法,得到了相同的结果和相同的大小不匹配

4

2 回答 2

2

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) vs PEM_write_bio_RSAPublicKey(PKCS#1) 编写的。

从 PEM 装甲的角度来看:

  • PKCS#1 公开:开始 RSA 公钥
  • X.509 SubjectPublicKeyInfo:开始公钥
  • PKCS#1 私有:开始 RSA 私钥
  • PKCS#8:开始私钥
于 2017-02-06T16:30:40.413 回答
0

我意识到我需要使用 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;
}
于 2017-02-06T18:42:41.880 回答