1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
""" 考虑K=kG ,其中K、G为椭圆曲线Ep(a,b)上的点,n为G的阶(nG=O∞ ),k为小于n的整数。 则给定k和G,根据加法法则,计算K很容易但反过来,给定K和G,求k就非常困难。 因为实际使用中的ECC原则上把p取得相当大,n也相当大,要把n个解点逐一算出来列成上表是不可能的。 这就是椭圆曲线加密算法的数学依据 点G称为基点(base point) k(k<n)为私有密钥(privte key) K为公开密钥(public key) """
def get_inverse(mu, p): """ 获取y的负元 """ for i in range(1, p): if (i*mu)%p == 1: return i return -1
def get_gcd(zi, mu): """ 获取最大公约数 """ if mu: return get_gcd(mu, zi%mu) else: return zi
def get_np(x1, y1, x2, y2, a, p): """ 获取n*p,每次+p,直到求解阶数np=-p """ flag = 1
if x1 == x2 and y1 == y2: zi = 3 * (x1 ** 2) + a mu = 2 * y1
else: zi = y2 - y1 mu = x2 - x1 if zi* mu < 0: flag = 0 zi = abs(zi) mu = abs(mu)
gcd_value = get_gcd(zi, mu) zi = zi // gcd_value mu = mu // gcd_value inverse_value = get_inverse(mu, p) k = (zi * inverse_value)
if flag == 0: k = -k k = k % p """ x3≡k2-x1-x2(mod p) y3≡k(x1-x3)-y1(mod p) """ x3 = (k ** 2 - x1 - x2) % p y3 = (k * (x1 - x3) - y1) % p return x3,y3
def get_rank(x0, y0, a, b, p): """ 获取椭圆曲线的阶 """ x1 = x0 y1 = (-1*y0)%p tempX = x0 tempY = y0 n = 1 while True: n += 1 p_x,p_y = get_np(tempX, tempY, x0, y0, a, p) if p_x == x1 and p_y == y1: return n+1 tempX = p_x tempY = p_y
def get_param(x0, a, b, p): """ 计算p与-p """ y0 = -1 for i in range(p): if i**2%p == (x0**3 + a*x0 + b)%p: y0 = i break
if y0 == -1: return False
x1 = x0 y1 = (-1*y0) % p return x0,y0,x1,y1
def get_graph(a, b, p): """ 输出椭圆曲线散点图 """ x_y = [] for i in range(p): x_y.append(['-' for i in range(p)])
for i in range(p): val =get_param(i, a, b, p) if(val != False): x0,y0,x1,y1 = val x_y[x0][y0] = 1 x_y[x1][y1] = 1
print("椭圆曲线的散列图为:") for i in range(p): temp = p-1-i
if temp >= 10: print(temp, end=" ") else: print(temp, end=" ")
for j in range(p): print(x_y[j][temp], end=" ") print("")
print(" ", end="") for i in range(p): if i >=10: print(i, end=" ") else: print(i, end=" ") print('\n')
def get_ng(G_x, G_y, key, a, p): """ 计算nG """ temp_x = G_x temp_y = G_y while key != 1: temp_x,temp_y = get_np(temp_x,temp_y, G_x, G_y, a, p) key -= 1 return temp_x,temp_y
def ecc_main(): while True: a = int(input("请输入椭圆曲线参数a(a>0)的值:")) b = int(input("请输入椭圆曲线参数b(b>0)的值:")) p = int(input("请输入椭圆曲线参数p(p为素数)的值:"))
if (4*(a**3)+27*(b**2))%p == 0: print("您输入的参数有误,请重新输入!!!\n") else: break
get_graph(a, b, p)
print("user1:在如上坐标系中选一个值为G的坐标") G_x = int(input("user1:请输入选取的x坐标值:")) G_y = int(input("user1:请输入选取的y坐标值:"))
n = get_rank(G_x, G_y, a, b, p)
key = int(input("user1:请输入私钥小key(<{}):".format(n)))
KEY_x,kEY_y = get_ng(G_x, G_y, key, a, p)
k = int(input("user2:请输入一个整数k(<{})用于求kG和kQ:".format(n))) k_G_x,k_G_y = get_ng(G_x, G_y, k, a, p) k_Q_x,k_Q_y = get_ng(KEY_x, kEY_y, k, a, p)
plain_text = input("user2:请输入需要加密的字符串:") plain_text = plain_text.strip() c = [] print("密文为:",end="") for char in plain_text: intchar = ord(char) cipher_text = intchar*k_Q_x c.append([k_G_x, k_G_y, cipher_text]) print("({},{}),{}".format(k_G_x, k_G_y, cipher_text),end="-")
print("\nuser1解密得到明文:",end="") for charArr in c: decrypto_text_x,decrypto_text_y = get_ng(charArr[0], charArr[1], key, a, p) print(chr(charArr[2]//decrypto_text_x),end="")
if __name__ == "__main__": print("*************ECC椭圆曲线加密*************") ecc_main()
|