From b1fd853270ba7c2a40d6e4480289ca54ba0b9c3d Mon Sep 17 00:00:00 2001 From: sangge <2251250136@qq.com> Date: Sun, 15 Oct 2023 14:00:55 +0800 Subject: [PATCH 1/9] feat: add KDF function --- src/tpre.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/tpre.py b/src/tpre.py index f4b8a85..6691984 100644 --- a/src/tpre.py +++ b/src/tpre.py @@ -117,7 +117,7 @@ def jacobianMultiply( return jacobianAdd(jacobianDouble(jacobianMultiply((Xp, Yp, Zp), n // 2, N, A, P), A, P), (Xp, Yp, Zp), A, P) raise ValueError("jacobian Multiply error") -def Setup(sec: int) -> Tuple[CurveFp, Tuple[int, int], +def Setup() -> Tuple[CurveFp, Tuple[int, int], Tuple[int, int], Callable, Callable, Callable, Callable]: ''' @@ -125,7 +125,6 @@ def Setup(sec: int) -> Tuple[CurveFp, Tuple[int, int], sec: an init safety param return: -<<<<<<< HEAD G: sm2 curve g: generator U: another generator @@ -159,7 +158,7 @@ def Setup(sec: int) -> Tuple[CurveFp, Tuple[int, int], for j in i: sm3.update(j.to_bytes()) digest = sm3.digest() - digest = int.from_bytes(digest,'big') % sm2p256v1.P + digest = int.from_bytes(digest, 'big') % sm2p256v1.P return digest def hash4(triple_G: Tuple[Tuple[int, int], @@ -172,10 +171,18 @@ def Setup(sec: int) -> Tuple[CurveFp, Tuple[int, int], sm3.update(j.to_bytes()) sm3.update(Zp.to_bytes()) digest = sm3.digest() - digest = int.from_bytes(digest,'big') % sm2p256v1.P + digest = int.from_bytes(digest, 'big') % sm2p256v1.P return digest - KDF = Sm3() #pylint: disable=e0602 + def KDF(G: Tuple[int, int]) -> int: + sm3 = Sm3() #pylint: disable=e0602 + for i in G: + sm3.update(i.to_bytes()) + digest = sm3.digest() + digest = digest + digest = int.from_bytes(digest, 'big') % sm2p256v1.P + return digest + return G, g, U, hash2, hash3, hash4, KDF @@ -209,8 +216,10 @@ def Enc(pk: Tuple[int, int], m: int) -> Tuple[Tuple[ enca = Encapsulate(pk) K = enca[0] capsule = enca[1] - - sm4_enc = Sm4Cbc(key, iv, DO_ENCRYPT) #pylint: disable=e0602 + if len(K) != 16: + raise ValueError("invalid key length") + iv = b'tpretpretpretpre' + sm4_enc = Sm4Cbc(K, iv, DO_ENCRYPT) #pylint: disable=e0602 plain_Data = m.to_bytes() enc_Data = sm4_enc.update(plain_Data) enc_Data += sm4_enc.finish() From 19298152c57cf5fac9649797e24f9044d4bec51f Mon Sep 17 00:00:00 2001 From: sangge <2251250136@qq.com> Date: Sun, 15 Oct 2023 14:01:12 +0800 Subject: [PATCH 2/9] feat: temp docker file --- dockerfile | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 dockerfile diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..ec874e3 --- /dev/null +++ b/dockerfile @@ -0,0 +1,10 @@ +FROM git.mamahaha.work/sangge/tpre:base + +COPY src /app + +COPY requirements.txt /app/requirements.txt + +WORKDIR /app + +RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple + From d5527c0c8dc539d1fe585eb81f3cb18dbb941167 Mon Sep 17 00:00:00 2001 From: sangge <2251250136@qq.com> Date: Sun, 15 Oct 2023 14:01:31 +0800 Subject: [PATCH 3/9] doc: update readme --- README_en.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/README_en.md b/README_en.md index 762487a..08e72f2 100644 --- a/README_en.md +++ b/README_en.md @@ -6,11 +6,23 @@ This project is designed for the National Cryptography Competition and is implem The project uses the Chinese national standard cryptography algorithm to implement distributed proxy re-encryption (TPRE). +## Project Structure +. +├── basedockerfile (being used to build base iamge) +├── dockerfile (being used to build application) +├── include (gmssl header) +├── lib (gmssl shared object) +├── LICENSE +├── README_en.md +├── README.md +├── requirements.txt +└── src (application source code) + ## Environment Dependencies System requirements: - Linux -- Windows +- Windows(may need to complie and install gmssl yourself) The project relies on the following software: - Python 3.11 @@ -27,6 +39,26 @@ Visit [GmSSL](https://github.com/guanzhi/GmSSL) to learn how to install. pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple ``` + +## Docker Installation +my docker version: +- Version: 24.0.5 +- API version: 1.43 +- Go version: go1.20.6 + +### Use base image and build yourself +```bash +docker pull git.mamahaha.work/sangge/tpre:base +docker build . -t your_image_name +docker run your_image_name +``` + +### Use pre-build image +```bash +docker pull git.mamahaha.work/sangge/tpre:latest +docker run git.mamahaha.work/sangge/tpre:latest +``` + ## Usage Instructions From 60877626552f05636ff5e76ca3eb29d3c1df79a1 Mon Sep 17 00:00:00 2001 From: sangge <2251250136@qq.com> Date: Sun, 15 Oct 2023 14:02:26 +0800 Subject: [PATCH 4/9] feat: update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 80d5f5f..c8705f0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ test.py example.py ReEncrypt.py +src/demo.py From 00425394c4f2aab05123c99032d77186425500e2 Mon Sep 17 00:00:00 2001 From: sangge <2251250136@qq.com> Date: Sun, 15 Oct 2023 14:04:17 +0800 Subject: [PATCH 5/9] style: update readme style --- README_en.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README_en.md b/README_en.md index 08e72f2..46ccff6 100644 --- a/README_en.md +++ b/README_en.md @@ -7,16 +7,16 @@ This project is designed for the National Cryptography Competition and is implem The project uses the Chinese national standard cryptography algorithm to implement distributed proxy re-encryption (TPRE). ## Project Structure -. -├── basedockerfile (being used to build base iamge) -├── dockerfile (being used to build application) -├── include (gmssl header) -├── lib (gmssl shared object) -├── LICENSE -├── README_en.md -├── README.md -├── requirements.txt -└── src (application source code) +. +├── basedockerfile (being used to build base iamge) +├── dockerfile (being used to build application) +├── include (gmssl header) +├── lib (gmssl shared object) +├── LICENSE +├── README_en.md +├── README.md +├── requirements.txt +└── src (application source code) ## Environment Dependencies @@ -63,7 +63,7 @@ docker run git.mamahaha.work/sangge/tpre:latest ## References -[TPRE Algorithm Blog Post](https://www.cnblogs.com/pam-sh/p/17364656.html#tprelib%E7%AE%97%E6%B3%95) +[TPRE Algorithm Blog Post](https://www.cnblogs.com/pam-sh/p/17364656.html#tprelib%E7%AE%97%E6%B3%95) [Gmssl-python library](https://github.com/GmSSL/GmSSL-Python) From 9c35cf1519c7739a3664a7400c7bd48249a681e5 Mon Sep 17 00:00:00 2001 From: sangge <2251250136@qq.com> Date: Mon, 16 Oct 2023 10:58:47 +0800 Subject: [PATCH 6/9] feat: merge form jiangchao --- src/tpre.py | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 147 insertions(+), 5 deletions(-) diff --git a/src/tpre.py b/src/tpre.py index 419bc31..809f8d6 100644 --- a/src/tpre.py +++ b/src/tpre.py @@ -210,7 +210,7 @@ def GenerateKeyPair( return public_key, secret_key -def Enc(pk: Tuple[int, int], m: int) -> Tuple[Tuple[ +def Encrypt(pk: Tuple[int, int], m: int) -> Tuple[Tuple[ Tuple[int, int],Tuple[int, int], int], int]: enca = Encapsulate(pk) K = enca[0].to_bytes() @@ -225,9 +225,31 @@ def Enc(pk: Tuple[int, int], m: int) -> Tuple[Tuple[ enc_message = (capsule, enc_Data) return enc_message +def Decapsulate(ska:int,capsule:Tuple[Tuple[int,int],Tuple[int,int],int]) -> int: + E,V,s = capsule + EVa=multiply(add(E,V), ska) # (E*V)^ska + K = KDF(EVa) + + return K + +def Decrypt(sk_A: int,C:Tuple[Tuple[ + Tuple[int, int],Tuple[int, int], int], int]) ->int: + ''' + params: + sk_A: secret key + C: (capsule, enc_data) + ''' + capsule,enc_Data = C + K = Decapsulate(sk_A,capsule) + iv = b'tpretpretpretpre' + sm4_dec = Sm4Cbc(K, iv, DO_DECRYPT) #pylint: disable= e0602 + dec_Data = sm4_dec.update(enc_Data) + dec_Data += sm4_dec.finish() + return dec_Data + # GenerateRekey def H5(id: int, D: int) -> int: - sm3 = Sm3() #pylint: ignore=e0602 + sm3 = Sm3() #pylint: disable=e0602 sm3.update(id.to_bytes(32)) sm3.update(D.to_bytes(32)) hash = sm3.digest() @@ -263,8 +285,10 @@ G, g, U, hash2, hash3, hash4, KDF = Setup(sec) def GenerateReKey(sk_A, pk_B, N: int, T: int) -> list: ''' - param: skA, pkB, N(节点总数), T(阈值) - return rki(0 <= i <= N-1) + param: + skA, pkB, N(节点总数), T(阈值) + return: + rki(0 <= i <= N-1) ''' # 计算临时密钥对(x_A, X_A) x_A = random.randint(0, G.P - 1) @@ -307,4 +331,122 @@ def Encapsulate(pk_A: Tuple[int, int]) -> Tuple[int, Tuple[Tuple[int, int], Tupl pk_A_ru = multiply(pk_A, r + u) K = KDF(pk_A_ru) capsule = (E, V, s) - return (K, capsule) \ No newline at end of file + return (K, capsule) + +def Checkcapsule(capsule:Tuple[Tuple[int,int],Tuple[int,int],int]) -> bool: # 验证胶囊的有效性 + E,V,s = capsule + h2 = hash2((E,V)) + g = (sm2p256v1.Gx, sm2p256v1.Gy) + result1 = multiply(g,s) + temp = multiply(E,h2) # 中间变量 + result2 =add(V,temp) # result2=V*E^H2(E,V) + if result1 == result2: + flag =True + else: + flag = False + + return flag + + +def ReEncapsulate(kFrag:list,capsule:Tuple[Tuple[int,int],Tuple[int,int],int]) -> Tuple[Tuple[int,int],Tuple[int,int],int,Tuple[int,int]] : + id,rk,Xa,U1 = kFrag + E,V,s = capsule + if not Checkcapsule(capsule): + raise ValueError('Invalid capsule') + flag = Checkcapsule(capsule) + assert flag == True # 断言,判断胶囊capsule的有效性 + E1 = multiply(E,rk) + V1 = multiply(V,rk) + cfrag = E1,V1,id,Xa + return cfrag # cfrag=(E1,V1,id,Xa) E1= E^rk V1=V^rk + + # 重加密函数 +def ReEncrypt(kFrag:list, + C:Tuple[Tuple[Tuple[int,int],Tuple[int,int],int],int])->Tuple[Tuple[Tuple[int,int],Tuple[int,int],int,Tuple[int,int]],int] : + capsule,enc_Data = C + + cFrag = ReEncapsulate(kFrag,capsule) + return (cFrag,enc_Data) # 输出密文 +# capsule, enc_Data = C + + +def mergecfrag()->tuple[Tuple[Tuple[int,int],Tuple[int,int] + ,int,Tuple[int,int]], ...]: + cfrags = () + kfrags = GenerateReKey(sk_A,pk_B,N,t) + result = Encapsulate(pk_A) + K,capsule = result + for kfrag in kfrags: + cfrag = ReEncapsulate(kfrag,capsule) + cfrags = cfrags + (cfrag,) + + return cfrags + + + +def DecapsulateFrags(sk_B:int,pk_A:Tuple[int,int],cFrags:Tuple[Tuple[Tuple[int,int],Tuple[int,int],int,Tuple[int,int]]] + ,capsule:Tuple[Tuple[int,int],Tuple[int,int],int]) -> int: + ''' + return: + K: sm4 key + ''' + Elist = [] + Vlist = [] + idlist = [] + Xalist = [] + t = 0 + for cfrag in cFrags: # Ei,Vi,id,Xa = cFrag + Elist.append(cfrag[0]) + Vlist.append(cfrag[1]) + idlist.append(cfrag[2]) + Xalist.append(cfrag[3]) + t = t+1 # 总共有t个片段,t为阈值 + + pkab = multiply(pk_A,sk_B) # pka^b + D = H6((pk_A,pk_B,pkab)) + Sx = [] + for id in idlist: # 从1到t + sxi = H5(id,D) # id 节点的编号 + Sx.append(sxi) + bis= [] # b ==> λ + j = 1 + i = 1 + bi =1 + for i in range(t): + for j in range(t): + if j == i: + j=j+1 + else: + bi = bi * (Sx[j]//(Sx[j]-Sx[i])) # 暂定整除 + bis.append(bi) + + E2=multiply(Elist[0],bis[0]) # E^ 便于计算 + V2=multiply(Vlist[0],bis[0]) # V^ + for k in range(1,t): + Ek = multiply(Elist[k],λis[k]) # EK/Vk 是个列表/元组 + Vk = multiply(Vlist[k],λis[k]) + E2 = add(Ek,E2) + V2 = add(Vk,V2) + Xab = multiply(Xa,b) # Xa^b + d = hash3((Xa,pk_B,Xab)) + EV = add(E2,V2) # E2 + V2 + EVd = multiply(EV,d) # (E2 + V2)^d + K = KDF(EVd) + + return K + +# M = IAEAM(K,enc_Data) + +def DecryptFrags(sk_B:int, + pk_A:Tuple[int,int], + cFrags:Tuple[Tuple[Tuple[int,int],Tuple[int,int],int,Tuple[int,int]]], + C:Tuple[Tuple[Tuple[int,int],Tuple[int,int],int],int] + )->int: + capsule,enc_Data = C # 加密后的密文 + K = DecapsulateFrags(sk_B,pk_A,cFrags,capsule) + + iv = b'tpretpretpretpre' + sm4_dec = Sm4Cbc(K, iv, DO_DECRYPT) #pylint: disable= e0602 + dec_Data = sm4_dec.update(enc_Data) + dec_Data += sm4_dec.finish() + return dec_Data \ No newline at end of file From 56f8945b46a7000b8e614870955ffaac3c860d00 Mon Sep 17 00:00:00 2001 From: ccyj <2384899431@qq.com> Date: Mon, 16 Oct 2023 14:51:34 +0800 Subject: [PATCH 7/9] =?UTF-8?q?fix:=20mergeccfrag=20=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8F=82=E6=95=B0N:int=EF=BC=8Ct:int=20?= =?UTF-8?q?=EF=BC=9B=20DecapsulateFrags=E5=87=BD=E6=95=B0=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=8F=98=E9=87=8F=E5=90=8D=E5=AD=97,=CE=BB->b?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tpre.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tpre.py b/src/tpre.py index 809f8d6..aca6a7c 100644 --- a/src/tpre.py +++ b/src/tpre.py @@ -370,7 +370,8 @@ def ReEncrypt(kFrag:list, # capsule, enc_Data = C -def mergecfrag()->tuple[Tuple[Tuple[int,int],Tuple[int,int] +# N 是加密节点的数量,t是阈值 +def mergecfrag(N:int,t:int)->tuple[Tuple[Tuple[int,int],Tuple[int,int] ,int,Tuple[int,int]], ...]: cfrags = () kfrags = GenerateReKey(sk_A,pk_B,N,t) @@ -423,8 +424,8 @@ def DecapsulateFrags(sk_B:int,pk_A:Tuple[int,int],cFrags:Tuple[Tuple[Tuple[int,i E2=multiply(Elist[0],bis[0]) # E^ 便于计算 V2=multiply(Vlist[0],bis[0]) # V^ for k in range(1,t): - Ek = multiply(Elist[k],λis[k]) # EK/Vk 是个列表/元组 - Vk = multiply(Vlist[k],λis[k]) + Ek = multiply(Elist[k],bis[k]) # EK/Vk 是个列表 + Vk = multiply(Vlist[k],bis[k]) E2 = add(Ek,E2) V2 = add(Vk,V2) Xab = multiply(Xa,b) # Xa^b From cd1e88471360e51de5649174220acb18a93fc40d Mon Sep 17 00:00:00 2001 From: sangge <2251250136@qq.com> Date: Mon, 16 Oct 2023 22:30:15 +0800 Subject: [PATCH 8/9] fix: extract hash and kdf from setup --- src/tpre.py | 96 +++++++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 51 deletions(-) diff --git a/src/tpre.py b/src/tpre.py index aca6a7c..cbd3969 100644 --- a/src/tpre.py +++ b/src/tpre.py @@ -118,8 +118,7 @@ def jacobianMultiply( raise ValueError("jacobian Multiply error") def Setup(sec: int) -> Tuple[CurveFp, Tuple[int, int], - Tuple[int, int], Callable, - Callable, Callable, Callable]: + Tuple[int, int]]: ''' params: sec: an init safety param @@ -128,10 +127,6 @@ def Setup(sec: int) -> Tuple[CurveFp, Tuple[int, int], G: sm2 curve g: generator U: another generator - use sm3 as hash function - hash2: G^2 -> Zq - hash3: G^3 -> Zq - hash4: G^3 * Zq -> Zq ''' G = sm2p256v1 @@ -141,50 +136,49 @@ def Setup(sec: int) -> Tuple[CurveFp, Tuple[int, int], tmp_u = random.randint(0, sm2p256v1.P) U = multiply(g, tmp_u) - def hash2(double_G: Tuple[Tuple[int, int], Tuple[int, int]]) -> int: - sm3 = Sm3() #pylint: disable=e0602 - for i in double_G: - for j in i: - sm3.update(j.to_bytes(32)) - digest = sm3.digest() - digest = int.from_bytes(digest,'big') % sm2p256v1.P - return digest - - def hash3(triple_G: Tuple[Tuple[int, int], - Tuple[int, int], - Tuple[int, int]]) -> int: - sm3 = Sm3() #pylint: disable=e0602 - for i in triple_G: - for j in i: - sm3.update(j.to_bytes(32)) - digest = sm3.digest() - digest = int.from_bytes(digest, 'big') % sm2p256v1.P - return digest - - def hash4(triple_G: Tuple[Tuple[int, int], - Tuple[int, int], - Tuple[int, int]], - Zp: int) -> int: - sm3 = Sm3() #pylint: disable=e0602 - for i in triple_G: - for j in i: - sm3.update(j.to_bytes(32)) - sm3.update(Zp.to_bytes(32)) - digest = sm3.digest() - digest = int.from_bytes(digest, 'big') % sm2p256v1.P - return digest - - def KDF(G: Tuple[int, int]) -> int: - sm3 = Sm3() #pylint: disable=e0602 - for i in G: - sm3.update(i.to_bytes(32)) - digest = sm3.digest(32) - digest = digest - digest = int.from_bytes(digest, 'big') % sm2p256v1.P - return digest - - - return G, g, U, hash2, hash3, hash4, KDF + return G, g, U + +def hash2(double_G: Tuple[Tuple[int, int], Tuple[int, int]]) -> int: + sm3 = Sm3() #pylint: disable=e0602 + for i in double_G: + for j in i: + sm3.update(j.to_bytes(32)) + digest = sm3.digest() + digest = int.from_bytes(digest,'big') % sm2p256v1.P + return digest + +def hash3(triple_G: Tuple[Tuple[int, int], + Tuple[int, int], + Tuple[int, int]]) -> int: + sm3 = Sm3() #pylint: disable=e0602 + for i in triple_G: + for j in i: + sm3.update(j.to_bytes(32)) + digest = sm3.digest() + digest = int.from_bytes(digest, 'big') % sm2p256v1.P + return digest + +def hash4(triple_G: Tuple[Tuple[int, int], + Tuple[int, int], + Tuple[int, int]], + Zp: int) -> int: + sm3 = Sm3() #pylint: disable=e0602 + for i in triple_G: + for j in i: + sm3.update(j.to_bytes(32)) + sm3.update(Zp.to_bytes(32)) + digest = sm3.digest() + digest = int.from_bytes(digest, 'big') % sm2p256v1.P + return digest + +def KDF(G: Tuple[int, int]) -> int: + sm3 = Sm3() #pylint: disable=e0602 + for i in G: + sm3.update(i.to_bytes(32)) + digest = sm3.digest(32) + digest = digest + digest = int.from_bytes(digest, 'big') % sm2p256v1.P + return digest def GenerateKeyPair( lamda_parma: int, @@ -281,7 +275,7 @@ pk_B, sk_B = GenerateKeyPair(0, ()) sec = 256 # 调用Setup函数 -G, g, U, hash2, hash3, hash4, KDF = Setup(sec) +G, g, U= Setup(sec) def GenerateReKey(sk_A, pk_B, N: int, T: int) -> list: ''' From c972af0371cbd06e5b24996e01e02ef54f4cfca9 Mon Sep 17 00:00:00 2001 From: ccyj <2384899431@qq.com> Date: Mon, 16 Oct 2023 22:31:31 +0800 Subject: [PATCH 9/9] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E4=BA=86=E5=8F=82?= =?UTF-8?q?=E6=95=B0X=5FA=EF=BC=8C=E5=9B=A0=E4=B8=BA=E5=80=BC=E6=98=AF?= =?UTF-8?q?=E5=9B=BA=E5=AE=9A=E7=9A=84=EF=BC=8C=E7=9B=B4=E6=8E=A5=E8=AF=BB?= =?UTF-8?q?=E5=8F=96list=E4=B8=AD=E7=9A=84=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tpre.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tpre.py b/src/tpre.py index aca6a7c..0c6273e 100644 --- a/src/tpre.py +++ b/src/tpre.py @@ -394,13 +394,13 @@ def DecapsulateFrags(sk_B:int,pk_A:Tuple[int,int],cFrags:Tuple[Tuple[Tuple[int,i Elist = [] Vlist = [] idlist = [] - Xalist = [] + X_Alist = [] t = 0 for cfrag in cFrags: # Ei,Vi,id,Xa = cFrag Elist.append(cfrag[0]) Vlist.append(cfrag[1]) idlist.append(cfrag[2]) - Xalist.append(cfrag[3]) + X_Alist.append(cfrag[3]) t = t+1 # 总共有t个片段,t为阈值 pkab = multiply(pk_A,sk_B) # pka^b @@ -428,8 +428,8 @@ def DecapsulateFrags(sk_B:int,pk_A:Tuple[int,int],cFrags:Tuple[Tuple[Tuple[int,i Vk = multiply(Vlist[k],bis[k]) E2 = add(Ek,E2) V2 = add(Vk,V2) - Xab = multiply(Xa,b) # Xa^b - d = hash3((Xa,pk_B,Xab)) + X_Ab = multiply(Xalist[0],b) # X_A^b X_A 的值是随机生成的xa,通过椭圆曲线上的倍点运算生成的固定的值 + d = hash3((Xalist[0],pk_B,X_Ab)) EV = add(E2,V2) # E2 + V2 EVd = multiply(EV,d) # (E2 + V2)^d K = KDF(EVd)