我正在尝试在haskell中编写带有椭圆曲线的elgamal实现。 但是我的点加法函数存在一些问题:只要我不断地将起点添加到自身,我就永远无法达到无穷远点(O)。 这是我的代码:
addP :: Curve->Point->Point->Point
addP _ O O = O
addP _ O p = p
addP _ p O = p
addP curve@(a,b,p) (P x1 y1) (P x2 y2) | x1 == x2 && y1 == -y2 = O
| otherwise = P x3 ((m*(x1-x3)-y1) `mod''` p)
where x3 = (((m*m)-x1-x2) `mod''` p)
m | x1 /= x2 = (y2-y1)/(x2-x1)
| otherwise = (3*(x1*x1)+a)/(2*y1)
曲线定义为
-- first double=a, second double=b, third double=p in y^2=x^3+ax+b mod p
type Curve = (Double, Double, Double)
和Point定义为
data Point = P Double Double |
P
deriving (Eq, Read, Show)
有谁知道我做错了什么?
答案 0 :(得分:3)
只要我不断向自身添加起点,我就永远无法到达无限远点(O)。
您能否发布您从中学到的参考/链接。我对Elliptic曲线的知识非常有限,但我对Haskell知之甚少,所以我试着看看你的代码是怎么回事。当你使用模运算模数p时,我首先注意到使用除法和双精度。我无法看到你修改了什么,所以我改变了你的代码,它对我来说很好。
type Curve = ( Integer , Integer , Integer )
data Point = P Integer Integer | O
deriving (Eq, Read, Show)
extendedGcd :: Integer -> Integer -> ( Integer , Integer )
extendedGcd a b
| b == 0 = ( 1 , 0 )
| otherwise = ( t , s - q * t ) where
( q , r ) = quotRem a b
( s , t ) = extendedGcd b r
modInv :: Integer -> Integer -> Integer
modInv a b
| gcd a b /= 1 = error " gcd is not 1 "
| otherwise = d where
d = until ( > 0 ) ( + b ) . fst.extendedGcd a $ b
addP :: Curve->Point->Point->Point
addP _ O O = O
addP _ O p = p
addP _ p O = p
addP ( a, b, p ) ( P x1 y1 ) ( P x2 y2 )
| x1 == x2 && mod ( y1 + y2 ) p == 0 = O
| otherwise = P x3 ( mod ( m * ( x1 - x3 ) - y1 ) p ) where
m | x1 /= x2 = ( mod ( y2 - y1 ) p ) * modInv ( mod ( x2 - x1 ) p ) p
| otherwise = ( 3 * x1 * x1 + a ) * modInv ( 2*y1 ) p
x3 = mod ( m * m - x1 - x2 ) p
让我们取曲线y ^ 2 = x ^ 3 + x + 1 modulo 13. Z_13 = [0,1,2,3,4,5,6,7,8,9,10,11,12]。二次残基(QR)= [0,1,3,4,9,10,12]和Z_13的二次非残留(QNR)= [2,5,6,7,8,11]。取x = 0并且我们有y ^ 2 = 1(mod 13),因为1在QR中,因此该等式的解是1和12.我们得到两个点(0,1)和(0,12)。假设x = 1,y ^ 2 = 3(mod 13),因此对应于x = 1的点是(1,4)和(1,9)。假设x = 2,y ^ 2 = 11(mod 13)和11是QNR,所以我们没有解决方案。每当一个解存在时,它给出了两个点,并且两个都是模数素数p的倒数(在这种情况下为13)。给定曲线上的总点数为(0,1),(0,12),(1,4),(1,9),(4,2),(4,11),(5,1),(5) ,12),(7,0),(7,0),(8,1),(8,12),(10,6),(10,7),(11,2),(11,11) )。您可以尝试所有点,并查看哪一个点生成整个组。
*Main>take 20 . iterate ( addP ( 1 , 1 , 13 ) ( P 7 0 ) ) $ ( P 7 0 )
[P 7 0,O,P 7 0,O,P 7 0,O,P 7 0,O,P 7 0,O,P 7 0,O,P 7 0,O,P 7 0,O,P 7 0,O,P 7 0,O]
*Main> take 20 . iterate ( addP ( 1 , 1 , 13 ) ( P 0 12 ) ) $ ( P 0 12 )
[P 0 12,P 10 6,P 7 0,P 10 7,P 0 1,O,P 0 12,P 10 6,P 7 0,P 10 7,P 0 1,O,P 0 12,P 10 6,P 7 0,P 10 7,P 0 1,O,P 0 12,P 10 6]
回到Elgamal系统
鲍勃在GF(p)或GF(2 ^ n)上选择椭圆曲线E(a,b)
鲍勃在曲线e1(x1,y1)上选择了一个点
鲍勃选择了一个整数d。
鲍勃计算e2(x2,y2)= d * e1(x1,y1)
5. Bob宣布E(a,b,p),e1(x1,y1)和e2(x2,y2)作为你的公钥,并将d保持为私钥
加密。
Alice选择P,指向曲线,作为她的纯文本。她选择了随机数r并计算C1 = r * e1,C2 = P + r * e2。
解密。
Bob收到C1和C2后,计算C2-d * C1 => P + r * e2 - d * r * e1
=> P + r * d * e1-d * r * e1 => P
编辑:你是对的!如果您使用生成元素并继续添加它,那么您可以生成整个组。参见Christof Paar [1]的讲座 [1] https://www.youtube.com/watch?v=3S9eZRHjP8g&list=PLn_QCKxjl9zmx3VojkDqljZcLCIslz7kB&index=37