符号
A,B:使用公钥密码系统的两个用户。
\(cf\):椭圆曲线阶相对于\(N\)的余因子。
\(cid\):用一个字节表示的曲线的标识符,其中\(\mbox{0x10}\)表示\(F_p\)(素数\(P>2^{191}\))上常曲线(即非超奇异曲线),\(\mbox{0x11}\)表示\(F_p\)表示超奇异曲线,\(\mbox{0x12}\)表示\(F_p\)上常曲线及其扭曲线。
\(Dec()\):分组解密算法。
\(de_B\):用户B的加密私钥。
\(Enc()\):分组加密算法。
\(e\):从\(G_1×G_2\)到\(G_T\)的双线性对。
\(eid\):用一个字节表示的双线性对\(e\)的标识符,其中\(\mbox{0x01}\)表示Tate对,\(\mbox{0x02}\)表示Weil对,\(\mbox{0x03}\)表示Ate对,\(\mbox{0x04}\)表示R-ate对。
\(G_T\):阶为素数\(N\)的乘法循环群。
\(G_1\):阶为素数\(N\)的加法循环群。
\(G_2\):阶为素数\(N\)的加法循环群。
\(g^u\):乘法群\(G_T\)中元素\(g\)的\(u\)次幂,\(g^{u} = \underset{u\text{个}}{\underbrace{g \cdot g \cdot \ldots \cdot g}}\),\(u\)是正整数。
\(H_v ()\),\(Hash()\):密码杂凑函数。
\(H_1 ()\):由密码杂凑函数派生的密码函数。
\(hid\):本部分中,用一个字节表示的加密私钥生成函数识别符,由KGC选择并公开。
\(ID_B\):用户B的表示,可以唯一确定用户B的公钥。
\(KDF()\):密钥派生函数。
\(M\):待加密的消息。
\(M'\):解密得到的消息。
\(MAC()\):消息认证码函数。
\(N\):循环群\(G_1\)、\(G_2\)和\(G_T\)的阶,为大于\(2^{191}\)的素数。
\(P_{pub-e}\):加密主公钥。
\(P_1\):群\(G_1\)的生成元。
\(P_2\):群\(G_2\)的生成元。
\(ke\):加密主私钥。
\(〈P〉\):由元素\(P\)生成的循环群。
\([u]P\):加法群\(G_1\)、\(G_2\)中元素\(P\)的\(u\)倍。
\(⌈x⌉\):顶函数,大于或等于\(x\)的最小整数。例如,\(⌈7⌉=7\),\(⌈8.3⌉=9\)。
\(⌊x⌋\):底函数,小于或等于\(y\)的最大整数。例如,\(⌊7⌋=7\),\(⌊8.3⌋=8\)。
\(x‖y\):\(x\)与\(y\)的拼接,其中\(x\)和\(y\)是比特串或字节串。
\([x,y]\):大于或等于\(x\)且小于或等于\(y\)的整数的集合。
\(⊕\):长度相等的两个比特串按比特的模\(2\)加运算。
\(β\):扭曲线参数。
系统加密主密钥和用户加密密钥的产生
KGC产生随机数\(ke∈[1,N-1]\)作为加密主私钥,计算\(G_1\)中的元素\(P_{pub-e}=[ke] P_1\)作为加密主公钥,则加密主密钥对为\((ke,P_{pub-e} )\)。KGC秘密保存\(ke\),公开\(P_{pub-e}\)。
KGC选择并公开用一个字节表示的加密私钥生成函数识别符\(hid\)。
用户B的标识为\(ID_B\),为产生用户B的加密私钥\(de_B\),KGC首先在有限域\(F_N\)上计算\(t_1=H_1(ID_B ‖hid,N)+ke\),若\(t_1=0\)则需重新产生加密主私钥,计算和公开加密主公钥,并更新已有用户的加密私钥;否则计算\(t_2=ke⋅t_3^{-1}\),然后计算\(de_B=[t_2 ] P_2\)。
密码杂凑函数\(H_v ()\)
密码杂凑函数\(H_v ()\)的输出是长度恰为\(v\)比特的杂凑值。本部分规定使用国家密码管理主管部门批准的密码杂凑函数,如SM3密码杂凑算法。
密码函数\(H_1 ()\)
密码函数\(H_1(Z,n)\)的输入为比特串\(Z\)和整数\(n\),输出为一个整数\(h_1∈[1,n-1]\)。\(H_1(Z,n)\)需要调用密码杂凑函数\(H_v ()\)。
密码函数\(H_1(Z,n)\):
输入:比特串\(Z\),整数\(n\)。
输出:整数\(h_1∈[1,n-1]\)。
- 初始化一个32比特构成的计数器\(ct=\mbox{0x00000001}\);
- 计算\(hlen=8×⌈(5×(\log{2}{n}))⁄32⌉\);
- 对\(i\)从\(1\)到\(⌈hlen⁄v⌉\)执行:
3.1. 计算\(Ha_i=H_v(\mbox{0x01}‖Z‖ct)\);
3.2. \(ct++\); - 若\(hlen⁄v\)是整数,令\(Ha!_{⌈hlen⁄v⌉} =Ha_{⌈hlen⁄v⌉}\) ,否则令\(Ha!_{⌈hlen⁄v⌉}\) 为\(Ha_{⌈hlen⁄v⌉}\) 最左边的\((hlen-(v×⌊hlen⁄v⌋))\)比特;
- 令\(Ha=Ha_1 ‖Ha_2 ‖⋯‖Ha_{⌈hlen⁄v⌉-1} ‖Ha!_{⌈hlen⁄v⌉}\) ;
- 计算\(h_1=(Ha\mod{(n-1)})+1\)。
密钥派生函数
设密码杂凑函数为\(H_v ()\),其输出是长度为\(v\)比特的杂凑值。
密钥派生函数\(KDF(Z,klen)\):
输入:比特串\(Z\),整数\(klen\)(表示要获得的密钥数据的比特长度,要求该值小于\((2^{32}-1)v\))。
输出:长度为\(klen\)的密钥数据比特串\(K\)。
- 初始化一个32比特构成的计数器\(ct=\mbox{0x00000001}\);
- 对\(i\)从\(1\)到\(⌈klen⁄v⌉\)执行:
2.1. 计算\(Ha_i=H_v(Z‖ct)\);
2.2. \(ct++\); - 若\(klen⁄v\)是整数,令\(Ha!_{⌈klen⁄v⌉} =Ha_{⌈klen⁄v⌉}\) ,否则令\(Ha!_{⌈klen⁄v⌉}\) 为\(Ha_{⌈klen⁄v⌉}\) 最左边的\((klen-(v×⌊klen⁄v⌋))\)比特;
- 令\(K=Ha_1 ‖Ha_2 ‖⋯‖Ha_{⌈klen⁄v⌉-1} ‖Ha!_{⌈klen⁄v⌉}\) 。
分组密码算法
分组加密算法包括加密算法\(Enc(K_1,m)\)和解密算法\(Dec(K_1,c)\)。\(Enc(K_1,m)\)表示用密钥\(K_1\)对明文\(m\)进行加密,其输出为密文比特串\(c\);\(Dec(K_1,c)\)表示用密钥\(K_1\)对密文\(c\)进行解密,其输出为明文比特串\(m\)或“错误”。密钥\(K_1\)的比特长度记为\(K_1\_len\)。
本部分规定使用国家密码管理主管部门批准的分组密码算法,如SM4分组密码算法。
消息认证码函数
消息认证码函数\(MAC(K_2,Z)\)的作用是防止消息数据\(Z\)被非法篡改,它在密钥\(K_2\)的控制下,产生消息数据比特串\(Z\)的认证码,密钥\(K_2\)的比特长度记为\(K_2\_len\)。在本部分的基于标识的加密算法中,消息认证码函数使用密钥派生函数生成的密钥对密文比特串求取消息认证码,从而使解密者可以鉴别消息的来源和检验数据的完整性。
消息认证码函数需要调用密码杂凑函数。
设密码杂凑函数为\(H_v ()\),其输出是长度为\(v\)比特的杂凑值。
消息认证码函数\(MAC(K_2,Z)\):
输入:比特串\(K_2\)(比特长度为\(K_2\_len\)的密钥),比特串\(Z\)(待求取消息认证码的消息)。
输出:长度为\(v\)的消息认证码数据比特串\(K\)。
- \(K=H_v(Z‖K_2 )\)
密钥封装机制
密钥封装算法
为了封装比特长度为\(klen\)的密钥给用户B,作为封装者的用户A需要执行以下运算步骤:
A1.计算群\(G_1\)中的元素\(Q_B=[H_1(ID_B ‖hid,N) ] P_1+P_{pub-e}\);
A2.产生随机数\(r∈[1,N-1]\);
A3.计算群\(G_1\)中的元素\(C=[r] Q_B\);
A4.计算群\(G_T\)中的元素\(g=e(P_{pub-e},P_2 )\);
A5.计算群\(G_T\)中的元素\(w=g^r\);
A6.计算\(K=KDF(C‖w‖ID_B,klen)\),若\(K\)为全0比特串,则返回A2;
A7.输出\((K,C)\),其中\(K\)是被封装的密钥,\(C\)是封装密文。
解封装算法
用户B收到封装密文\(C\)后,为了对比比特长度为\(klen\)的密钥解封装,需要执行以下运算步骤:
B1.验证\(C∈G_1\)是否成立,若不成立则报错并退出;
B2.计算群\(G_T\)中的元素\(w'=e(C,de_B )\);
B3.计算封装的密钥\(K'=KDF(C‖w'‖ID_B,klen)\),若\(K'\)为全0比特串,则报错并退出;
B4.输出密钥\(K'\)。
公钥加密算法
加密算法
设需要发送的消息为比特串\(M\),\(mlen\)为\(M\)的比特长度,\(K_1\_len\)为分组密码算法中密钥\(K_1\)的比特长度,\(K_2\_len\)为函数\(MAC(K_2,Z)\)中密钥\(K_2\)的比特长度。
为了加密明文\(M\)给用户B,作为加密者的用户A应实现以下运算步骤:
A1.计算群\(G_1\)中的元素\(Q_B=[H_1(ID_B ‖hid,N) ] P_1+P_{pub-e}\);
A2.产生随机数\(r∈[1,N-1]\);
A3.计算群\(G_1\)中的元素\(C_1=[r] Q_B\);
A4.计算群\(G_T\)中的元素\(g=e(P_{pub-e},P_2 )\);
A5.计算群\(G_T\)中的元素\(w=g^r\);
A6.按加密明文的方法分类进行计算:
a) 如果加密明文的方法是基于密钥派生函数的序列密码算法,则
1) 计算整数\(klen=mlen+K_2\_len\),然后计算\(K=KDF(C_1 ‖w‖ID_B,klen)\)。令\(K_1\)为\(K\)最左边的\(mlen\)比特,\(K_2\)为剩下的\(K_2\_len\)比特,若\(K_1\)为全0比特串,则返回A2;
2) 计算\(C_2=M⊕K_1\)。
b) 如果加密明文的方法是结合密钥派生函数的分组密码算法,则
1) 计算整数\(klen=K_1\_len+K_2\_len\),然后计算\(K=KDF(C_1 ‖w‖ID_B,klen)\)。令\(K_1\)为\(K\)最左边的\(K_1\_len\)比特,\(K_2\)为剩下的\(K_2\_len\)比特,若\(K_1\)为全0比特串,则返回A2;
2) 计算\(C_2=Enc(K_1,M)\)。
A7.计算\(C_3=MAC(K_2,C_2 )\);
A8.输出密文\(C=C_1 ‖C_2 ‖C_3\)。
解密算法
设\(mlen\)为密文\(C=C_1 ‖C_2 ‖ C_3\)中\(C_2\)的比特长度,\(K_1\_len\)为分组密码算法中密钥\(K_1\)的比特长度,\(K_2\_len\)为函数\(MAC(K_2,Z)\)中密钥\(K_2\)的比特长度。
为了对\(C\)进行解密,作为解密者的用户B应实现以下运算步骤:
B1.从\(C\)中取出比特串\(C_1\),验证\(C_1∈G_1\)是否成立,若不成立则报错并退出;
B2.计算群\(G_T\)中的元素\(w'=e(C_1,de_B )\);
B3.按加密明文的方法分类进行计算:
a) 如果加密明文的方法是基于密钥派生函数的序列密码算法,则
1) 计算整数\(klen=mlen+K_2\_len\),然后计算\(K'=KDF(C_1 ‖w'‖ID_B,klen)\)。令\(K_1'\)为\(K'\)最左边的\(mlen\)比特,\(K_2'\)为剩下的\(K_2\_len\)比特,若\(K_1'\)为全0比特串,则报错并退出;
2) 计算\(M'=C_2⊕K_1'\)。
b) 如果加密明文的方法是结合密钥派生函数的分组密码算法,则
1) 计算整数\(klen=K_1\_len+K_2\_len\),然后计算\(K'=KDF(C_1 ‖w'‖ID_B,klen)\)。令\(K_1'\)为\(K'\)最左边的\(K_1\_len\)比特,\(K_2'\)为剩下的\(K_2\_len\)比特,若\(K_1'\)为全0比特串,则报错并退出;
2) 计算\(M'=Dec(K_1',C_2 )\)。
B4.计算\(u=MAC(K_2',C_2 )\),从\(C\)中取出比特串\(C_3\),若\(u≠C_3\),则报错并退出;
B5.输出明文\(M'\)。
注1:注意到加密主公钥为\(P_{pub-e}=[ke] P_1\),且用户B的加密私钥为
注2:双线性对
设\((G_1,+)\)、\((G_2,+)\)和\((G_T,⋅)\)是3个循环群,\(G_1\)、\(G_2\)和\(G_T\)的阶均为素数\(N\),\(P_1\)是\(G_1\)的生成元,\(P_2\)是\(G_2\)的生成元,存在\(G_2\)到\(G_1\)的同态映射\(ψ\)使得\(ψ(P_2 )=P_1\)。
双线性对\(e\)是\(G_1×G_2→G_T\)的映射,满足如下条件:
a) 双线性性:对任意的\(P∈G_1\),\(Q∈G_2\),\(a,b∈Z_N\),有\(e([a]P,[b]Q)={e(P,Q)}^{ab}\);
b) 非退化性:\(e(P_1,P_2 )≠1_(G_T )\);
c) 可计算性:对任意的\(P∈G_1\),\(Q∈G_2\),存在有效的算法计算\(e(P,Q)\)。
标准GM/T 0044.1—2016中7.1节、GM/T 0044.5—2016中3.1节规定了,SM9算法使用R-ate对(\(eid\):\(\mbox{0x04}\))。