月色和雪色之间,日月星辉之中。
如果想要实现签名结构体到无符号数组转换时,首先要了解几个函数
BN_bn2bin 函数是 OpenSSL 库中用于将大数(Big Number,简称 BN)转换为二进制数据的函数。该函数主要用于将 OpenSSL 中的大数对象表示(BIGNUM结构)转换为二进制表示形式,方便在计算和通信中的数据传输和存储。
以下是该函数的一般形式:
int BN_bn2bin(const BIGNUM *a, unsigned char *to);
其中:
a
是要转换的大数对象。to
是存储结果的缓冲区的指针。
该函数返回一个表示二进制数据的字节数。如果成功,返回的字节数等于大数 a
所需的字节数。如果传递的缓冲区大小不足以容纳整个大数,函数将返回 -1。
在 OpenSSL 库中,ECDSA_SIG_get0
函数是用于获取 ECDSA(Elliptic Curve Digital Signature Algorithm)签名结构体 ECDSA_SIG
中的 r 和 s 值的函数。ECDSA 签名通常由两个整数 r 和 s 组成,它们是通过对消息的哈希值使用私钥进行签名而生成的。
以下是该函数的一般形式:
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
其中:
sig
是 ECDSA 签名结构体。pr
是指向指针的指针,用于存储 r 值的BIGNUM
结构体指针。ps
是指向指针的指针,用于存储 s 值的BIGNUM
结构体指针。
有了这两个函数我们就可以实现签名结构体到无符号数组的转换了
int ecc_get_signature(ECDSA_SIG *sig, unsigned char *sig_hex)
{
unsigned char sig_buf[256];
int sig_len, sig_len1;
memset(sig_buf, 0, sizeof(sig_buf));
// 将 r 和 s 组合到固定长度的签名中
const BIGNUM *r, *s;
ECDSA_SIG_get0(sig, &r, &s);
sig_len = BN_bn2bin(r, sig_buf);
memcpy(sig_hex, sig_buf, sig_len);
sig_len1 = BN_bn2bin(s, sig_buf);
memcpy(sig_hex+sig_len, sig_buf, sig_len1);
printf("sig len is %d\n", sig_len + sig_len1);
return 0;
}
当实现无符号数组到签名结构体的转换时,需要了解下面几个函数
BN_bin2bn
函数是 OpenSSL 库中用于将二进制数据转换为大数对象 (BIGNUM
结构体) 的函数。该函数主要用于将二进制数据表示的整数转换为 OpenSSL 中的大数对象,以便进行加密、数字签名等操作。
以下是该函数的一般形式:
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
其中:
s
是指向包含二进制数据的缓冲区的指针。len
是缓冲区的字节数。ret
是一个可选的大数对象,如果不为NULL
,则函数会将结果存储在这个对象中;如果为NULL
,则函数会创建一个新的大数对象来存储结果。
函数返回一个指向 BIGNUM
结构体的指针,即包含了从二进制数据转换而来的大数对象。如果发生错误,返回值为 NULL
。
在 OpenSSL 库中,ECDSA_SIG_set0
函数用于设置 ECDSA(Elliptic Curve Digital Signature Algorithm)签名结构体 ECDSA_SIG
中的 r 和 s 值。这个函数允许开发者自定义 r 和 s 的值,通常在进行签名验证时使用。
以下是该函数的一般形式:
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
其中:
sig
是要设置 r 和 s 值的 ECDSA 签名结构体。r
是要设置的 r 值的BIGNUM
结构体指针。s
是要设置的 s 值的BIGNUM
结构体指针。
该函数返回一个整数值,成功返回 1,失败返回 0。
有了这两个函数我们就可以实现无符号数组到签名结构体的转换了:
/*
* 函数介绍:二进制数组转大数
* 输入参数:data 数组,len数组长度
* 输出参数:无
* 返回值 : 转换后的大数地址
*/
BIGNUM *ecc_bin2bn_new(unsigned char *data, int len)
{
BIGNUM *a = BN_new();
if(a == NULL)
{
return NULL;
}
if(BN_bin2bn(data, len, a) == NULL)
{
fprintf(stderr, "Bin to Bn failed\n");
BN_free(a);
return NULL;
}
return a;
}
int bin_to_sig(ECDSA_SIG *sig, unsigned char *signature, unsigned int signature_len)
{
int ret = 1;
BIGNUM *r = ecc_bin2bn_new(signature, signature_len/2);
if(r == NULL)
{
fprintf(stderr, "Error creating r BIGNUM.\n");
EC_KEY_free(ec_key);
ECDSA_SIG_free(sig);
return 1;
}
BIGNUM *s = ecc_bin2bn_new(signature+(signature_len/2), signature_len/2);
if(s == NULL)
{
fprintf(stderr, "Error creating s BIGNUM.\n");
BN_free(r);
return 1;
}
ret = ECDSA_SIG_set0(sig, r, s);
if(ret != 1)
{
fprintf(stderr, "Error Sig seting.\n");
BN_free(r);
BN_free(s);
return 1;
}
return 0;
}
上面的转换函数如果操作成功是不需要释放r和s的,当释放sig时,r和s也会被释放。