Linux openssl 生成的签名结构与无符号数组相互转换

月色和雪色之间,日月星辉之中。

如果想要实现签名结构体到无符号数组转换时,首先要了解几个函数

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也会被释放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值