1.基础知识

1.1 群

定义

群是集合G和G上的二元运算∘\circ∘,简记为(G,∘)(G,\circ)(G,∘)。集合G={x∣x∈G}G=\{x|x\in G\}G={x∣x∈G}和GGG上的二元运算∘\circ∘满足如下性质:
1.封闭性:对∀a,b∈G\forall a,b \in G∀a,b∈G,有a∘b∈Ga\circ b \in Ga∘b∈G。
2.结合性:对∀a,b,c∈G\forall a,b,c \in G∀a,b,c∈G,有a∘b∘c=a∘(b∘c)a\circ b\circ c=a\circ (b\circ c)a∘b∘c=a∘(b∘c)。
3.单位元:存在单位元111,使得a∘1=1∘a=aa\circ 1=1\circ a=aa∘1=1∘a=a。
4.有逆元:对∀a∈G\forall a \in G∀a∈G,∃a−1∈G\exists a^{-1} \in G∃a−1∈G,使得a−1∘a=a∘a−1=1a^{-1}\circ a=a\circ a^{-1} =1a−1∘a=a∘a−1=1。
若对∀a,b∈G\forall a,b \in G∀a,b∈G,有a∘b=b∘aa\circ b=b\circ aa∘b=b∘a,则称群GGG为阿贝尔群(可交换群)。

例子

1.Zn={0,1,2,⋯,n−1}Z_n=\{0,1,2,\cdots,n-1\}Zn​={0,1,2,⋯,n−1},∘=+modn\circ=+\ mod \ n∘=+ mod n。单位元为000。
2.Zn∗={ai∣ai∈{0,1,2,⋯,n−1}andgcd(ai,n)=1}Z_n^*=\{a_i|a_i \in\{0,1,2,\cdots,n-1\}\ and \ gcd(a_i,n)=1\}Zn∗​={ai​∣ai​∈{0,1,2,⋯,n−1} and gcd(ai​,n)=1},∘=×modn\circ=\times\ mod \ n∘=× mod n。单位元为111。若n为素数,则Zn∗={1,2,⋯,n−1}Z_n^*=\{1,2,\cdots,n-1\}Zn∗​={1,2,⋯,n−1}。证明:根据定义推导,显然。
3.(R,+)(R,+)(R,+)是群,单位元是0。
4.(R去除0,×)(R去除0,\times)(R去除0,×)是群,单位元是1。

1.2 有限群

有限群和群的阶

群(G,∘)(G,\circ)(G,∘)是有限的,若它有有限个元素。我们称群的元素数目为群的阶,记为∣G∣|G|∣G∣。

元素的阶

群(G,∘)(G,\circ)(G,∘)中元素α\alphaα的阶为满足αk=1,αk=α∘α∘⋯∘α⏟k\alpha^k=1,\alpha^k=\underbrace{\alpha \circ \alpha \circ \cdots \circ \alpha}_kαk=1,αk=kα∘α∘⋯∘α​​的最小正整数kkk,记为ord(α)ord(\alpha)ord(α)。

有限循环群和生成元

有限群(G,∘)(G,\circ)(G,∘),若存在一个元素α\alphaα,其阶为∣G∣|G|∣G∣,则称此有限群为循环群,其中阶为∣G∣|G|∣G∣的元素称为生成元。

1.3 有用的结论

Lagrange’s 定理

GGG是有限群,若HHH是GGG的子群,则∣H∣整除∣G∣|H|整除|G|∣H∣整除∣G∣。

定理1

若(G,∘)(G,\circ)(G,∘)是一个有限群,则对于∀α∈G\forall \alpha \in G∀α∈G,存在s≤∣G∣s\le |G|s≤∣G∣,使得(α1,α2,⋯,αs)(\alpha ^1,\alpha^2,\cdots,\alpha^s)(α1,α2,⋯,αs)是一个有限循环群,记为<α><\alpha><α>,其中α\alphaα为此子群的生成元,ord(a)=sord(a)=sord(a)=s。

定理2

若(G,∘)(G,\circ)(G,∘)是一个有限群,则1.对∀α∈G\forall \alpha \in G∀α∈G,有α∣G∣=1\alpha^{|G|}=1α∣G∣=1;2.对∀α∈G\forall \alpha \in G∀α∈G,ord(α)ord(\alpha)ord(α)整除∣G∣|G|∣G∣。
证明:由Lagrange’s 定理即可得到。

推论1

(G,∘)(G,\circ)(G,∘)是一个有限群,若其阶为素数,则(G,∘)(G,\circ)(G,∘)是一个有限循环群。
证明:若其阶为素数,则除去单位元的其他元素,其阶都为|G|。

推论2

若(G,∘)(G,\circ)(G,∘)是一个有限循环群群,则1.生成元的数目为Φ(∣G∣)\Phi(|G|)Φ(∣G∣);2.若∣G∣|G|∣G∣是素数,则除单位元外,GGG中所有元素都是生成元。

结论

若p是素数,则Zp∗={1,2,⋯,p−1}Z_p^*=\{1,2,\cdots,p-1\}Zp∗​={1,2,⋯,p−1},∘=×modp\circ=\times\ mod \ p∘=× mod p。结论是Zp∗Z_p^*Zp∗​是有限循环群,显然也是可交换群。(此结论如何证明,未知)

2 离散对数问题

2.1 一般性定义

给定一个有限循环群(G,∘)(G,\circ)(G,∘),阶∣G∣|G|∣G∣=nnn,假设α\alphaα是G的生成元,则离散对数问题描述为:给定β∈G\beta \in Gβ∈G,求xxx使得αx=β\alpha ^x = \betaαx=β,其中1≤x≤n1 \le x \le n1≤x≤n。

2.2 ZnZ_nZn​上的定义

Zn={0,1,2,⋯,n−1}Z_n=\{0,1,2,\cdots,n-1\}Zn​={0,1,2,⋯,n−1},∘=+modn\circ=+\ mod \ n∘=+ mod n。则其阶为nnn,则生成元的数目为Φ(n)\Phi(n)Φ(n),其生成元为与nnn互质的数。其离散对数问题描述如下:假设α\alphaα是ZnZ_nZn​的生成元,给定β∈G\beta \in Gβ∈G,求xxx使得αx=β\alpha ^x = \betaαx=β,这里αx=α+α+⋯+α⏟xmodn=x⋅αmodn\alpha ^x=\underbrace{\alpha + \alpha + \cdots + \alpha }_x \ mod \ n=x \cdot \alpha \ mod \ nαx=xα+α+⋯+α​​ mod n=x⋅α mod n,所以αx=β\alpha ^x = \betaαx=β表达为x⋅α≡βmodnx \cdot \alpha \equiv \beta \ mod \ nx⋅α≡β mod n,其中1≤x≤n1 \le x \le n1≤x≤n。在这里唯一需要说明的在ZnZ_nZn​上计算离散对数问题是简单的:这里x=α−1⋅βx=\alpha^{-1}\cdot \betax=α−1⋅β,其中α−1⋅α≡1modn\alpha^{-1} \cdot \alpha \equiv 1 \ mod \ nα−1⋅α≡1 mod n。

2.3 Zp∗Z_p^*Zp∗​上的定义

ppp是素数,Zp∗={1,2,⋯,p−1}Z_p^*=\{1,2,\cdots,p-1\}Zp∗​={1,2,⋯,p−1},∘=×modp\circ=\times\ mod \ p∘=× mod p,则其阶为p−1p-1p−1。其离散对数问题描述如下:假设α\alphaα是Zp∗Z_p^*Zp∗​的生成元,给定β∈G\beta \in Gβ∈G,求xxx使得αx=β\alpha ^x = \betaαx=β,将∘=×modp\circ=\times\ mod \ p∘=× mod p代入得到αx≡βmodp\alpha ^x \equiv \beta \ mod \ pαx≡β mod p,其中1≤x≤(p−1)1 \le x \le (p-1)1≤x≤(p−1)。在这里唯一需要说明的在Zp∗Z_p^*Zp∗​上计算离散对数问题是困难的。

2.4 基于离散对数问题的密钥交换协议(Diffie-Hellman)

基于有限循环群 Zp∗Z_p^*Zp∗​的DH算法

1.初始化:Zp∗Z_p^*Zp∗​的参数,通常称为域参数

选择一个大素数ppp
选择一个整数α∈{2,3,⋯,p−1}\alpha \in \{2,3,\cdots,p-1\}α∈{2,3,⋯,p−1},其中α\alphaα为生成元。
发布域参数:ppp和α\alphaα。

2.密钥交换

Alice:随机选择一个a∈{2,3,⋯,p−1}a \in \{2,3,\cdots,p-1\}a∈{2,3,⋯,p−1},计算A=αamodpA = \alpha^a \ mod \ pA=αa mod p,将AAA通过公共网路传送给Bob。
Bob:随机选择一个b∈{2,3,⋯,p−1}b \in \{2,3,\cdots,p-1\}b∈{2,3,⋯,p−1},计算B=αbmodpB = \alpha^b \ mod \ pB=αb mod p,将BBB通过公共网路传送给Alice。

3.密钥计算

Alice:Kab=Ba=αabmodpK_{ab}=B^a=\alpha^{ab} \ mod \ pKab​=Ba=αab mod p
Bob:Kab=Ab=αabmodpK_{ab}=A^b=\alpha^{ab} \ mod \ pKab​=Ab=αab mod p

此算法目的用于在不安全的公共网络上双方协商密钥。关键点在于通过A=αamodpA = \alpha^a \ mod \ pA=αa mod p,很难计算aaa;同理通过B=αbmodpB = \alpha^b \ mod \ pB=αb mod p,很难计算bbb。这里利用了Zp∗Z_p^*Zp∗​上的离散对数问题在计算上是困难的。

基于有限循环群(G,∘)(G,\circ)(G,∘) 的DH算法的一般定义

1.初始化:

随机选择一个元素α∈G\alpha \in Gα∈G,α\alphaα为生成元。
发布(G,∘)(G,\circ)(G,∘)、生成元α\alphaα和阶∣G∣|G|∣G∣。

2.密钥交换

Alice:随机选择一个a∈{2,3,⋯,∣G∣}a \in \{2,3,\cdots,|G|\}a∈{2,3,⋯,∣G∣},计算A=αaA = \alpha^aA=αa,将AAA通过公共网路传送给Bob。
Bob:随机选择一个b∈{2,3,⋯,∣G∣}b \in \{2,3,\cdots,|G|\}b∈{2,3,⋯,∣G∣},计算B=αbB = \alpha^bB=αb,将BBB通过公共网路传送给Alice。

3.密钥计算

Alice:Kab=Ba=αabK_{ab}=B^a=\alpha^{ab}Kab​=Ba=αab
Bob:Kab=Ab=αabK_{ab}=A^b=\alpha^{ab}Kab​=Ab=αab

安全性要求:(G,∘)(G,\circ)(G,∘)上的离散对数问题要计算困难。比如Zn={0,1,2,⋯,n−1}Z_n=\{0,1,2,\cdots,n-1\}Zn​={0,1,2,⋯,n−1},∘=+modn\circ=+\ mod \ n∘=+ mod n就不行。

3 素数域ZpZ_pZp​上的椭圆曲线上的离散对数问题

3.1 椭圆曲线的定义

椭圆曲线的定义:椭圆曲线是点的集合,哪些点呢?
1.在素数域ZpZ_pZp​上(p是素数),所有点(x,y)∈Zp(x,y) \in Z_p(x,y)∈Zp​:
满足:
y2≡x3+a⋅x+bmodpy^2 \equiv x^3 + a \cdot x + b \ mod \ py2≡x3+a⋅x+b mod p
其中a,b∈Zpa,b \in Z_pa,b∈Zp​且4⋅a3+27⋅b2≠0modp4 \cdot a^3+27 \cdot b^2 \ne 0 \ mod \ p4⋅a3+27⋅b2​=0 mod p。
2.另外加上一个无穷远点ϑ\varthetaϑ。

Ellipticcurve={(x,y)∣y2≡x3+a⋅x+bmodp}⋃{ϑ}Elliptic \ curve=\{(x,y)|y^2 \equiv x^3 + a \cdot x + b \ mod \ p\} \bigcup \{\vartheta\}Elliptic curve={(x,y)∣y2≡x3+a⋅x+b mod p}⋃{ϑ},其中a,b∈Zpa,b \in Z_pa,b∈Zp​且4⋅a3+27⋅b2≠0modp4 \cdot a^3+27 \cdot b^2 \ne 0 \ mod \ p4⋅a3+27⋅b2​=0 mod p。

注意:素数域Zp={0,1,2,⋯,p−1}Z_p=\{0,1,2,\cdots ,p-1\}Zp​={0,1,2,⋯,p−1}的意思是:在$+ \mod p $下构成单位元为000的群,去除000元素在×modp\times \ mod \ p× mod p下构成单位元为111的群。

3.2 椭圆曲线上的二元运算∘\circ∘的定义

二元运算∘\circ∘的定义

Ellipticcurve={(x,y)∣y2≡x3+a⋅x+bmodp}⋃{ϑ}Elliptic \ curve=\{(x,y)|y^2 \equiv x^3 + a \cdot x + b \ mod \ p\} \bigcup \{\vartheta\}Elliptic curve={(x,y)∣y2≡x3+a⋅x+b mod p}⋃{ϑ},其中a,b∈Zpa,b \in Z_pa,b∈Zp​且4⋅a3+27⋅b2≠0modp4 \cdot a^3+27 \cdot b^2 \ne 0 \ mod \ p4⋅a3+27⋅b2​=0 mod p。

椭圆曲线上的∘\circ∘的定义

对∀P=(x1,y1),Q=(x2,y2)∈Ellipticcurve\forall P=(x_1,y_1),Q=(x_2,y_2)\in Elliptic \ curve∀P=(x1​,y1​),Q=(x2​,y2​)∈Elliptic curve,(x3,y3)=P∘Q(x_3,y_3)=P \circ Q(x3​,y3​)=P∘Q定义如下:
x3=s2−x1−x2modpx_3=s^2 -x_1-x_2 \ mod \ px3​=s2−x1​−x2​ mod p
y3=s⋅(x1−x3)−y1modpy_3=s\cdot (x_1-x_3) -y_1 \mod py3​=s⋅(x1​−x3​)−y1​modp
其中
s=y2−y1x2−x1modp,如果P≠Qs=\frac{y_2- y_1}{x_2 - x_1} \ mod \ p,如果P\ne Qs=x2​−x1​y2​−y1​​ mod p,如果P​=Q
s=3⋅x12+a2⋅y1modp,如果P=Qs=\frac{3\cdot x_1^2 +a}{2\cdot y_1} \ mod \ p,如果P=Qs=2⋅y1​3⋅x12​+a​ mod p,如果P=Q

另外其他一些定义:
1.ϑ\varthetaϑ为单位元,即对∀P∈Ellipticcurve\forall P\in Elliptic \ curve∀P∈Elliptic curve,P∘ϑ=PP\circ \vartheta=PP∘ϑ=P
2.对∀P=(x1,y1)∈Ellipticcurve\forall P=(x_1,y_1) \in Elliptic \ curve∀P=(x1​,y1​)∈Elliptic curve,P−1=(x1,p−y1modp)P^{-1}=(x_1,p-y_1 \ mod \ p)P−1=(x1​,p−y1​ mod p),所以理论上∀P=(x1,y1),Q=(x2,y2)∈Ellipticcurve\forall P=(x_1,y_1),Q=(x_2,y_2)\in Elliptic \ curve∀P=(x1​,y1​),Q=(x2​,y2​)∈Elliptic curve,若x1=x2x_1=x_2x1​=x2​,则P∘Q=ϑP\circ Q=\varthetaP∘Q=ϑ。

结论

Ellipticcurve={(x,y)⋃ϑ∣y2≡x3+a⋅x+bmodp}Elliptic \ curve=\{(x,y) \bigcup \vartheta|y^2 \equiv x^3 + a \cdot x + b \ mod \ p\}Elliptic curve={(x,y)⋃ϑ∣y2≡x3+a⋅x+b mod p},其中a,b∈Zpa,b \in Z_pa,b∈Zp​且4⋅a3+27⋅b2≠0modp4 \cdot a^3+27 \cdot b^2 \ne 0 \ mod \ p4⋅a3+27⋅b2​=0 mod p,以及其上的二元运算∘\circ∘,构成一个有限群。在某种条件下构成有限循环群。

如何证明请参考专业书籍,这里的某种条件,我们通常会选取满足条件的aaa、bbb和ppp,所以我们以下假定椭圆曲线在以上定义的二元运算上是有限循环群。

一些简称

二元运算P∘QP\circ QP∘Q,我们通常称为加法P+QP+QP+Q
二元运算P∘PP\circ PP∘P,我们通常称为倍乘2⋅P2\cdot P2⋅P;则Pd=P∘P∘⋯∘P⏟d=d⋅PP^d=\underbrace{P\circ P \circ \cdots \circ P}_d=d\cdot PPd=dP∘P∘⋯∘P​​=d⋅P

3.3 椭圆曲线上的离散对数问题

给定一条基于素数域ZpZ_pZp​的椭圆曲线EEE,模为ppp,椭圆曲线的系数为aaa,bbb;若G为生成元,ord(G)=#Eord(G)=\#Eord(G)=#E,则离散问题描述为:给定P∈EP \in EP∈E,求ddd使得Gd=PG ^d = PGd=P即d⋅G=Pd\cdot G=Pd⋅G=P,其中1≤d≤#E1 \le d \le \#E1≤d≤#E。这里唯一要说明的是这在计算上是困难的。

注意:#E\#E#E椭圆曲线点的数目。

3.3 椭圆曲线在密码学上的应用

3.3.1 椭圆曲线的密钥生成

1.域参数选择

选择一条基于素数域ZpZ_pZp​椭圆曲线EEE,模为ppp,椭圆曲线的系数为aaa,bbb;
选择椭圆曲线上的一个点GGG,GGG的阶为nnn,阶nnn是素数,G称为基点。
模为ppp,椭圆曲线的系数为aaa,bbb、G=(xG,yG)G=(x_G,y_G)G=(xG​,yG​)和阶nnn称为域参数。域参数是公开的。

2.密钥生成

随机选择一个整数ddd,1≤d<n1\le d < n1≤d<n
计算P=d⋅GP=d\cdot GP=d⋅G

3.公钥Kpub=P=(xP,yP)K_{pub}=P=(x_P,y_P)Kpub​=P=(xP​,yP​)和私钥Kpri=dK_{pri}=dKpri​=d

3.3.2 椭圆曲线的数字签名算法

签名

用私钥ddd对消息xxx进行签名

1.选择1≤KE<n1\le K_E < n1≤KE​<n
2.计算R=KE⋅G=(xR,yR)R=K_E\cdot G=(x_R,y_R)R=KE​⋅G=(xR​,yR​)
3.签名结果为(r,s)(r,s)(r,s),其中r=xRr=x_Rr=xR​。
4.计算s,s≡(h(x)+d⋅r)⋅KE−1modns \equiv (h(x)+d\cdot r)\cdot K_E^{-1} \ mod \ ns≡(h(x)+d⋅r)⋅KE−1​ mod n,其中KE−1⋅KE≡1modnK_E^{-1} \cdot K_E \equiv 1 \ mod \ nKE−1​⋅KE​≡1 mod n,h为hash算法。

验签

用公钥PPP对结果(x,(r,s))(x,(r,s))(x,(r,s))进行验签

1.计算ω=s−1modn\omega=s^{-1} \ mod \ nω=s−1 mod n。
2.计算μ1=ω⋅h(x)modn\mu_1=\omega \cdot h(x) \ mod \ nμ1​=ω⋅h(x) mod n。
3.计算μ2=ω⋅rmodn\mu_2=\omega \cdot r \ mod \ nμ2​=ω⋅r mod n。
4.计算Q=μ1⋅G+μ2⋅PQ=\mu_1\cdot G+\mu_2\cdot PQ=μ1​⋅G+μ2​⋅P。若xQ≡rmodnx_Q \equiv r \ mod \ nxQ​≡r mod n,则签名正确。

证明:

因为GGG是基点,所以n⋅G=ϑn\cdot G=\varthetan⋅G=ϑ
又因为P=d⋅GP=d\cdot GP=d⋅G
由μ1=ω⋅h(x)modn\mu_1=\omega \cdot h(x) \ mod \ nμ1​=ω⋅h(x) mod n,知存在c1c_1c1​使得μ1=ω⋅h(x)+c1⋅n\mu_1=\omega \cdot h(x) + c_1 \cdot nμ1​=ω⋅h(x)+c1​⋅n。
由μ2=ω⋅rmodn\mu_2=\omega \cdot r \ mod \ nμ2​=ω⋅r mod n,知存在c2c_2c2​使得μ2=ω⋅r+c2⋅n\mu_2=\omega \cdot r + c_2\cdot nμ2​=ω⋅r+c2​⋅n。
所以Q=μ1⋅G+μ2⋅P=(ω⋅h(x)+c1⋅n)⋅G+(ω⋅r+c2⋅n)⋅d⋅GQ=\mu_1\cdot G+\mu_2\cdot P=(\omega \cdot h(x) + c_1 \cdot n)\cdot G+(\omega \cdot r + c_2\cdot n)\cdot d \cdot GQ=μ1​⋅G+μ2​⋅P=(ω⋅h(x)+c1​⋅n)⋅G+(ω⋅r+c2​⋅n)⋅d⋅G。
所以Q=(ω⋅h(x))⋅G+(ω⋅r⋅d)⋅G=(ω⋅h(x)+ω⋅r⋅d)⋅GQ=(\omega \cdot h(x))\cdot G + (\omega \cdot r \cdot d)\cdot G=(\omega \cdot h(x) + \omega \cdot r \cdot d)\cdot GQ=(ω⋅h(x))⋅G+(ω⋅r⋅d)⋅G=(ω⋅h(x)+ω⋅r⋅d)⋅G。
由ω=s−1modn\omega=s^{-1} \ mod \ nω=s−1 mod n,知存在c3c_3c3​使得ω=s−1+c3⋅n\omega=s^{-1} + c_3\cdot nω=s−1+c3​⋅n。
所以Q=(s−1⋅h(x)+s−1⋅r⋅d)⋅GQ=(s^{-1} \cdot h(x) + s^{-1} \cdot r \cdot d)\cdot GQ=(s−1⋅h(x)+s−1⋅r⋅d)⋅G。
又s≡(h(x)+d⋅r)⋅KE−1modns \equiv (h(x)+d\cdot r)\cdot K_E^{-1} \ mod \ ns≡(h(x)+d⋅r)⋅KE−1​ mod n,则KE=s−1⋅h(x)+s−1⋅r⋅dmodnK_E=s^{-1} \cdot h(x) + s^{-1} \cdot r \cdot d \ mod \ nKE​=s−1⋅h(x)+s−1⋅r⋅d mod n。又R=KE⋅G=(xR,yR)R=K_E\cdot G=(x_R,y_R)R=KE​⋅G=(xR​,yR​)。证毕。

3.3.3 椭圆曲线的DH算法

参考前面

3.3.5 Python测试代码

import hashlib
import math#求逆 mod p
def inverseP(p,r1): #p为正整数,r0为整数
#修正r0为0=<r0<pif r1<0 or r1>p:r1=r1-math.floor(r1/p)*pr0=pr1=r1#满足r0=s0*r0+t0*r1s0=1t0=0 #满足r1=s1*r0+t1*r1s1=0t1=1 while r1 !=0:r2= r0 % r1q= r0//r1 r0=r1r1=r2s0_temp=s0t0_temp=t0#r0=r1=s1*r0+t1*r1 所以s0=s1 t0=t1s0=s1t0=t1  #r1=r2=r0-q*r1=(s0*r0+t0*r1)-q*(s1*r0+t1*r1)=(s0-q*s1)*r0+(t0-q*t1)*r1s1=s0_temp-q*s1t1=t0_temp-q*t1if r0!=1:print("No inverseP")return 0else:if t0<0 or t0>p:t0=t0-math.floor(t0/p)*p #修正到0和p-1之间return t0#自定义椭圆曲线
class EcSelfDefine():def __init__(self,a,b,p,xG,yG,order,d,xPub,yPub):self.a=aself.b=bself.p=pself.xG=xGself.yG=yGself.order=orderself.d=dself.xPub=xPubself.yPub=yPubdef _point_addition(self,xP,yP,xQ,yQ):if xP == None:return xQ,yQelif xQ == None:return xP,yPelif yP == -1*yQ:return None,Noneelif xP==xQ and yP==yQ:s=((3 * xP**2 + self.a ) * inverseP(self.p,(2 * yP)))%self.pnewx = -2 * xP  + s*snewy = -yP + s*(xP-newx)return newx % self.p , newy % self.pelse:s=((yQ-yP)*inverseP(self.p,(xQ-xP)))%self.pnewx = - xP-xQ  + s*snewy = -yP + s*(xP-newx)return newx % self.p , newy % self.pdef _mul(self,scalar,xP,yP):xResult = NoneyResult = NonexN=xPyN=yPif scalar > 0:for bit in range(scalar.bit_length()):if (scalar & (1 << bit)):(xResult,yResult)=self._point_addition(xResult,yResult,xN,yN)(xN,yN)=self._point_addition(xN,yN,xN,yN)return xResult,yResultdef verifySign(self,data,r,s,hash):mHash=hashlib.sha256(data)ismp=inverseP(self.order,s)u1=ismp*int(mHash.hexdigest(),16) % self.orderu2=ismp*r % self.orderxP1,yP1=self._mul(u1,self.xG,self.yG)xP2,yP2=self._mul(u2,self.xPub,self.yPub)x,y=self._point_addition(xP1,yP1,xP2,yP2)if r % self.order == x % self.order:print("verify suc")else:print("verify fail")#椭圆曲线SECP256K1()的域参数
p=115792089237316195423570985008687907853269984665640564039457584007908834671663
a=0#椭圆曲线系数 a
b=7#椭圆曲线系数 b
xG=55066263022277343669578718895168534326250603453777594175500187360389116729240#基点G
yG=32670510020758816978083085130507043184471273380659243275938904335757337482424
order=115792089237316195423570985008687907852837564279074904382605163141518161494337#基点G的阶#私钥
d="77090417795357418597142879162416172615250850989980925874163023305273313532855"
d=int(d,16) #公钥Pub=(xPub,yPub)
xPub=int("d00d4ae6f998fa1d1c2f7b9f45dfba6021cd678b80cce46c39a268b1dbac1274",16)
yPub=int("3e409cf6d4894b21e21b0ef30b1b108b15ceaa24677c5c4418cec371c97fd96f",16) #数据
data = b"this is some data I'd like to sign"EcCure=EcSelfDefine(a,b,p,xG,yG,order,d,xPub,yPub)#签名结果(r,s)
r="1b68fe1f67f371e23be270bb6a1cefba406da2fab0e227c4e9f83ac8b067e7da"
s="71b079be6001e53b421f736024791f8fd28d55db50fef16f86a06115c7043b45"
r=int(r,16)
s=int(s,16)#验签
EcCure.verifySign(data,r,s,0)

4. 基于素数域ZpZ_pZp​的SM2国密算法

4.1 SM2椭圆曲线的定义

SM2的椭圆曲线的域参数如下

a=int('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC',16)
b=int('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93',16)
p=int('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)
xG=int('32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7',16)
yG=int('bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0',16)
order=int('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123',16)

密钥生成

密钥生成

随机选择一个整数ddd,1≤d<n1\le d < n1≤d<n,nnn为阶orderorderorder。
计算P=d⋅GP=d\cdot GP=d⋅G

公钥Kpub=P=(xP,yP)K_{pub}=P=(x_P,y_P)Kpub​=P=(xP​,yP​)和私钥Kpri=dK_{pri}=dKpri​=d

4.2 SM2椭圆曲线在密码学上的应用

4.2.1 SM2的数字签名算法

类似于ECDSA。

签名

用私钥ddd对消息MMM进行签名

1.计算用户A的可辨别标识ZA=SM3(ENTLA)∣∣IDA∣∣a∣∣b∣∣xG∣∣yG∣∣xP∣∣yP)Z_A=SM_3(ENTL_A)||ID_A||a||b||x_G||y_G||x_P||y_P)ZA​=SM3​(ENTLA​)∣∣IDA​∣∣a∣∣b∣∣xG​∣∣yG​∣∣xP​∣∣yP​),其中用户AAA具有长度为entlenAentlen_AentlenA​比特的可辨别标识IDAID_AIDA​,ENTLAENTL_AENTLA​是由整数entlenAentlen_AentlenA​转换而成的两个字节。
2.计算Mˉ=ZA∣∣M\bar{M}=Z_A||MMˉ=ZA​∣∣M。
3.计算e=SM3(Mˉ)e=SM_3(\bar{M})e=SM3​(Mˉ)。
4.选择1≤KE<n1\le K_E < n1≤KE​<n。
5.计算(x1,y1)=KE⋅G(x_1,y_1)=K_E \cdot G(x1​,y1​)=KE​⋅G
6.计算rrr,r=(e+x1)modnr=(e+x_1) \ mod \ nr=(e+x1​) mod n。
4.计算sss,s=((1+d)−1)⋅(KE−r⋅d)modns=((1+d)^{-1})\cdot (K_E-r\cdot d) \mod \ ns=((1+d)−1)⋅(KE​−r⋅d)mod n。ddd为私钥。

验签

用公钥PPP对结果(M,(r,s))(M,(r,s))(M,(r,s))进行验签

1.计算e,类似于签名步骤1,2,3
2.计算t=(r+s)modnt=(r+s) \ mod \ nt=(r+s) mod n。
3.计算计算(x1,y1)=s⋅G+t⋅P(x_1,y_1)=s\cdot G+ t \cdot P(x1​,y1​)=s⋅G+t⋅P。
4.计算R=(e+x1)modnR=(e+x_1) \ mod \ nR=(e+x1​) mod n。若R≡rmodnR \equiv r \ mod \ nR≡r mod n,则签名正确。

证明:

因为GGG是基点,所以n⋅G=ϑn\cdot G=\varthetan⋅G=ϑ
又因为P=d⋅GP=d\cdot GP=d⋅G
由t=(r+s)modnt=(r+s) \ mod \ nt=(r+s) mod n,知存在c1c_1c1​使得t=(r+s)+c1⋅nt=(r+s) + c_1 \cdot nt=(r+s)+c1​⋅n。
所以(x1,y1)=s⋅G+t⋅P=s⋅G+(r+s)⋅d⋅G+c1⋅n⋅d⋅G=((1+d)⋅s+r⋅d)⋅G(x_1,y_1)=s\cdot G + t \cdot P=s\cdot G + (r+s)\cdot d \cdot G +c_1\cdot n \cdot d \cdot G=((1+d)\cdot s + r\cdot d )\cdot G(x1​,y1​)=s⋅G+t⋅P=s⋅G+(r+s)⋅d⋅G+c1​⋅n⋅d⋅G=((1+d)⋅s+r⋅d)⋅G。
又由s=((1+d)−1)⋅(KE−r⋅d)modns=((1+d)^{-1})\cdot (K_E-r\cdot d) \mod \ ns=((1+d)−1)⋅(KE​−r⋅d)mod n知c2c_2c2​使得(1+d)⋅s+r⋅d=KE+c2⋅n(1+d)\cdot s +r\cdot d=K_E+c_2\cdot n(1+d)⋅s+r⋅d=KE​+c2​⋅n,所以(x1,y1)=(KE+c2⋅n)⋅G=KE⋅G(x_1,y_1)=(K_E+c_2\cdot n)\cdot G=K_E \cdot G(x1​,y1​)=(KE​+c2​⋅n)⋅G=KE​⋅G,证毕。

SM2的DH算法

待写

4.2.2 SM2的公钥加密算法

加密

用公钥P对M进行加密,klen为M的比特长度

1.随机生成1≤k<n1\le k < n1≤k<n。
2.计算C1=k⋅G=(x1,y1)C_1=k\cdot G=(x_1,y_1)C1​=k⋅G=(x1​,y1​)。
3.计算(x2,y2)=k⋅P(x_2,y_2)=k\cdot P(x2​,y2​)=k⋅P。
4.计算t=KDF(x2∣∣y2,klen)t=KDF(x_2||y_2,klen)t=KDF(x2​∣∣y2​,klen)
5.计算C2=M⊕tC_2=M \oplus tC2​=M⊕t。
6.计算C3=SM3(x2∣∣M∣y2)C_3=SM_3(x_2||M|y_2)C3​=SM3​(x2​∣∣M∣y2​)。
7.输出密文C=C1∣∣C2∣∣C3C=C_1||C_2||C_3C=C1​∣∣C2​∣∣C3​,其中C2C_2C2​为与明文长度相等的密文。

KDF

参考 [4] SM2 椭圆曲线公钥密码算法第2 部分:公钥加密算,国家密码管理
局,2010 年12 月

 def kdf(self,Z,klen,v=256): #SM3:256bit,32 bytes。  #klen是8的倍数。  #Z:bytesif klen>(2**32-1)*256:print("error")return Nonecount=0x01k=math.ceil(klen/v)Z=Z.hex()H=""for i in range(k):H=H+SM3.Hash_sm3(Z+"%08x" % count,1)count=count+1return bytes.fromhex(H[:klen//4])

解密

利用私钥d对(C=C=C_1||C_2||C_3)进行解密

利用C_1=C1=k⋅G=(x1,y1)C_1=k\cdot G=(x_1,y_1)C1​=k⋅G=(x1​,y1​)。从而d⋅C1=k⋅d⋅G=k⋅P=(x2,y2)d\cdot C_1=k\cdot d\cdot G=k\cdot P=(x_2,y_2)d⋅C1​=k⋅d⋅G=k⋅P=(x2​,y2​)。利用t=KDF(x2∣∣y2,klen)t=KDF(x_2||y_2,klen)t=KDF(x2​∣∣y2​,klen),从而解密M=C2⊕tM=C_2 \oplus tM=C2​⊕t。

Python测试代码

SM3.py

from  math import ceilIV="7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e"
IV = int(IV.replace(" ", ""), 16)
a = []
for i in range(0, 8):a.append(0)a[i] = (IV >> ((7 - i) * 32)) & 0xFFFFFFFF
IV = adef out_hex(list1):for i in list1:print("%08x" % i)print("\n")def rotate_left(a, k):k = k % 32return ((a << k) & 0xFFFFFFFF) | ((a & 0xFFFFFFFF) >> (32 - k))T_j = []
for i in range(0, 16):T_j.append(0)T_j[i] = 0x79cc4519
for i in range(16, 64):T_j.append(0)T_j[i] = 0x7a879d8adef FF_j(X, Y, Z, j):if 0 <= j and j < 16:ret = X ^ Y ^ Zelif 16 <= j and j < 64:ret = (X & Y) | (X & Z) | (Y & Z)return retdef GG_j(X, Y, Z, j):if 0 <= j and j < 16:ret = X ^ Y ^ Zelif 16 <= j and j < 64:#ret = (X | Y) & ((2 ** 32 - 1 - X) | Z)ret = (X & Y) | ((~ X) & Z)return retdef P_0(X):return X ^ (rotate_left(X, 9)) ^ (rotate_left(X, 17))def P_1(X):return X ^ (rotate_left(X, 15)) ^ (rotate_left(X, 23))def CF(V_i, B_i):W = []for i in range(16):weight = 0x1000000data = 0for k in range(i*4,(i+1)*4):data = data + B_i[k]*weightweight = int(weight/0x100)W.append(data)for j in range(16, 68):W.append(0)W[j] = P_1(W[j-16] ^ W[j-9] ^ (rotate_left(W[j-3], 15))) ^ (rotate_left(W[j-13], 7)) ^ W[j-6]str1 = "%08x" % W[j]W_1 = []for j in range(0, 64):W_1.append(0)W_1[j] = W[j] ^ W[j+4]str1 = "%08x" % W_1[j]A, B, C, D, E, F, G, H = V_i"""print "00",out_hex([A, B, C, D, E, F, G, H])"""for j in range(0, 64):SS1 = rotate_left(((rotate_left(A, 12)) + E + (rotate_left(T_j[j], j))) & 0xFFFFFFFF, 7)SS2 = SS1 ^ (rotate_left(A, 12))TT1 = (FF_j(A, B, C, j) + D + SS2 + W_1[j]) & 0xFFFFFFFFTT2 = (GG_j(E, F, G, j) + H + SS1 + W[j]) & 0xFFFFFFFFD = CC = rotate_left(B, 9)B = AA = TT1H = GG = rotate_left(F, 19)F = EE = P_0(TT2)A = A & 0xFFFFFFFFB = B & 0xFFFFFFFFC = C & 0xFFFFFFFFD = D & 0xFFFFFFFFE = E & 0xFFFFFFFFF = F & 0xFFFFFFFFG = G & 0xFFFFFFFFH = H & 0xFFFFFFFF"""str1 = "%02d" % jif str1[0] == "0":str1 = ' ' + str1[1:]print str1,out_hex([A, B, C, D, E, F, G, H])"""V_i_1 = []V_i_1.append(A ^ V_i[0])V_i_1.append(B ^ V_i[1])V_i_1.append(C ^ V_i[2])V_i_1.append(D ^ V_i[3])V_i_1.append(E ^ V_i[4])V_i_1.append(F ^ V_i[5])V_i_1.append(G ^ V_i[6])V_i_1.append(H ^ V_i[7])return V_i_1def hash_msg(msg):# print(msg)len1 = len(msg)reserve1 = len1 % 64msg.append(0x80)reserve1 = reserve1 + 1# 56-64, add 64 byterange_end = 56if reserve1 > range_end:range_end = range_end + 64for i in range(reserve1, range_end):msg.append(0x00)bit_length = (len1) * 8bit_length_str = [bit_length % 0x100]for i in range(7):bit_length = int(bit_length / 0x100)bit_length_str.append(bit_length % 0x100)for i in range(8):msg.append(bit_length_str[7-i])# print(msg)group_count = round(len(msg) / 64)B = []for i in range(0, group_count):B.append(msg[i*64:(i+1)*64])V = []V.append(IV)for i in range(0, group_count):V.append(CF(V[i], B[i]))y = V[i+1]result = ""for i in y:result = '%s%08x' % (result, i)return resultdef str2byte(msg): # 字符串转换成byte数组ml = len(msg)msg_byte = []msg_bytearray = msg.encode('utf-8')for i in range(ml):msg_byte.append(msg_bytearray[i])return msg_bytedef byte2str(msg): # byte数组转字符串ml = len(msg)str1 = b""for i in range(ml):str1 += b'%c' % msg[i]return str1.decode('utf-8')def hex2byte(msg): # 16进制字符串转换成byte数组ml = len(msg)if ml % 2 != 0:msg = '0'+ msgml = int(len(msg)/2)msg_byte = []for i in range(ml):msg_byte.append(int(msg[i*2:i*2+2],16))return msg_bytedef byte2hex(msg): # byte数组转换成16进制字符串ml = len(msg)hexstr = ""for i in range(ml):hexstr = hexstr + ('%02x'% msg[i])return hexstrdef Hash_sm3(msg,Hexstr = 0):if(Hexstr):msg_byte = hex2byte(msg)else:msg_byte = str2byte(msg)return hash_msg(msg_byte)def KDF(Z,klen): # Z为16进制表示的比特串(str),klen为密钥长度(单位byte)klen = int(klen)ct = 0x00000001rcnt = ceil(klen/32)Zin = hex2byte(Z)Ha = ""for i in range(rcnt):msg = Zin  + hex2byte('%08x'% ct)# print(msg)Ha = Ha + hash_msg(msg)# print(Ha)ct += 1return Ha[0: klen * 2]if __name__ == '__main__':y = Hash_sm3("abc")print(y)# klen = 19# print(KDF("57E7B63623FAE5F08CDA468E872A20AFA03DED41BF1403770E040

SM2验签和加密

import SM3
import math
import os#求逆 mod p
def inverseP(p,r1): #p为正整数,r0为整数
#修正r0为0=<r0<pif r1<0 or r1>p:r1=r1-math.floor(r1/p)*pr0=pr1=r1#满足r0=s0*r0+t0*r1s0=1t0=0 #满足r1=s1*r0+t1*r1s1=0t1=1 while r1 !=0:r2= r0 % r1q= r0//r1 r0=r1r1=r2s0_temp=s0t0_temp=t0#r0=r1=s1*r0+t1*r1 所以s0=s1 t0=t1s0=s1t0=t1  #r1=r2=r0-q*r1=(s0*r0+t0*r1)-q*(s1*r0+t1*r1)=(s0-q*s1)*r0+(t0-q*t1)*r1s1=s0_temp-q*s1t1=t0_temp-q*t1if r0!=1:print("No inverseP")return 0else:if t0<0 or t0>p:t0=t0-math.floor(t0/p)*p #修正到0和p-1之间return t0
class SM2():def __init__(self,d,xPub,yPub,a=int('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC',16),b=int('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93',16),p=int('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16),xG=int('32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7',16),yG=int('bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0',16),order=int('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123',16),key_size=32):self.a=aself.b=bself.p=pself.xG=xGself.yG=yGself.order=orderself.d=dself.xPub=xPubself.yPub=yPubself.key_size=key_sizedef _point_addition(self,xP,yP,xQ,yQ):if xP == None:return xQ,yQelif xQ == None:return xP,yPelif yP == -1*yQ:return None,Noneelif xP==xQ and yP==yQ:s=((3 * xP**2 + self.a ) * inverseP(self.p,(2 * yP)))%self.pnewx = -2 * xP  + s*snewy = -yP + s*(xP-newx)return newx % self.p , newy % self.pelse:s=((yQ-yP)*inverseP(self.p,(xQ-xP)))%self.pnewx = - xP-xQ  + s*snewy = -yP + s*(xP-newx)return newx % self.p , newy % self.pdef _mul(self,scalar,xP,yP):xResult = NoneyResult = NonexN=xPyN=yPif scalar > 0:for bit in range(scalar.bit_length()):if (scalar & (1 << bit)):(xResult,yResult)=self._point_addition(xResult,yResult,xN,yN)(xN,yN)=self._point_addition(xN,yN,xN,yN)return xResult,yResultdef verifySign(self,data,IDA,r,s,hash):#IDA hexstr r int s int hash 0   #02杂凑值ZA=H256(ENTLA ∥ IDA ∥ a ∥ b ∥ xG ∥ yG ∥ xA ∥ yA)#IDA="11248139509653376079" #hexstr#1.计算eENTLA="".join(["%02x" % x for x in [(len(IDA)*4)//256,(len(IDA)*4)%256]])a='FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC'b='28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93'xG='32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7'yG='bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0'#xG="5fcf1e2d45db51f4e0145b0a86f9d6b8eaadde214041cd7ae3c77fcdfb4cba2c"xPub="0"*(self.key_size-len("%x" % self.xG))+"%x" % self.xPubyPub="0"*(self.key_size-len("%x" % self.xG))+"%x" % self.yPubZA=ENTLA+IDA+a+b+xG+yG+xPub+yPubZA=SM3.Hash_sm3(ZA,1)e=ZA+data.hex()e=SM3.Hash_sm3(e,1)#2.计算t=r+st=(r+s) % self.order#3.计算(x1,y1)xP1,yP1=self._mul(s,self.xG,self.yG)xP2,yP2=self._mul(t,self.xPub,self.yPub)x_1,y_1=self._point_addition(xP1,yP1,xP2,yP2)#4.计算RR=int(e,16)+x_1if r % self.order == R % self.order:print("verify suc")else:print("verify fail")def sign():passdef kdf(self,Z,klen,v=256): #SM3:256bit,32 bytes。  #klen是8的倍数。  #Z:bytesif klen>(2**32-1)*256:print("error")return Nonecount=0x01k=math.ceil(klen/v)Z=Z.hex()H=""for i in range(k):H=H+SM3.Hash_sm3(Z+"%08x" % count,1)count=count+1return bytes.fromhex(H[:klen//4])def encrypt(self,message):#返回bytes#1.随机选择kkey=os.urandom(32)key=key.hex()#2.计算C_1=(x_1,y_1)C1_x,C1_y=self._mul(int(key,16),self.xG,self.yG)#3.计算(x_2,y_2)x_2,y_2=self._mul(int(key,16),self.xPub,self.yPub)#4.计算tt=self.kdf(bytes.fromhex("%064x" % x_2 + "%064x" % y_2),len(message)*8)#5.计算C_2C2="".join([ "%02x" % (message[i]^t[i]) for i in range(len(message))])#6.计算C_3C3=SM3.Hash_sm3("%064x" % x_2 + message.hex()+"%064x" % y_2,1)C1="04"+"%064x" % C1_x + "%064x" % C1_y #"04"代表C_1是未压缩模式C=C1+C2+C3return bytes.fromhex(C)def dencrypt(self,e_message):#返回bytesif e_message[0] != 0x04:print(error)return#1.提取C_1C1_x=e_message[1:1+32]C1_y=e_message[1+32:1+32+32]#2.提取C_2C2=e_message[1+32+32:-32]#3.提取C_3C3=e_message[-32:]#4.计算(x_2,y_2)x_2,y_2=self._mul(self.d,int(C1_x.hex(),16),int(C1_y.hex(),16))#5.计算tt=self.kdf(bytes.fromhex("%064x" % x_2 + "%064x" % y_2),len(C2)*8)#6.计算明文MM="".join([ "%02x" % (C2[i]^t[i]) for i in range(len(C2))])C3_=SM3.Hash_sm3("%064x" % x_2 + M+"%064x" % y_2,1)if C3.hex()==C3_:return bytes.fromhex(M)else:print("fail")return b"fail"if __name__=="__main__":#私钥d=int("552E8CA9F023F8AFAAFA6FF35B8B936E3940EFA94BEB6FD2D066C5BA99D8B7B9",16)#公钥xPub=int("5fcf1e2d45db51f4e0145b0a86f9d6b8eaadde214041cd7ae3c77fcdfb4cba2c",16)yPub=int("ec3ae9e628850d73b43f1012e96c6193184dca08c607e3ff27772746e3029890",16)#用户IDIDA="3131323438313339353039363533333736303739"#1.验签#数据Mdata=bytes.fromhex("6D65737361676520646967657374")#签名结构(r,s)r="FBF686FD1DAA6B635E1377112CF7B0BC1FD170A90D3120F9722D5C36DE8CD566"s="4DFAB9FA7F92759829EF170F48D7E9BF0A8723B13861A7F4FE7111AAE15B7AC2"sm=SM2(d,xPub,yPub)sm.verifySign(data,IDA,int(r,16),int(s,16),0)#2.加密yResult=sm.encrypt(b'I love you')print(yResult.hex())#3.解密yResult_plain=sm.dencrypt(yResult)print(yResult_plain)

参考

[1] Understanding Cryptography: A Textbook for Students and Practitioners,
Paar, Christof, Pelzl, Jan
[2] SM2 椭圆曲线公钥密码算法第1 部分:总则,国家密码管理局,2010 年
12 月
[3] SM2 椭圆曲线公钥密码算法第2 部分:数字签名算法,国家密码管理
局,2010 年12 月
[4] SM2 椭圆曲线公钥密码算法第2 部分:公钥加密算,国家密码管理
局,2010 年12 月

结束

椭圆曲线算法和国密SM2算法介绍相关推荐

  1. 国密SM2算法的只求理解不求甚解 (4/5)SM2算法加解密协议

    国密SM2算法的只求理解不求甚解 (1/5)前置数学知识:模运算 国密SM2算法的只求理解不求甚解 (2/5)前置数学知识:平面几何 国密SM2算法的只求理解不求甚解 (3/5)SM2算法数学模型 国 ...

  2. 一文告诉你,国密SM2算法有多优秀

    可能很多人都想不到,密码技术是与核技术.航天技术并列的国家三大安全核心技术之一,在保障信息安全,建设行业网络安全环境,增强我国行业信息系统的"安全可控"能力等方面发挥着至为关键的作 ...

  3. 国密SM2算法与RSA算法对比分析

    SM2算法和RSA算法都是公钥密码算法,SM2算法是一种更先进安全的算法,在安全性能.速度性能等方面都优于RSA算法,在我国商用密码体系中被用来替换RSA算法.国家密码管理局于2010年12月17日发 ...

  4. 国密SM2算法密钥派生函数KDF的实现

    前段时间需要实现国密算法SM2的签名.验签.加密.解密等功能,加解密过程使用到的密钥派生函数(KDF),从网上搜到的代码不符合<GMT 0003.4-2012 SM2椭圆曲线公钥密码算法 > ...

  5. 国密SM2算法(JS加密,C#、Java解密)

    常见的渗透测试会将网站登录时密码使用明文传输视为风险.推荐使用国密算法或者RSA算法对密码进行加密传输. RSA加密(JS加密,C#.Java解密)请参考<RSA对称加密(JS加密,C#.Jav ...

  6. 谈谈PBOC3.0中使用的国密SM2算法

    转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/39780825 作者:小马 一 知识准备 SM2是国密局推出的一种他们自己说具有自主 ...

  7. PBOC3.0中使用的国密SM2算法

    一.知识准备 PBOC3.0规范就是<中国金融集成电路(IC)卡规范>3.0版本. SM2是国密局推出的一种他们自己说具有自主知识产权的非对称商用密码算法.本身是基于ECC椭圆曲线算法的, ...

  8. 国密SM2算法的java和nodejs实现

    转至 http://mp.weixin.qq.com/s/nboZAvg1qYiJIEun6yF2aQ 国密即国家密码局认定的国产密码算法,即商用密码.包括对称加密(SM1) ,非对称加密(SM2) ...

  9. mysql国密算法_【国密SM2算法】通过公钥证书获取JAVA对象

    网上关于国密算法的资料较单一,大部分代码都是写的怎么通过java代码生成公私钥串. 实际项目中对方已经给了他们的公钥证书,这里记录如何通过代码解析获得Ecpoint对象并输出 关键代码 String ...

  10. 国密SM2算法加解密文件

    对文档进行加密操作,只有经过系统解密后才能进行查看文档内容 这里使用hutool工具类提供的SM2方法,首先引入pom.xml依赖 hutool文档地址 <!--工具类--> <de ...

最新文章

  1. Why close date in S2 view is not displayed correctly after clicking it
  2. 一个关于微服务架构和monolithic架构的讨论
  3. 罗永浩开了一家直播界的新东方
  4. 自媒体各大平台收益对比_各大自媒体平台的收益情况汇总
  5. [SQL入门级] 上篇被移出园子首页,那这篇咱就'薄利多销'
  6. 对application/x-www-form-urlencoded、multipart/form-data和text/plain的认识
  7. 算法突击训练营:开学第1课 听课总结
  8. 【HDU-5963】朋友【树上博弈】
  9. 热带鱼屏保(Marine Aquarium 3),如何才能绕过它的Key Code?
  10. 水晶报表繁体转简体心得:之一 RPT文件篇
  11. 阿里云服务器安装宝塔流程
  12. Ecshop主要文件功能介绍,Ecshop文件详细说明
  13. 求图像边界点坐标c语言,三、Windows图像处理—画点和线(边框函数)
  14. 微信小程序自适应图片的时候底部总有一条白色的空白区像一条线该怎么办呢?
  15. 关于IntelliJ IDEA
  16. 微信小程序获取公众号code以及openId
  17. 干货丨开源软件的商业路径
  18. 仓库管理系统————QT+SQLite实现
  19. adb对夜神模拟器查看游戏的log
  20. 启航!2023 Amazon DeepRacer 自动驾驶赛车中国联赛战燃擎开启!

热门文章

  1. 去除firefox火狐更新提示
  2. AI研习丨专题:面向共享出行的群体智能技术与应用
  3. Sqlmap免Python版启动器的小修改(根据学习进度逐步更新)
  4. 【易语言】微信跳一跳教程详细版,分分钟让新手学会的教程(附源码)
  5. 立陶宛央行抢跑数字货币背后:前瞻的区块链战略 中国已有企业布局
  6. 最新微信公众号采集方案详细介绍
  7. CTGU实验5_2-创建还书罚款触发器
  8. CTGU实验6_1-创建能否借书存储过程
  9. 爬取''百思不得姐''网站的全部视频
  10. 使用NuSMV解决过河问题