PEM_write_bio_RSAPrivateKey在FIPS模式下抛出keygen错误

时间:2017-12-13 22:50:03

标签: openssl private-key fips

我正在尝试生成一个2048位RSA私钥,该密钥在FIPS模式下使用AES256CBC密码加密。我在这里使用OpenSSL 1.0.2l。我尝试了最新的1.0.2快照,但没有任何区别。

我的问题是PEM_write_bio_RSAPrivateKey没有返回1并且我收到此错误:

26660:error:0607606B:digital envelope routines:PKCS5_v2_PBE_keyivgen:unsupported cipher:.\crypto\evp\p5_crpt2.c:229:
26660:error:06074078:digital envelope routines:EVP_PBE_CipherInit:keygen failure:.\crypto\evp\evp_pbe.c:197:
26660:error:23077073:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 algor cipherinit error:.\crypto\pkcs12\p12_decr.c:87:
26660:error:2306C067:PKCS12 routines:PKCS12_item_i2d_encrypt:encrypt error:.\crypto\pkcs12\p12_decr.c:188:
26660:error:2307D067:PKCS12 routines:PKCS8_encrypt:encrypt error:.\crypto\pkcs12\p12_p8e.c:96:

代码:

#include <stdio.h>
#include <tchar.h>
#include <cassert>
#include <memory>
#include <io.h>
#include <fcntl.h>
#include <iostream>
#include <string>
#include <openssl/crypto.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <openssl/x509.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/fips.h>

using std::unique_ptr;
#define ASSERT assert

using BN_ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>;
using RSA_ptr = std::unique_ptr<RSA, decltype(&::RSA_free)>;
using EVP_KEY_ptr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
using BIO_FILE_ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
using BIO_MEM_ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
using namespace std;

int main(int argc, char* argv[])
{
    int rc;
    //PART 1: Enter FIPS mode
    CRYPTO_malloc_init();
    if (0 == FIPS_mode())
    {
        printf("FIPS_mode says FIPS not set.\n");
    }

    rc = FIPS_mode_set(1);
    if (rc != 1)
    {
        printf("FIPS_mode_set failed.\n");

        ERR_load_crypto_strings();
        ERR_print_errors_fp(stderr);

        getchar();

        exit(1);
    }
    else
    {
        printf("FIPS_mode_set worked.\n");
    }

    //PART 2: Make the CA Private Key

    char filename_ca[] = "C:\\Users\\jlaird\\source\\repos\\keygen_sample\\Release\\ca.key.pem";
    char unsigned password_ca[] = "capass";

    RSA_ptr rsa(RSA_new(), ::RSA_free);
    BN_ptr bn(BN_new(), ::BN_free);

    //binary input/output file access
    BIO_FILE_ptr pem5(
        BIO_new_file(
            filename_ca, //file name
            "w+" //access mode
        ),
        ::BIO_free
    );

    BIO_MEM_ptr bio(BIO_new(BIO_s_mem()), ::BIO_free);

    //allocate a big number
    rc = BN_set_word(
        bn.get(),
        RSA_F4
    );

    //success is indicated by a value of 1
    if (rc == 1)
    {
        printf("BN_set_word worked\n");
    }
    else
    {
        printf("FAIL\n");
    }

    //Generate key
    rc = RSA_generate_key_ex(
        rsa.get(), //pointer to rsa key
        2048, //desired size of key in bits
        bn.get(), //get pointer to our big number
        NULL //progress callback (we don't care so NULL)
    );

    //success is indicated by a value of 1
    if (rc == 1)
    {
        printf("RSA_generate_key_ex worked\n");
    }
    else
    {
        printf("FAIL\n");
    }

    rc = RSA_print(bio.get(), rsa.get(), 0);

    //success is indicated by a value of 1
    if (rc == 1)
    {
        printf("RSA_print worked\n");
    }
    else
    {
        printf("FAIL\n");
    }

    BUF_MEM* mem = NULL;
    BIO_get_mem_ptr(bio.get(), &mem);
    ASSERT(mem != NULL);

    string s;
    if (mem->data && mem->length)
        s.assign(mem->data, mem->length);

    if (s.length())
        cout << s << endl;
    else
        cout << "Failed to retrieve key" << endl;

    // Convert RSA to PKEY
    //allocate RSA to PKEY memory
    EVP_KEY_ptr pkey(
        EVP_PKEY_new(),
        ::EVP_PKEY_free
    );

    printf("Convert RSA to PKEY.\n");

    //get our private key from the rsa key
    rc = EVP_PKEY_set1_RSA(
        pkey.get(),
        rsa.get()
    );

    //success is indicated by a value of 1
    if (rc == 1)
    {
        printf("EVP_PKEY_set1_RSA worked\n");
    }
    else
    {
        printf("FAIL\n");
    }

    printf("get our private key from the rsa key.\n");

    //Write private key
    rc = PEM_write_bio_RSAPrivateKey(
        pem5.get(), //binary file pointer
        rsa.get(), //key in use
        EVP_aes_256_cbc(), //cipher
        NULL,
        0,
        NULL,
        password_ca
    );

    //success is indicated by a value of 1
    if (rc == 1)
    {
        printf("PEM_write_bio_RSAPrivateKey worked\n");
    }
    else
    {
        printf("PEM_write_bio_RSAPrivateKey FAIL\n");
        ERR_load_crypto_strings();
        ERR_print_errors_fp(stderr);
    }

    printf("done!.\n");
    getchar();

    return 0;
}

程序的完整输出:

FIPS_mode says FIPS not set.
FIPS_mode_set worked.
BN_set_word worked
RSA_generate_key_ex worked
RSA_print worked
Private-Key: (2048 bit)
modulus:
    00:c4:30:0c:a4:ce:25:6c:13:e9:b8:6b:aa:f4:50:
    e4:f4:bb:af:ae:cd:4a:b8:0e:a0:35:01:74:ac:d0:
    58:96:cc:0d:48:0e:51:6a:00:77:5e:6b:f6:33:0a:
    10:1c:fc:8c:5e:67:5c:d3:c0:e2:1b:98:d8:98:9e:
    82:83:88:83:4e:35:6d:4e:a5:b4:3f:09:6b:56:b8:
    d2:b1:67:3f:d2:c6:79:f6:90:5e:18:1b:39:98:9d:
    89:f9:cd:1d:21:d9:0f:bd:ae:83:38:17:83:98:9f:
    6b:53:16:05:b3:dd:4f:00:f5:d6:27:83:84:c2:ce:
    03:aa:5e:0f:ba:51:a9:50:1d:35:3f:8c:76:8a:bb:
    78:54:ff:e3:11:9d:7c:fd:09:ac:5e:8c:57:84:ca:
    20:11:92:39:34:e5:8a:15:68:33:c1:90:e2:d2:03:
    d2:8b:e4:b6:77:5f:2c:17:93:81:cf:0f:5c:13:d2:
    bc:ae:72:2d:47:eb:ca:0d:cd:19:76:4d:75:5d:cd:
    70:1b:aa:c4:96:cf:e7:8f:d3:36:83:6f:c3:30:65:
    02:b2:cc:9a:c0:a5:5b:bb:53:09:66:01:12:4e:d7:
    6c:44:e8:62:a4:24:a6:21:bf:da:7e:d5:68:c4:94:
    40:7f:ba:25:47:92:ea:97:fd:99:17:db:76:b9:69:
    52:99
publicExponent: 65537 (0x10001)
privateExponent:
    11:1f:1e:63:5d:a8:4f:6b:d7:78:64:51:19:9c:5b:
    b6:ee:10:51:81:92:15:49:15:7b:3a:c2:cb:78:2d:
    5b:0f:b8:d3:02:88:e1:66:e4:04:06:09:09:00:46:
    52:b9:49:a8:cd:7d:80:ef:72:ec:34:a5:26:80:a2:
    e4:46:cc:2a:cd:a7:d9:f6:c5:29:c1:31:30:72:d5:
    d4:6c:ad:d9:bf:bf:92:20:9c:4d:9f:46:a2:06:91:
    ad:8e:d4:8d:89:2b:82:02:d2:69:d9:47:7f:50:de:
    65:74:65:10:02:ee:eb:a7:08:c7:0f:07:cd:96:7c:
    24:68:ac:17:b7:1b:bf:25:7e:46:52:5b:33:13:9c:
    0b:48:1f:f9:47:cf:09:ed:5d:4d:18:85:d2:49:30:
    94:1c:bb:25:7b:bc:63:31:93:c3:17:f7:b8:d5:77:
    6d:2b:36:de:b1:d4:07:e4:ce:9c:ca:29:ef:dd:0a:
    3f:60:4a:80:ac:a8:8e:81:95:21:35:6a:49:c5:0c:
    e3:2f:50:59:7e:c3:73:3e:ac:98:29:15:57:4b:ad:
    fc:70:88:9d:fc:50:39:69:a9:a4:ee:80:db:4e:36:
    70:dd:a1:d6:2c:79:77:9d:0d:c3:ef:d2:5e:15:d4:
    77:e3:b1:20:12:c6:59:6e:41:d9:ef:9e:8b:a4:13:
    19
prime1:
    00:e7:9c:27:77:b9:5c:72:0e:81:2e:fb:2f:46:e4:
    a8:0e:af:31:63:31:86:d2:2c:71:46:1f:2a:fd:30:
    5c:44:45:02:8b:eb:0e:b7:50:9d:25:e2:0b:3a:07:
    2f:74:84:48:f0:d3:83:68:bf:6f:e1:59:c4:b4:88:
    40:0d:89:57:6d:fe:23:82:af:de:b4:25:ac:6c:76:
    26:ce:c7:e1:b7:f9:78:9d:2b:a7:87:25:ce:db:9a:
    b4:b7:cb:e6:3d:a1:33:a7:dc:15:a3:5a:99:7c:cc:
    b1:2d:e9:c3:72:a3:e6:25:f0:5e:c5:77:47:9e:2c:
    8f:51:da:81:62:79:41:98:fd
prime2:
    00:d8:d8:f7:22:11:96:35:07:fb:30:8b:70:d0:bf:
    fc:7e:ab:2d:9d:f8:94:92:12:74:b4:69:97:1b:5d:
    c3:7e:a9:d7:8d:23:04:0b:56:04:4f:fa:40:3d:cf:
    18:2f:53:bc:a6:bc:23:19:d1:4f:3e:36:90:d6:f0:
    e6:4a:4e:8e:6f:12:87:52:51:f0:90:53:d0:f8:44:
    d6:8d:9b:35:5a:7d:09:a8:0e:9b:87:76:8a:94:5e:
    ed:a1:22:80:71:8b:98:e6:f0:09:91:70:b1:a5:e4:
    9f:12:96:be:a6:a9:74:8a:83:e4:33:cd:b3:db:ff:
    71:cd:37:b0:ef:61:3a:10:cd
exponent1:
    61:42:98:ec:54:e1:b6:5f:d2:ed:e8:bb:6c:b8:de:
    bd:f3:e1:f8:76:b6:d8:11:a3:ab:bf:b0:ec:cb:df:
    23:28:1b:ae:a8:11:f0:f7:20:56:e5:3a:b3:ae:8a:
    c6:12:3b:13:2e:af:53:50:78:ea:18:29:5b:6a:90:
    03:5f:36:60:d1:45:16:3f:46:75:3e:10:cf:27:3a:
    9a:c1:23:4f:7f:aa:9f:cd:d2:37:15:b0:6d:55:e5:
    27:fd:ae:fd:18:71:b9:be:d9:33:54:fb:79:85:f7:
    ad:81:29:fb:3d:4a:8b:8a:0a:32:40:29:ca:09:8a:
    51:e4:41:4b:1a:02:6a:fd
exponent2:
    00:d2:82:05:9f:60:1d:46:4c:02:30:85:1d:36:b9:
    39:9f:aa:03:75:b8:6c:5a:45:6a:5f:fd:a5:40:5e:
    cc:ba:78:9c:95:19:aa:02:6b:35:72:82:88:bc:b7:
    ff:4d:6a:67:d8:21:09:9e:35:90:4c:df:e1:c9:97:
    40:a8:60:0c:6b:8d:3c:2a:d0:fa:cc:d1:61:2a:b2:
    80:ea:25:03:2d:5d:f6:f2:db:83:66:84:d0:50:ea:
    ba:9a:d3:88:87:31:b2:74:76:0f:83:ce:37:d6:c8:
    d3:17:d3:99:2e:e7:90:08:2b:b3:6c:0a:c4:10:cc:
    b1:28:3c:69:1a:69:73:59:fd
coefficient:
    00:88:66:c0:36:fa:1b:e8:cc:d7:25:13:34:fb:de:
    cc:cf:29:1c:e7:b0:0e:26:a1:e2:04:43:c4:a1:17:
    41:c0:bc:6a:11:3f:03:67:ae:9a:23:b0:d6:ec:9e:
    7b:6c:cf:ce:ba:35:4f:7a:d3:e8:49:45:48:e6:cd:
    ea:83:ee:76:34:f0:53:6b:90:72:67:41:a5:0c:ae:
    02:25:4e:c5:da:b6:01:fc:13:9f:eb:8d:c4:0b:8d:
    a7:a0:4d:c8:8e:a0:56:00:51:31:c9:50:03:37:ab:
    85:8f:bf:3c:4e:af:17:11:7a:38:6e:be:ac:94:1a:
    dc:54:8e:07:62:fc:b8:1f:04

Convert RSA to PKEY.
EVP_PKEY_set1_RSA worked
get our private key from the rsa key.
PEM_write_bio_RSAPrivateKey FAIL
26660:error:0607606B:digital envelope routines:PKCS5_v2_PBE_keyivgen:unsupported cipher:.\crypto\evp\p5_crpt2.c:229:
26660:error:06074078:digital envelope routines:EVP_PBE_CipherInit:keygen failure:.\crypto\evp\evp_pbe.c:197:
26660:error:23077073:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 algor cipherinit error:.\crypto\pkcs12\p12_decr.c:87:
26660:error:2306C067:PKCS12 routines:PKCS12_item_i2d_encrypt:encrypt error:.\crypto\pkcs12\p12_decr.c:188:
26660:error:2307D067:PKCS12 routines:PKCS8_encrypt:encrypt error:.\crypto\pkcs12\p12_p8e.c:96:
done!.

^我不知道这意味着什么。它就像使用FIPS模式一样不会允许该算法!它会允许什么?

1 个答案:

答案 0 :(得分:0)

好的,所以我在更多地考虑错误并发现错误之后想出了这个:

https://wiki.openssl.org/index.php/Manual:OpenSSL_add_all_algorithms(3)

如果在调用FIPS_mode_set(1)后调用OpenSSL_add_all_algorithms(),则PEM_write_bio_RSAPrivateKey可以正常工作。也就是说,这不会引发错误:

rc = PEM_write_bio_RSAPrivateKey(
        pem5.get(), //binary file pointer
        rsa.get(), //key in use
        EVP_aes_256_cbc(), //cipher to use
        NULL,
        0,
        NULL,
        password_ca
    );

然后我完成后调用EVP_cleanup()以从OpenSSL_add_all_algorithms()调用中释放内存。