画验证曲线_椭圆曲线加密算法(ECC)
橢圓曲線加密算法,簡稱ECC,是基于橢圓曲線數學理論實現的一種非對稱加密算法。相比RSA,ECC優勢是可以使用更短的密鑰,來實現與RSA相當或更高的安全,RSA加密算法也是一種非對稱加密算法,在公開密鑰加密和電子商業中RSA被廣泛使用。據研究,160位ECC加密安全性相當于1024位RSA加密,210位ECC加密安全性相當于2048位RSA加密(有待考證)。
比特幣Bitcoin使用了 secp256k1這條特殊的橢圓曲線:
一、阿貝爾群
橢圓曲線也可以有運算,像實數的加減乘除一樣,這就需要使用到加群。19世紀挪威的尼爾斯·阿貝爾抽象出了加群(又叫阿貝爾群或交換群)。數學中的群是一個集合,我們為它定義了一個“加法”,并用符號+表示。假定群用 表示,則加法必須遵循以下四個特性:
- 封閉性:如果a和b都是 的成員,那么a+b也是 的成員;
- 結合律:(a + b) + c = a + (b + c);
- 單位元:a+0=0+a=a,0就是單位元;
- 逆元:對于任意值a必定存在b,使得a+b=0。
如果再增加一個條件,交換律:a + b = b + a,則稱這個群為阿貝爾群,根據這個定義整數集是個阿貝爾群。
二、橢圓曲線的加法
過曲線上的兩點A、B畫一條直線,找到直線與橢圓曲線的交點,交點關于x軸對稱位置的點,定義為A+B,即為加法。如下圖所示:A + B = C
三、橢圓曲線的二倍運算
上述方法無法解釋A + A,即兩點重合的情況,因此在這種情況下,將橢圓曲線在A點的切線,與橢圓曲線的交點,交點關于x軸對稱位置的點,定義為A + A,即2A,即為二倍運算。
四、同余運算
同余就是有相同的余數,兩個整數 a、 b,若它們除以正整數 m所得的余數相等,則稱 a, b對于模m同余。
五、有限域
橢圓曲線是連續的,并不適合用于加密;所以必須把橢圓曲線變成離散的點,要把橢圓曲線定義在有限域上。而橢圓曲線密碼所使用的橢圓曲線是定義在有限域內,有限域最常見的例子是有限域GF(p),指給定某質數p,由0,1,2...p-1共p個元素組成的整數集合中加法、二倍運算。例如GF(233)就是
六、乘法逆元
在模7乘法中:
- 1的逆元為1 (1*1)%7=1
- 2的逆元為4 (2*4)%7=1
- 3的逆元為5 (3*5)%7=1
- 4的逆元為2 (4*2)%7=1
- 5的逆元為3 (5*3)%7=1
- 6的逆元為6 (6*6)%7=1
七、數學解釋
并不是所有的橢圓曲線都適合加密,
是一類可以用來加密的橢圓曲線,也是最為簡單的一類。針對曲線Ep(a,b)表示為
該曲線關于x軸對稱。選擇兩個滿足下列條件的小于p(p為素數)的非負整數a、b,要求滿足以下條件
1、有限域的負元
的負元是2、有限域的加法, , 和 三點(其中R是PQ直線與曲線的交點的關于x軸的對稱點,即 )有如下關系:
3、斜率計算(P=Q即要計算P點切線,需要求導)
若
,則若 ,則
該公式可以自己推導,為了方便理解,可以套用以上公式,解決以下例題。
例:已知
上兩點 , ,求1) ,2) ,3)解:1)
的負元是2)
, ,因為 所以2的乘法逆元為12, 故 k=11。 故的坐標為3)
, ,因為,5的乘法逆元為14,故k=6。 故 的坐標為八、橢圓曲線加解密算法原理
設私鑰、公鑰分別為d、Q,即Q = dG,其中G為基點,橢圓曲線上的已知G和dG,求d是非常困難的,也就是說已知公鑰和基點,想要算出私鑰是非常困難的。公鑰加密:選擇隨機數r,將消息M生成密文C,該密文是一個點對,C = {rG, M+rQ},其中Q為公鑰。私鑰解密:M + rQ - d(rG) = M + r(dG) - d(rG) = M,其中d、Q分別為私鑰、公鑰。
九、橢圓曲線簽名算法原理
橢圓曲線簽名算法(ECDSA)。設私鑰、公鑰分別為d、Q,即Q = dG,其中G為基點。
私鑰簽名:
- 選擇隨機數r,計算點rG(x, y)。
- 根據隨機數r、消息M的哈希h、私鑰d,計算s = (h + dx)/r。
- 將消息M、和簽名{rG, s}發給接收方。
公鑰驗證簽名:
- 接收方收到消息M、以及簽名{rG=(x,y), s}。
- 根據消息求哈希h。
- 使用發送方公鑰Q計算:hG/s + xQ/s,并與rG比較,如相等即驗簽成功。
原理:hG/s + xQ/s = hG/s + x(dG)/s = (h+xd)G/s = r(h+xd)G / (h+dx) = rG
10、簽名過程
假設要簽名的消息是一個字符串:“Hello World!”。DSA簽名的第一個步驟是對待簽名的消息生成一個消息摘要,不同的簽名算法使用不同的消息摘要算法,而ECDSA256使用SHA256生成256比特的摘要。
摘要生成結束后,應用簽名算法對摘要進行簽名:
- 產生一個隨機數k
- 利用隨機數k,計算出兩個大數r和s。將r和s拼在一起就構成了對消息摘要的簽名。
這里需要注意的是,因為隨機數k的存在,對于同一條消息,使用同一個算法,產生的簽名是不一樣的。從函數的角度來理解,簽名函數對同樣的輸入會產生不同的輸出。因為函數內部會將隨機值混入簽名的過程。
11、驗證過程
關于驗證過程,這里不討論它的算法細節。從宏觀上看,消息的接收方從簽名中分離出r和s,然后利用公開的密鑰信息和s計算出r。如果計算出的r和接收到的r值相同,則表示驗證成功,否則,表示驗證失敗。
12、數值計算Demo實現
# -*- coding:utf-8 -*-def get_inverse(value, p):"""求逆元:param value: 待求逆元的值:param p: 模數"""for i in range(1, p):if (i * value) % p == 1:return ireturn -1def get_gcd(value1, value2):"""輾轉相除法求最大公約數:param value1::param value2:"""if value2 == 0:return value1else:return get_gcd(value2, value1 % value2)def get_PaddQ(x1, y1, x2, y2, a, p):"""計算P+Q:param x1: P點橫坐標:param y1: P點縱坐標:param x2: Q點橫坐標:param y2: Q點縱坐標:param a: 曲線參數:param p: 曲線模數"""flag = 1 # 定義符號位(+/-)# 如果P=Q,斜率k=(3x^2+a)/2y mod pif x1 == x2 and y1 == y2:member = 3 * (x1 ** 2) + a # 分子denominator = 2 * y1 # 分母# 如果P≠Q, 斜率k=(y2-y1)/(x2-x1) mod pelse:member = y2 - y1denominator = x2 - x1if member * denominator < 0:flag = 0 # 表示負數member = abs(member)denominator = abs(denominator)# 化簡分子分母gcd = get_gcd(member, denominator) # 最大公約數member = member // gcddenominator = denominator // gcd# 求分母的逆元inverse_deno = get_inverse(denominator, p)# 求斜率k = (member * inverse_deno)if flag == 0:k = -kk = k % p# 計算P+Q=(x3,y3)x3 = (k ** 2 - x1 - x2) % py3 = (k * (x1 - x3) - y1) % preturn x3, y3def get_order(x0, y0, a, b, p):"""計算橢圓曲線的階"""x1 = x0 # -P的橫坐標y1 = (-1 * y0) % p # -P的縱坐標temp_x = x0temp_y = y0n = 1while True:n += 1# 累加P,得到n*P=0∞xp, yp = get_PaddQ(temp_x, temp_y, x0, y0, a, p)# 如果(xp,yp)==-P,即(xp,yp)+P=0∞,此時n+1為階數if xp == x1 and yp == y1:return n + 1temp_x = xptemp_y = ypdef get_dot(x0, a, b, p):"""計算P和-P"""y0 = -1for i in range(p):# 滿足適合加密的橢圓曲線條件,Ep(a,b),p為質數,x,y∈[0,p-1]if i ** 2 % p == (x0 ** 3 + a * x0 + b) % p:y0 = ibreak# 如果找不到合適的y0返回Falseif y0 == -1:return False# 計算-yx1 = x0y1 = (-1 * y0) % preturn x0, y0, x1, y1def get_graph(a, b, p):"""畫出橢圓曲線散點圖"""xy = []# 初始化二維數組for i in range(p):xy.append(['-' for i in range(p)])for i in range(p):value = get_dot(i, a, b, p)if value is not False:x0, y0, x1, y1 = valuexy[x0][y0] = 1xy[x1][y1] = 1print('橢圓曲線散點圖:')for i in range(p):temp = p - 1 - iif temp >= 10:print(temp, end='')else:print(temp, end='')# 輸出具體坐標值for j in range(p):print(xy[j][temp], end='')print()print(' ', end='')for i in range(p):if i >= 10:print(i, end='')else:print(i, end='')print()def get_nG(xG, yG, priv_key, a, p):"""計算nG"""temp_x = xGtemp_y = yGwhile priv_key != 1:temp_x, temp_y = get_PaddQ(temp_x, temp_y, xG, yG, a, p)priv_key -= 1return temp_x, temp_ydef get_KEY():"""生成公鑰私鑰"""# 選擇曲線方程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)# 選擇基點Gprint('在上圖坐標系中選擇基點G的坐標')xG = int(input('橫坐標xG:'))yG = int(input('縱坐標yG:'))# 獲取曲線的階n = get_order(xG, yG, a, b, p)# 生成私鑰key,且key<npriv_key = int(input('輸入私鑰key(<%d):' % n))# 生成公鑰KEYxK, yK = get_nG(xG, yG, priv_key, a, p)return xK, yK, priv_key, a, b, p, n, xG, yGdef encrypt(xG, yG, xK, yK, priv_key, a, p, n):"""加密"""k = int(input('輸入一個整數k(<%d)用于計算kG和kQ:' % n))kGx, kGy = get_nG(xG, yG, priv_key, a, p) # kGkQx, kQy = get_nG(xK, yK, priv_key, a, p) # kQplain = input('輸入需要加密的字符串:')plain = plain.strip()c = []print('密文為:', end='')for char in plain:intchar = ord(char)cipher = intchar * kQxc.append([kGx, kGy, cipher])print('(%d,%d),%d' % (kGx, kGy, cipher), end=' ')print()return cdef decrypt(c, priv_key, a, p):"""解密"""for charArr in c:kQx, kQy = get_nG(charArr[0], charArr[1], priv_key, a, p)print(chr(charArr[2] // kQx), end='')print()if __name__ == '__main__':xK, yK, priv_key, a, b, p, n, xG, yG = get_KEY()c = encrypt(xG, yG, xK, yK, priv_key, a, p, n)decrypt(c, priv_key, a, p)總結
以上是生活随笔為你收集整理的画验证曲线_椭圆曲线加密算法(ECC)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 往境外汇款的限制
- 下一篇: 12 天直降 891 元:苹果 Mac