使用原始EC生成的密钥在C中进行OpenSSL签名和验证

使用原始EC生成的密钥在C中进行OpenSSL签名和验证,c,openssl,cryptography,public-key-encryption,C,Openssl,Cryptography,Public Key Encryption,我生成EC私钥作为随机数,EC公钥作为随机数生成器的乘法 现在我想使用这些密钥对消息进行签名和验证,但有关验证的操作失败。你有什么办法解决这个问题吗 我正在使用OpenSSL 1.0.0进行一些限制。我不能换新的 #include <openssl/ec.h> #include <openssl/rand.h> #include <openssl/bn.h> #include <openssl/sha.h> #include <openssl

我生成EC私钥作为随机数,EC公钥作为随机数生成器的乘法

现在我想使用这些密钥对消息进行签名和验证,但有关验证的操作失败。你有什么办法解决这个问题吗

我正在使用OpenSSL 1.0.0进行一些限制。我不能换新的

#include <openssl/ec.h>
#include <openssl/rand.h>
#include <openssl/bn.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>

int main()
{
    BN_CTX *ctx;
    EC_GROUP *curve;
    BIGNUM *q = NULL;

    EVP_MD_CTX *hashctx;
    unsigned int ol;
    unsigned char fh[EVP_MAX_MD_SIZE];

    BIGNUM *priv = NULL;
    EC_POINT *G, *pub;

    EC_KEY *keypriv = EC_KEY_new();
    EC_KEY *keypub = EC_KEY_new();

    unsigned char *s1 = "hello";

    // makes all algorithms available to the EVP* routines
    OpenSSL_add_all_algorithms();

    // load the error strings for ERR_error_string
    ERR_load_crypto_strings();
    hashctx = EVP_MD_CTX_new();

    const EVP_MD *hashptr = EVP_get_digestbyname("SHA256");

    EVP_DigestInit_ex(hashctx, hashptr, NULL);
    EVP_DigestUpdate(hashctx, s1, strlen(s1));
    EVP_DigestFinal_ex(hashctx, fh, &ol);

    // seed PRNG
    if (RAND_load_file("/dev/urandom", 256) < 64)
    {
        printf("Can't seed PRNG!\n");
        abort();
    }

    ctx = BN_CTX_new();
    q   = BN_new();

    // read the generator and order of the curve
    curve   = EC_GROUP_new_by_curve_name(NID_secp160r1);
    G       = EC_GROUP_get0_generator(curve);
    EC_GROUP_get_order(curve, q, ctx);

    // precompute multiples of g (faster multiplications)
    EC_GROUP_precompute_mult(curve, ctx);

    EC_KEY_set_group(keypriv, curve);

    pub     = EC_POINT_new(curve);
    priv    = BN_new();
    BN_rand_range(priv, q);
    EC_POINT_mul(curve, pub, NULL, G, priv, ctx);


    EC_KEY_set_private_key(keypriv, priv);
    EC_KEY_set_public_key(keypub, pub);


    ECDSA_SIG *signature = ECDSA_do_sign(fh, 64, keypriv);
    if (NULL == signature)
    {
        printf("Failed to generate EC Signature\n");
    }
    else
    {
        int verify_status = ECDSA_do_verify(fh, 64, signature, keypub);
        const int verify_success = 1;
        if (verify_success != verify_status)
        {
            printf("Failed to verify EC Signature\n");
        }
        else
        {
            printf("Verifed EC Signature\n");
        }
        ECDSA_SIG_free(signature);
    }

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main()
{
BN_CTX*CTX;
EC_组*曲线;
BIGNUM*q=NULL;
执行副总裁MD CTX*hashctx;
无符号整数;
无符号字符fh[EVP_MAX_mdu SIZE];
BIGNUM*priv=NULL;
欧共体点*G,*pub;
EC_KEY*keypriv=EC_KEY_new();
EC_KEY*keypub=EC_KEY_new();
未签名字符*s1=“你好”;
//使所有算法可用于EVP*例程
OpenSSL_添加_所有算法();
//加载ERR\u error\u字符串的错误字符串
错误加载加密字符串();
hashctx=EVP_MD_CTX_new();
const EVP_MD*hashptr=EVP_get_digestbyname(“SHA256”);
EVP_DigestInit_ex(hashctx、hashptr、NULL);
执行副总裁DigestUpdate(hashctx,s1,strlen(s1));
执行副总裁(hashctx、fh和ol);
//种子PRNG
if(随机加载文件(“/dev/uradom”,256)<64)
{
printf(“无法为PRNG种子!\n”);
中止();
}
ctx=BN_ctx_new();
q=BN_new();
//读取曲线的生成器和顺序
curve=EC_GROUP_new_by_curve_name(NID_secp160r1);
G=EC_组_get0_发生器(曲线);
EC_组_获得_顺序(曲线,q,ctx);
//预计算g的倍数(更快的乘法)
电子计算机组(曲线,ctx);
EC_键集_组(键priv,曲线);
pub=EC_点_新(曲线);
priv=BN_new();
BN_和rand_范围(priv,q);
EC_POINT_mul(曲线、pub、NULL、G、priv、ctx);
EC_KEY_set_private_KEY(私钥、私钥);
EC_KEY_set_public_KEY(keypub,pub);
ECDSA_SIG*签名=ECDSA_do_签名(fh,64,keypriv);
if(NULL==签名)
{
printf(“未能生成EC签名\n”);
}
其他的
{
int verify_status=ECDSA_do_verify(fh,64,签名,密钥发布);
const int verify_success=1;
如果(验证\u成功!=验证\u状态)
{
printf(“验证EC签名失败\n”);
}
其他的
{
printf(“验证EC签名”);
}
ECDSA_SIG_free(签名);
}
返回0;
}

我只需将代码中公钥的EC组设置为:

EC_KEY_set_group(keypub, curve);
顺便说一句,我希望这个Q/A也能回答接受答案中的第一条评论:

如何仅使用eckey的公共部分进行验证