GMSSL :SM2椭圆曲线公钥密码算法——数字签名算法4

2021SC@SDUSC

目录

一、ECDSA介绍

二、代码分析


一、ECDSA介绍

ECDSA的全名是Elliptic Curve DSA,即椭圆曲线DSA。它是Digital Signature Algorithm (DSA)应用了椭圆曲线加密算法的变种。椭圆曲线算法的原理很复杂,但是具有很好的公开密钥算法特性,通过公钥无法逆向获得私钥。

与ECDSA相关的几个概念:

私钥:一个秘密号码,只有生成它的人知道。私钥本质上是一个随机生成的数字。在比特币中,一个人的私钥与区块链可以花这笔钱。在比特币中,私钥是单个无符号256位整数(32字节)。

公钥:与私钥相对应,但不需要保密的数字。公钥可以从私钥计算,但反之亦然。公钥可以用来确定签名是否是真实的(换句话说,用正确的密钥生成),而不需要泄露私钥。

ECDSA算法的两个优点:
1.在已知公钥的情况下,无法推导出该公钥对应的私钥。
2.可以通过某些方法来证明某人拥有一个公钥所对应的私钥,而此过程不会暴露关于私钥的任何信息。

ESCDA处理的实际上是消息的哈希值,而不是消息本身。哈希函数是可选择的,但这个哈希函数必须是一个

密码学安全的哈希函数。消息的哈希值需要截取一个固定的长度 Ln ,这个长度是 n (子群的阶)的二进制位数。截取后的哈希值是一个整数,我们记为 z。

  ECDSA签名流程:

  1. 在 {1,2.......,n-1}随机选择一个整数  k(  n​ 是子群的阶)
  2. 计算点 P=kG (其中 G是子群的基点)
  3. 计算  r=xp mod n(其中 xp是  P​ 点的横坐标)
  4. 如果 r=0  ,就重新选择一个k,然后再尝试一次同样的流程
  5. 计算  ​(其中dA 是Alice的私钥, k^n-1是  k在模n下的乘法逆元)
  6. 如果  s=0,就重新选择一个 k​ 然后再尝试一次同样的流程

 二元组(r,s)就是消息的签名

在多倍点运算中,已知多倍点与基点,求解倍数的问题称为椭圆曲线离散对数问题。对于一般椭圆曲线的离散对数问题,目前只存在指数级计算复杂度的求解方法。与大数分解问题及有限域上离散对数问题相比,椭圆曲线离散对数问题的求解难度要大得多。因此,在相同安全程度要求下,椭圆曲线密码较其他公钥密码所需的密钥规模要小得多。

ECDSA优点证明:

1.在已知公钥的情况下,无法推导出该公钥对应的私钥。

假设随机取一个0-256位之间的值x,计算x*P,最后的结果一定会落在曲线上的一点。假设该点为X,在公开X以及具体曲线的方程的情况下,能否反推出最初的随机值x?
证:寻找x的过程只能通过暴力计算,x的可能值为0~2^{256}-1中的一个,平均来说需要计算2^{128}次能够找到一次x值。那么问题来了,运行一次2^{128}的计算需要多长的时间呢?
假设我们使用的是超级计算机,主频为1THz(一秒钟可以进行一万亿次运算),从宇宙诞生的那一刻开始计算,到现在也就进行了2^{98}次。找到x值的概率为\frac {2^{98}}{2^{128}}=\frac 1{1073741824}。这个概率和下一秒地球被巨型陨石撞击而毁灭的概率接近。
在上面的案例中,x0~256位的一个随机数,可以作为私钥。X是随机椭圆曲线上的一个点,也就是由私钥生成的公钥,因此优点可以1得证。

但是密码学中,并不能使用上面介绍的实数域上的椭圆曲线。因为

1.实数域上的椭圆曲线是连续的,有无限个点,密码学要求有限点。
2.实数域上的椭圆曲线的运算有误差,不精确。密码学要求精确。

所以我们需要引入有限域上的椭圆曲线。
要证明优点2,还需要将随机椭圆曲线做一些改动:为了保证最后计算出来的点的坐标值相加是512位,secp256k1引入了一个对质数取模的机制。具体来说,随机椭圆曲线从变为了y^2 mod\ p=(x^3+ax+b)mod\ p其中P=2256-232-29-28-27-26-24-1,是小于2^{256}的最大质数。

 2.可以通过某些方法来证明某人拥有一个公钥所对应的私钥,而此过程不会暴露关于私钥的任何信息。

这部分类似于零知识证明:我知道你能买得起这个东西,但是我不知道你到底有多少钱。

 

添加一个hash函数,简单修改可以得出:hash(m,r\cdot P)\cdot n\cdot P+r\cdot P=(hash(m,r\cdot P)*(n+r))\cdot P使n*P=X,那么可知nx。此时方程为:hash(m,r\cdot P)\cdot X+r\cdot P=(hash(m,r\cdot P)*(x+r))\cdot P为了简单起见,我们记R=r\cdot Ps=hash(m,R)*x+r。此时方程化简为:hash(m,R)\cdot X+R=s\cdot P
假设:在已知m的情况下,如果能够提供一个sR满足上面的方程,就可以证明一个人拥有x。这个假设有一个前提,如果一个人不知道x,那么他就无法提供Rs满足上面的等式。
详细探讨这个前提:如果一个人不知道x,又想计算出sR,能够办到吗?结论是不能,首先我们无法从hash(m,R)计算出R(在有限时间内)。
还有一个问题:在已知Rs的情况下,能否计算出关于x的任何信息?
根据公式:s=hash(m,R)*x+r只要解出x=\frac {s-r}{hash(m,R)}就可以了。
要想计算出x,就需要知道r,但是在r没有公开的情况下,能计算出r吗?我们知道R=r*P;但是根据这个公式无法倒推出r,所以x也是安全的。

(这部分是我在网上看到的相对好理解的证明了,来源ECDSA(椭圆曲线数字签名算法) - 简书

二、代码分析

static ECDSA_SIG *sm2_do_sign(const unsigned char *dgst, int dgstlen,

 EC_KEY ecc算法中的秘钥结构体,里面包含私钥、公钥、曲线信息

一些返回空值,并直接结束的情况:

ec_group = EC_KEY_get0_group(ec_key);
	priv_key = EC_KEY_get0_private_key(ec_key);
	if (!ec_group || !priv_key) {
		SM2err(SM2_F_SM2_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
		return NULL;
	}

	if (!(ret = ECDSA_SIG_new())) {
		SM2err(SM2_F_SM2_DO_SIGN, ERR_R_MALLOC_FAILURE);
		return NULL;
	}
	ret->r = BN_new();
	ret->s = BN_new();
	ctx = BN_CTX_new();
	order = BN_new();
	e = BN_new();
	bn = BN_new();
	if (!ret->r || !ret->s || !ctx || !order || !e || !bn) {
		SM2err(SM2_F_SM2_DO_SIGN, ERR_R_MALLOC_FAILURE);
		goto end;
	}
	if (!EC_GROUP_get_order(ec_group, order, ctx)) {
		SM2err(SM2_F_SM2_DO_SIGN, ERR_R_EC_LIB);
		goto end;
	}
/* convert dgst to e */
	i = BN_num_bits(order);
#if 0
	if (8 * dgstlen > i) {
		dgstlen = (i + 7)/8;
	}
#endif
	if (!BN_bin2bn(dgst, dgstlen, e)) {
		SM2err(SM2_F_SM2_DO_SIGN, ERR_R_BN_LIB);
		goto end;
	}

 计算并判断随机数k

/* use or compute k and (kG).x */
		if (!in_k || !in_x) {
			if (!sm2_sign_setup(ec_key, ctx, &k, &ret->r)) {
				SM2err(SM2_F_SM2_DO_SIGN, ERR_R_ECDSA_LIB);
				goto end;
			}
			ck = k;
		} else {
			ck = in_k;
			if (!BN_copy(ret->r, in_x)) {
				SM2err(SM2_F_SM2_DO_SIGN, ERR_R_MALLOC_FAILURE);
				goto end;
			}
		}

计算大整数r,并确保大整数r的合理性:如果 r=0  ,就重新选择一个k

/* r = e + x (mod n) */
		if (!BN_mod_add(ret->r, ret->r, e, order, ctx)) {
			SM2err(SM2_F_SM2_DO_SIGN, ERR_R_BN_LIB);
			goto end;
		}

		if (!BN_mod_add(bn, ret->r, ck, order, ctx)) {
			SM2err(SM2_F_SM2_DO_SIGN, ERR_R_BN_LIB);
			goto end;
		}

		/* check r != 0 && r + k != n */
		if (BN_is_zero(ret->r) || BN_is_zero(bn)) {
			if (in_k && in_x) {
				SM2err(SM2_F_SM2_DO_SIGN, SM2_R_NEED_NEW_SETUP_VALUES);
				goto end;
			} else
				continue;
		}

计算大整数s,并判断其合理性,如果s等于0,重新选择k

/* s = ((1 + d)^-1 * (k - rd)) mod n */

	/* s = d'(k + r) - r mod n */
		if (!BN_mod_mul(ret->s, EC_KEY_get_ex_data(ec_key, sm2_sign_idx),
			bn, order, ctx)) {
			SM2err(SM2_F_SM2_DO_SIGN, ERR_R_BN_LIB);
			goto end;
		}
		if (!BN_mod_sub(ret->s, ret->s, ret->r, order, ctx)) {
			SM2err(SM2_F_SM2_DO_SIGN, ERR_R_BN_LIB);
			goto end;
		}
#endif

		/* check s != 0 */
		if (BN_is_zero(ret->s)) {
			if (in_k && in_x) {
				SM2err(SM2_F_SM2_DO_SIGN, SM2_R_NEED_NEW_SETUP_VALUES);
				goto end;
			}
		} else {
			break;
		}

 结束:

end:
	if (!ok) {
		ECDSA_SIG_free(ret);
		ret = NULL;
	}
	BN_free(k);
	BN_CTX_free(ctx);
	BN_free(order);
	BN_free(e);
	BN_free(bn);

	return ret;
}

猜你喜欢

转载自blog.csdn.net/vincy_yeha/article/details/121325140
今日推荐