因为毕业设计需要,在网上找到的基于Openssl的SM2算法C语言实现代码,在安装好Openssl1.1.1,环境搭建完成后,进行编译出现如下问题:
严重性 代码 说明 项目 文件 行 禁止显示状态
错误(活动) E0393 不允许指针指向不完整的类类型 "struct ECDSA_SIG_st"
sm2.h——》
static ECDSA_SIG *sm2_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *in_k, const BIGNUM *in_r, EC_KEY *eckey)
{
int ok = 0, i;
BIGNUM *k=NULL, *s, *m=NULL,*tmp=NULL,*order=NULL;
const BIGNUM *ck;
BN_CTX *ctx = NULL;
const EC_GROUP *group;
ECDSA_SIG *ret;
//ECDSA_DATA *ecdsa;
const BIGNUM *priv_key;
BIGNUM *r,*x=NULL,*a=NULL; //new added
//ecdsa = ecdsa_check(eckey);
group = EC_KEY_get0_group(eckey);
priv_key = EC_KEY_get0_private_key(eckey);
if (group == NULL || priv_key == NULL /*|| ecdsa == NULL*/)
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
ret = ECDSA_SIG_new();
if (!ret)
{
ECDSAerr(EC_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
return NULL;
}
s = ret->s;
r = ret->r; /*这两句中的ret报错了*/
if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
(tmp = BN_new()) == NULL || (m = BN_new()) == NULL ||
(x = BN_new()) == NULL || (a = BN_new()) == NULL)
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EC_GROUP_get_order(group, order, ctx))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
goto err;
}
// for(i=0;i<dgst_len;i++)
// printf("%02X",dgst[i]);
// printf("\n");
i = BN_num_bits(order);
/* Need to truncate digest if it is too long: first truncate whole
* bytes.
*/
if (8 * dgst_len > i)
dgst_len = (i + 7)/8;
if (!BN_bin2bn(dgst, dgst_len, m))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
/* If still too long truncate remaining bits with a shift */
if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
// fprintf(stdout,"m: ");
// BNPrintf(m);
// fprintf(stdout,"\n");
do
{
if (in_k == NULL || in_r == NULL)
{
if (!sm2_sign_setup(eckey, ctx, &k, &x))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB);
goto err;
}
ck = k;
}
else
{
ck = in_k;
if (BN_copy(x, in_r) == NULL)
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
goto err;
}
}
//r=(e+x1) mod n
if (!BN_mod_add_quick(r, m, x, order))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
// BNPrintf(r);
// fprintf(stdout,"\n");
if(BN_is_zero(r) )
continue;
BN_add(tmp,r,ck);
if(BN_ucmp(tmp,order) == 0)
continue;
if (!BN_mod_mul(tmp, priv_key, r, order, ctx))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
if (!BN_mod_sub_quick(s, ck, tmp, order))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
BN_one(a);
//BN_set_word((a),1);
if (!BN_mod_add_quick(tmp, priv_key, a, order))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
/* compute the inverse of 1+dA */
if (!BN_mod_inverse(tmp, tmp, order, ctx))
{
ECDSAerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
goto err;
}
// BNPrintf(tmp);
// fprintf(stdout,"\n");
if (!BN_mod_mul(s, s, tmp, order, ctx))
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
if (BN_is_zero(s))
{
/* if k and r have been supplied by the caller
* don't to generate new k and r values */
if (in_k != NULL && in_r != NULL)
{
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_NEED_NEW_SETUP_VALUES);
goto err;
}
}
else
/* s != 0 => we have a valid signature */
break;
}
while (1);
ok = 1;
err:
if (!ok)
{
ECDSA_SIG_free(ret);
ret = NULL;
}
if (ctx)
BN_CTX_free(ctx);
if (m)
BN_clear_free(m);
if (tmp)
BN_clear_free(tmp);
if (order)
BN_free(order);
if (k)
BN_clear_free(k);
if (x)
BN_clear_free(x);
if (a)
BN_clear_free(a);
return ret;
}
ec.h——》
typedef struct ECDSA_SIG_st ECDSA_SIG;
/** Allocates and initialize a ECDSA_SIG structure
* \return pointer to a ECDSA_SIG structure or NULL if an error occurred
*/
ECDSA_SIG *ECDSA_SIG_new(void); /*主要涉及到的结构体定义声明部分*/
由于专业问题 好久没碰过C语言了,百度这个错误都说是由于函数定义了但是没声明导致的,还有说是由于头文件没有包含,但是这些都检查过了没问题,于是考虑是否是结构体中变量问题,ret中是否有 r、s两个变量
查找openssl官网找到了ECDSA_SIG_new函数的介绍:
ECDSA_SIG是一个不透明的结构,由两个 BIGNUM 组成,用于表示 ECDSA 特征码的 r和 s 值(请参见 X9.62 或 FIPS 186-2)。
ECDSA_SIG_new() 分配一个空的ECDSA_SIG结构。注意:在 OpenSSL 1.1.0 之前,r和s组件已初始化。
ECDSA_SIG_free() 释放ECDSA_SIG结构sig。
ECDSA_SIG_get0() 返回sig中包含的r和s值的内部指针,并分别将它们存储在pr和ps中。指针pr或ps可以为 NULL,在这种情况下,不会返回相应的值。
值r, s也可以分别由相应的函数 ECDSA_SIG_get0_r() 和 ECDSA_SIG_get0_s() 分别检索。
可以通过调用 ECDSA_SIG_set0() 并将 r 和s的新值作为参数传递给函数来设置r和s值。调用此函数会将值的内存管理传输到ECDSA_SIG对象,因此在调用此函数后,不应直接释放已传入的值。
但是还是没明白是否ECDSA_SIG这个空的结构体中r、s已经进行了初始化定义?
也尝试过使用ECDSA_SIG_get0或ECDSA_SIG_getr或ECDSA_SIG_gets 函数直接调取r、s但是都无果
本人是第一次接触Openssl 希望各位能帮忙解决这个问题