上一节我们了解了有限域的定义,并使用代码进行实现。作为区块链技术的底层技术支柱之一,它跟有限域有着非常紧密的联系,正式因为如此,椭圆曲线才能用来给区块链创建公钥,由此形成区块链钱包的地址。
对椭圆曲线而言,我们并不关心它本身,但是我们关系椭圆曲线上的点,以及这些点在特定操作下所形成的性质。因此我们代码的逻辑在实现椭圆曲线上的点,首先我们实现代码如下:
```python
class EllipticPoint:
def __init__(self, x, y, a, b):
"""
a, b为椭圆曲线方程 y^2 = x ^ 3 + ax + b
对于区块链的椭圆曲线a取值为0,b取值为7,其专有名称为secp256k1
由此在初始化椭圆曲线点时,必须确保(x,y)位于给定曲线上
"""
if y**2 != x**3 + a*x + b:
raise ValueError(f'({x}, {y}) is not on the curve')
self.x = x
self.y = y
self.a = a
self.b = b
def __eq__(self, other):
"""
两个点要相等,我们不能只判断x,y是否一样,必须判断他们是否位于同一条椭圆曲线
"""
return self.x == other.x and self.y == other.y and self.a == other.a and self.b == other.b
def __ne__(self, other):
return self.x != other.x or self.y != other.y or self.a != other.a or self.b != other.b
いくつかのインスタンスを作成して、上記のコードを確認してみましょう。
'''
设置曲线y^2 = x ^ 3 + 5x + 7, (a=5, b=7)
'''
b = EllipticPoint(-1, -1, 5, 7)
c = EllipticPoint(18, 77, 5, 7)
print(b == c)
print(b != c)
#下面的点不在曲线上因此会出现异常
d = EllipticPoint(5, 7, 5, 7)
上記のコードでは、3 つの楕円曲線ポイントを作成しました。最初の 2 つのポイントは曲線上にあり、3 番目のポイントは曲線上にないため、ポイント d がインスタンス化されると例外が生成され、実行結果は次のようになります。 :
False
True
Traceback (most recent call last):
File "/Users/my/PycharmProjects/pythonProject3/blockchain_curve.py", line 104, in <module>
d = EllipticPoint(5, 7, 5, 7)
File "/Users/my/PycharmProjects/pythonProject3/blockchain_curve.py", line 78, in __init__
raise ValueError(f'({
x}, {
y}) is not on the curve')
ValueError: (5, 7) is not on the curve
前節で楕円曲線上の点の足し算について述べました. 楕円曲線上の2点を選択し, それらを接続します. このとき, 3つの状況があります. 2点接続が延長されてから曲線下の図に示すように、3 番目の点で交差します。
2 番目のケースは次のとおりです。2 点が同じ直線上にあるため、2 点を結ぶ線と曲線には 3 番目の交点がなくなります。前のセクションで、有限体に
はポイント "0" は、内部の任意のポイント a に対するセット Do "+" 操作に関連していますが、結果はポイント a のままです。上記の状況は点「0」に対応します. 上記の直線と曲線の間には3番目の交点はありませんが、この直線と曲線の追加を「無限大」で「定義」し、その交点を「定義」できます.は「0」なので、この場合、直線と曲線の2つの交点は「反対数」です.上の交点をaとすると、下の交点は-aに対応します.曲線上の2点を結ぶ線がy軸に平行 のとき、この2点の「+」演算結果を「0」として記録します。
楕円曲線上の 2 点が一致する 3 番目のケースもあります。つまり、それらは実際には同じ点であり、2 点を結ぶ線が接線を形成します。楕円曲線上の任意の 2 点を選択すると
、 execute "+" 操作の後、楕円曲線暗号化の基礎となる 3 番目の点は数学的に予測できません。次に、点の「+」操作を実装します。まず、2 番目の場合を目指します。2 点が同じ直線上にある場合、3 番目の点が無限遠の曲線に「追加」されるためです。 x=None , y=None を使用して表すと同時に、そのような点が他の点 a と "+" 操作を行うようにします。結果は a です。コードの実装を見てみましょう。 :
class EllipticPoint:
def __init__(self, x, y, a, b):
self.x = x
self.y = y
self.a = a
self.b = b
"""
x == None, y == None对应点"0"
"""
if x is None or y is None:
return
"""
a, b为椭圆曲线方程 y^2 = x ^ 3 + ax + b
对于区块链的椭圆曲线a取值为0,b取值为7,其专有名称为secp256k1
由此在初始化椭圆曲线点时,必须确保(x,y)位于给定曲线上
"""
if y ** 2 != x ** 3 + a * x + b:
raise ValueError(f'({
x}, {
y}) is not on the curve')
def __eq__(self, other):
"""
两个点要相等,我们不能只判断x,y是否一样,必须判断他们是否位于同一条椭圆曲线
"""
return self.x == other.x and self.y == other.y and self.a == other.a and self.b == other.b
def __ne__(self, other):
return self.x != other.x or self.y != other.y or self.a != other.a or self.b != other.b
def __add__(self, other):
"""
实现"+"操作,首先确保两个点位于同一条曲线,也就是他们对应的a,b要相同
"""
if self.a != other.a or self.b != other.b:
raise TypeError(f"points {
self}, {
other} not on the same curve")
#如果其中有一个是"0"那么"+"的结果就等于另一个点
if self.x is None:
return other
if other.x is None:
return self
def __repr__(self):
return f"EllipticPoint(x:{
self.x},y:{
self.y},a:{
self.a}, b:{
self.b})"
上記のコードは、元の初期化関数の実装を変更します. x と y の 2 つのコンポーネントのいずれかが None の場合、それは "0" 点に対応し、"+" 操作に対応する __add__ 関数を実装します. 2 つ追加 ポイントの 1 つが「0」の場合、結果は別のポイントと等しくなります。上記の実装をテストして結果を確認しましょう。
zero + p1 is EllipticPoint(x:-1,y:-1,a:5, b:7)
zero + p2 is EllipticPoint(x:-1,y:1,a:5, b:7)
出力は私たちの期待に沿っています。以下では、3 つの "+" 状況の中で最も単純な状況を実装します。つまり、2 つの点が同じ直線上にある、つまり、点の x 成分は同じですが、y 成分は互いに反対であり、同時に、このような 2 つのポイントは "+" 操作の後、結果は "0" です。実装を見てみましょう。
def __add__(self, other):
"""
实现"+"操作,首先确保两个点位于同一条曲线,也就是他们对应的a,b要相同
"""
if self.a != other.a or self.b != other.b:
raise TypeError(f"points {
self}, {
other} not on the same curve")
#如果其中有一个是"0"那么"+"的结果就等于另一个点
if self.x is None:
return other
if other.x is None:
return self
"""
两点在同一直线上,也就是x相同,y互为相反数
"""
if self.x == other.x and self.y == -other.y:
return __class__(None, None, self.a, self.b)
上記のコードをテストしてみましょう。
p1 = EllipticPoint(-1, -1, 5, 7)
p2 = EllipticPoint(-1, 1, 5, 7)
# print(f"zero + p1 is {zero + p1}")
# print(f"zero + p2 is {zero + p2}")
print(f"p1 + p2 = {
p1 + p2}")
上記のコードを実行した結果:
p1 + p2 = EllipticPoint(x:None,y:None,a:5, b:7)
これは私たちの予想と一致しています. 以下では, より複雑な状況, つまり, 3 番目のタイプを実装します. 2 点で形成された直線は 3 番目の点で曲線と交差します. ここではいくつかの数学的導出が必要です. 与えられた 2 点 (x1,y1 ),( x2, y2), まず、高校の代数 k = (y2 - y1)/(x2 - x1) に従って、これらの 2 点を結ぶことによって形成される直線の傾き k を取得し、2 点は直線方程式 y = k * ( x - x1) + y1、直線が楕円曲線と交差する 3 番目の点は直線と曲線の両方にあるため、3 番目の点の座標は両方の方程式を満たさなければなりません。
y = k*(x - x1)+y1
y^2 = x^3 + a*x + b
最初の式の y を 2 番目の式に代入すると、次のようになります。
(k*(x - x1)+y1)^2 = x^3 + a*x + b
上記の式の右側の部分を左に移動し、同時に展開します。
x^3 - k^2 * x^2 +(a + 2*s^2*x1 - 2*k*y1)*x + b - k^2(x1)^2 + 2*k*(x1)*(y1) - (y1)^2 = 0 (1)
(x3, y3) を使用して 3 番目の点を表す場合、(x1, y1)、(x2, y2)、(x3, y3) は次の式を満たさなければなりません。
(x-x1)*(x-x2)*(x-x3) = 0
上記の式を展開すると、次のようになります。
x^3 - (x1+x2+x3)*x^2 + (x1*x2 + x1*x3 + x2*x3)*x - (x1*x2*x3) = 0 (2)
(1) と (2) で x ^ 3、x ^ 2、x ^ 1 に対応すると、定数項目は互いに対応します。
k^2 -> (x1+x2+x3) (3)
(a + 2 * s^2*x1 - 2*k*y1) -> (x1*x2 + x1*x3 + x2*x3)
b - k^2(x1)^2 + 2*k*(x1)*(y1) - (y1)^2 -> (x1*x2*x3)
ヴェーダの定理によると
、上記 (3) の -> は = に置き換えることができるため、x3 を解くことができます。
x3 = k^2 - x2 - x1 (4)
次に、直線方程式に x3 を代入して、y3 を解きます。
y3 = k * (x3 - x1) + y1 (5)
#记得要根据x轴做对称得到"+"对应结果
y = -y3 = k*(x1-x3) - y1 (6)
したがって、式 (4) および (6) に従って、3 番目の交点を直接見つけることができます。コードの実装は次のとおりです。
def __add__(self, other):
"""
实现"+"操作,首先确保两个点位于同一条曲线,也就是他们对应的a,b要相同
"""
if self.a != other.a or self.b != other.b:
raise TypeError(f"points {
self}, {
other} not on the same curve")
#如果其中有一个是"0"那么"+"的结果就等于另一个点
if self.x is None:
return other
if other.x is None:
return self
"""
两点在同一直线上,也就是x相同,y互为相反数
"""
if self.x == other.x and self.y == -other.y:
return __class__(None, None, self.a, self.b)
"""
计算两点连线后跟曲线相交的第3点,使用韦达定理
"""
x1 = self.x
y1 = self.y
x2 = other.x
y2 = other.y
k = (y2 - y1) / (x2 - x1)
x3 = k ** 2 - x1 - x2
y3 = k * (x1 - x3) - y1
if self != other:
return __class__(x3, y3, self.a, self.b)
上記の実装をテストしましょう。
#测试两点直线与曲线相交于第三点
p1 = EllipticPoint(2, 5, 5, 7)
p2 = EllipticPoint(-1, -1, 5, 7)
print(f"p1 + p2 = {
p1 + p2}")
上記のコードを実行した後の結果:
p1 + p2 = EllipticPoint(x:3.0,y:-7.0,a:5, b:7)
最後に、2 点を結ぶ線が曲線の接線になる状況を認識します。2 点が同じなので、以前のように直線の傾きを直接計算することはできません。k = (y2 - y1)/(x2 - x1)、この時点では x2 = x1 なので、分母は 0 なので、ここでは高度な数学を使用する必要があります の微積分 : 特定の点での曲線の接線の勾配は、曲線方程式によると、その点での曲線の微分に等しくなります。
y^2 = x ^ 3 + a*x + b
x
を両側で微分します。 (4)、(6) を使用して 3 番目の点の座標の計算を完了することができるため、前のコードは次のように変更されます。
def __add__(self, other):
"""
实现"+"操作,首先确保两个点位于同一条曲线,也就是他们对应的a,b要相同
"""
if self.a != other.a or self.b != other.b:
raise TypeError(f"points {
self}, {
other} not on the same curve")
# 如果其中有一个是"0"那么"+"的结果就等于另一个点
if self.x is None:
return other
if other.x is None:
return self
"""
两点在同一直线上,也就是x相同,y互为相反数
"""
if self.x == other.x and self.y == -other.y:
return __class__(None, None, self.a, self.b)
"""
计算两点连线后跟曲线相交的第3点,使用韦达定理
"""
x1 = self.x
y1 = self.y
x2 = other.x
y2 = other.y
if self == other:
# 如果两点相同,根据微分来获得切线的斜率
k = (3 * self.x ** 2 + self.a) / 2 * self.y
else:
k = (y2 - y1) / (x2 - x1)
x3 = k ** 2 - x1 - x2
y3 = k * (x1 - x3) - y1
return __class__(x3, y3, self.a, self.b)
上記のコードの効果をテストしましょう。
#测试两点相同所形成切线与曲线的交点
p1 = EllipticPoint(-1, -1, 5, 7)
print(f"p1 + p1 = {
p1 + p1}")
上記のコードを実行した後の結果は次のとおりです。
p1 + p1 = EllipticPoint(x:18.0,y:77.0,a:5, b:7)
最後に、別の特殊なケースとして、
対応する点の y 成分が 0 の場合があります。この場合、微分を使用して曲線の傾きを計算することはできないため、このケースの判断を次のように追加できます。 __追加__:
def __add__(self, other):
"""
特殊情况,两点相同而且y分量为0
"""
if self == other and self.y == 0:
return __class__(None, None, self.a, self.b )
#余下代码省略
....
以上が楕円曲線上の点「+」演算の実現です。ブロックチェーン アプリケーションでは、最初に曲線上の特定の点 G を選択し、次に前のセクションで説明した有限フィールド プロパティを満たす集合 {1 G, 2 G, ...} を生成する必要があります。ブロック チェーン ウォレット アドレスを作成するには、最初に秘密鍵とも呼ばれる大きな数 k を選択し、次に k * G を計算します。結果が公開鍵です。一連のハッシングの後にウォレット アドレスを取得し、公開鍵のエンコーディング、詳細については、ステーション b でコーディング ディズニーを検索してください。