【问题标题】:How to generate a DSA key pair using OpenSSL libcrypto?如何使用 OpenSSL libcrypto 生成 DSA 密钥对?
【发布时间】:2019-05-03 11:13:31
【问题描述】:

我有以下代码尝试生成 DSA 密钥对。

OpenSSL_add_all_algorithms();
ctx=EVP_PKEY_CTX_new_id(EVP_PKEY_DSA,NULL); EVP_PKEY_keygen_init(ctx);
if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx,1024)<=0)      ERR_print_errors_fp(stderr);

我收到以下错误

3073906944:error:06089094:数字信封 例程:EVP_PKEY_CTX_ctrl:无效操作:pmeth_lib.c:398:

关于我做错了什么的任何线索?谢谢

【问题讨论】:

    标签: c openssl dsa


    【解决方案1】:

    你需要两个上下文;一个用于参数,一个用于实际的 keygen。您应该执行以下 两组 组操作:

    参数生成

    1. 使用EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL) 创建参数生成器
    2. 使用EVP_PKEY_CTX_set_dsa_paramgen_bits 设置参数生成器上下文中的位; 不是 keygen 上下文(如果你做对了,它甚至还不存在)。
    3. 使用EVP_PKEY_paramgen_init初始化参数生成器
    4. 最后,使用EVP_PKEY_paramgen生成参数。结果是一个EVP_PKEY 对象(我称之为pkey_params),其中包含即将生成的密钥的输入参数

    完成上述操作后,然后您将继续进行实际的密钥生成,这要简单得多:

    密钥生成

    1. 使用EVP_PKEY_CTX_new(pkey_params, NULL) 创建一个新上下文注意pkey_params 来自前面的一系列步骤。
    2. 使用EVP_PKEY_keygen_init初始化生成器上下文
    3. 使用EVP_PKEY_keygen 生成实际密钥

    一旦完成,除了最后的pkey 之外的所有资源都应该被正确地销毁。完成使用后释放最终密钥。就是这样。

    示例

    这没有任何错误检查,但操作顺序在这里很重要。所以要注意这一点。

    #include <stdio.h>
    #include <openssl/evp.h>
    #include <openssl/dsa.h>
    #include <openssl/pem.h>
    
    // required for any BIO standard stream IO.
    #include <openssl/applink.c>
    
    int main()
    {
        OPENSSL_init();
        OpenSSL_add_all_algorithms();
    
        // build parameters first
        EVP_PKEY_CTX *ctx_params = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);
        EVP_PKEY_paramgen_init(ctx_params);
        EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_params, 1024);
    
        EVP_PKEY* pkey_params = NULL;
        EVP_PKEY_paramgen(ctx_params, &pkey_params);
    
        // using parameters, build DSA keypair
        EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey_params, NULL);
        EVP_PKEY_keygen_init(ctx);
        
        EVP_PKEY* pkey = NULL;
        EVP_PKEY_keygen(ctx, &pkey);
    
        // cleanup everything but the final key
        EVP_PKEY_free(pkey_params);
        EVP_PKEY_CTX_free(ctx_params);
        EVP_PKEY_CTX_free(ctx);
    
        // TODO: whatever you want with the generator pkey. in this
        //  example we're just dumping the full unencrypted key to 
        //  stdout. 
        DSA* dsa = EVP_PKEY_get1_DSA(pkey);
        BIO* bio = BIO_new_fp(stdout, BIO_NOCLOSE);
        PEM_write_bio_DSAPrivateKey(bio, dsa, NULL, NULL, 0, NULL, NULL);
        BIO_flush(bio);
        DSA_free(dsa);
        EVP_PKEY_free(pkey);
    
        return 0;
    }
    

    输出(显然不同)

    -----BEGIN DSA PRIVATE KEY-----
    MIIBuwIBAAKBgQDJ+NoL8SZeTcqVA83WI7CCO6INYLw18DiALLMewPqXEPm99mof
    RX2693WJfpbWIjuHi/KXzH6vQ/0sQU+2z1CqgWhudVhQTofGNcsPrUbPpShTDMcP
    OoTx9dRb8rXWbxg7dfhGZ9z2pEhzRtPWpI2y81VxYhGXzVSC3zqW6+ec2QIVALaE
    fynSMqc56gPqDPZfRz1rlq3dAoGAL+vbbYu+gSy8zGqoLykqhG+Vl4/Eh/zQIWoB
    t64bfh7GU6o0wvgTQgcdGZK3/laa9Msa6J3iEGZcP3dd9x4fTQ5vzxDGIYikcC8I
    L8s2JbNi1Jxbr5dw3/sOKsdHIt95rFZ03+gMzaV+9pc8LpATnaXMtp5mmH+lRgsJ
    SIEdLqcCgYAVGpwZHaFUnttqQAf3/ohMtqIQG+RBp/yUf2EA7rcoHpA7bCBADApx
    mG5hH/F4dKjCSciKdHq4Ibf60ctAJNL2sobPKNArTMo/GNuzE+J79Wj6s/b7zwt7
    AF+27H9PAiXB08ftMmCSesXkX7v926EHRxDgSlVAgCPSfkXKNQn1XwIVALF2MF2N
    GRdMtFUxZFnIk2GnqC1R
    -----END DSA PRIVATE KEY-----
    

    【讨论】:

    • 你需要调用 EVP_PKEY_paramgen_init(ctx_params) 之前你做 EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_params, 1024);否则 EVP_PKEY_CTX_set_dsa_paramgen_bits 返回错误 (-1) 并且密钥长度将保持在默认值 2048 位。上面的代码缺乏任何错误处理,因此很容易错过此类问题。
    猜你喜欢
    • 2013-12-02
    • 2019-08-09
    • 2014-11-29
    • 2020-07-23
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2021-09-10
    • 1970-01-01
    相关资源
    最近更新 更多