我不确定这个问题是否与stackoverflow或加密堆栈交换相关,但我认为我会在这里问它,因为问题可能会进入编程。
我正在尝试使用椭圆曲线diffie-hellman生成公钥和私钥对,我成功生成了一个小于曲线顺序的私钥,但是当我通过将基点乘以私有来计算公钥时key我计算一个不在曲线上的点。
我用来生成密钥的代码如下所示:
Public Shared Function generate_Keys(ByVal Param As Domain_Parameters) As Keys
Dim __PrivateKey As BigInteger
Dim __PublicKey As ECPoint
Dim d As BigInteger
Dim rng As New RNGCryptoServiceProvider
Dim bytes(Param.n.ToByteArray.Length) As Byte
Do
rng.GetBytes(bytes)
d = New BigInteger(bytes)
If d.Sign = -1 Then
d = d * -1
End If
Loop While d >= Param.n
__PrivateKey = d
__PublicKey = Point_Operations.Scalar_Mult(Param.Base, Param, d)
Dim Ret As Keys
Ret.PublicKey = __PublicKey
Ret.PrivateKey = __PrivateKey
__PrivateKey = BigInteger.Zero()
d = BigInteger.Zero()
bytes = {0}
Return Ret
End Function
我测试过的代码并且可以很好地将基点乘以私钥,如下所示:
Public Class Point_Operations
''' <summary>
''' A structure that contains data returned from Extended_GCD function
''' </summary>
Friend Structure RetGCD
Public x As BigInteger
Public y As BigInteger
Public GCD As BigInteger
End Structure
''' <summary>
''' Perfomrs addition of two points
''' </summary>
Public Shared Function Addition(ByVal P1 As ECPoint, ByVal P2 As ECPoint) As ECPoint
'Details about the maths was found on https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication
'Tested with the site http://christelbach.com/ECCalculator.aspx
If P1.IsPointInfinity() Then
Return P2
End If
If P2.IsPointInfinity() Then
Return P1
End If
If P1.p <> P2.p Then
Return New ECPoint(-99, -99, -99) 'Add custom errors with ENUM
End If
If P1.x = P2.x And P1.y = P2.y Then
Return New ECPoint(-99, -99, -99)
End If
Dim P3 As New ECPoint(P1)
Dim l, z As BigInteger
z = Inverse((P2.x - P1.x), P1.p)
l = ((P2.y - P1.y) * z) Mod P1.p
P3.x = ((l * l) Mod P1.p - P2.x - P1.x) Mod P1.p
P3.y = (l * (P1.x - P3.x) Mod P1.p - P1.y) Mod P1.p
If P3.x < 0 Then 'Tested the code without the peice below and found that the input (10,10,47) and (20,20,47) returned wrong values found out that the difference between each was the prime number so if its less than zero we add the prime whcih seems to work
P3.x += P1.p
End If
If P3.y < 0 Then
P3.y += P1.p
End If
Return P3
End Function
''' <summary>
''' A way of doubling a EC Point
''' </summary>
Public Shared Function PDouble(ByVal P As ECPoint, ByVal a As Domain_Parameters) As ECPoint
'Details about the maths was found on https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication
'Tested with the site http://christelbach.com/ECCalculator.aspx
If P.p = 0 And a.Fp.p = 0 Then
Return New ECPoint(-99, -99, -99)
End If
'If a.a = 0 Then
' Return New ECPoint(-99, -99, -99)
'End If
If P.IsPointInfinity() Then
Return P
End If
Dim prime As BigInteger
If P.p = 0 Then
prime = a.Fp.p
Else
prime = P.p
End If
Dim Q As New ECPoint(P)
Dim l, z As BigInteger
z = Inverse(2 * P.y, P.p)
l = ((((3 * P.x * P.x) Mod P.p + a.a) Mod P.p) * z) Mod P.p
Q.x = ((l * l) Mod P.p - 2 * P.x) Mod P.p 'accidental set (2 * p.x) to (2 * P.p)
Q.y = (l * (P.x - Q.x) Mod P.p - P.y) Mod P.p
If Q.x < 0 Then 'This code was tested and the same problem again with negative values for x and y so we must add the prime to p to correct that
Q.x += P.p
End If
If Q.y < 0 Then
Q.y += P.p
End If
Return Q
End Function
''' <summary>
''' Performs point multiplication with a scalar
''' </summary>
Public Shared Function Scalar_Mult(ByVal P As ECPoint, ByVal a As Domain_Parameters, ByVal Scalar As BigInteger) As ECPoint
'Details about the maths was found on https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication
'Tested with the site http://christelbach.com/ECCalculator.aspx
If P.p = 0 And a.Fp.p = 0 Then
Return New ECPoint(-99, -99, -99)
End If
'If a.a = 0 Then
' Return New ECPoint(-99, -99, -99)
'End If
If P.IsPointInfinity Then
Return P
End If
Dim prime As BigInteger
If P.p = 0 Then
prime = a.Fp.p
Else
prime = P.p
End If
'Dim k As New BigInteger(Scalar.ToByteArray)
Dim N, S As New ECPoint(P)
S = New ECPoint(0, 0, prime) 'Accidentally set S.y = 1 was causing a bad value
'Dim sc As New BigInteger(k.ToByteArray) 'Depreciated as now we can use bits.lenght
'Dim bitlenght As Integer
'While sc / 2 <> 0
' bitlenght += 1
' sc /= 2
'End While
Dim bits As New BitArray(Scalar.ToByteArray)
For i = 0 To bits.Length - 1
If bits(i) = True Then 'Fixed error where BitArray uses True/False instead of 1/0
S = Addition(S, N)
End If
N = PDouble(N, a)
Next
Return S
End Function
''' <summary>
''' Calcualtes the Greatest Common Divisor of two numbers
''' </summary>
Private Shared Function Extended_GCD(ByVal a As BigInteger, b As BigInteger) As RetGCD
'The pseudocode was found on https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Pseudocode
'Tested with the site http://planetcalc.com/3298/
Dim r, o_r As BigInteger
Dim t, o_t As BigInteger
Dim s, o_s As BigInteger
Dim p, q As BigInteger
Dim ret As RetGCD
s = 0
t = 1
r = b
o_s = 1
o_t = 0
o_r = a
While r <> 0
q = o_r / r
p = r
r = o_r - q * p
o_r = p
p = s
s = o_s - q * p
o_s = p
p = t
t = o_t - q * p
o_t = p
End While
ret.x = o_s
ret.y = o_t
ret.GCD = o_r
Return ret
End Function
''' <summary>
''' Performs the modular multiplitcative inverse of a number so we can use multiplication instead of division in our arithmetic
''' </summary>
Public Shared Function Inverse(ByVal a As BigInteger, ByVal p As BigInteger) As BigInteger
'Not tested but works
Dim ret As RetGCD
ret = Extended_GCD(a, p)
If ret.GCD <> 1 Then
Return 0
End If
Return ret.x Mod p
End Function
我觉得这可能是我生成私钥的方式,或者我在计算G.d时使用了错误的操作。 非常感谢任何帮助。
=== EDIT ===
花了一些时间检查值后,我发现问题是由scalar_mult函数没有返回正确的值引起的。这个函数是否正确编写,因为我不确定我是否使用来自网站的值对其进行了测试,并且它已经从维基百科上的伪代码进行了改编。这是将点添加到自身x个时间的正确方法吗?