ECDH生成公钥导致该点不在曲线VB.net上

时间:2017-08-15 17:47:43

标签: vb.net elliptic-curve diffie-hellman

我不确定这个问题是否与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个时间的正确方法吗?

0 个答案:

没有答案