椭圆曲线算法应用之私钥生成公钥

原理

有限域GF(p)上的椭圆曲线y² = x³ + ax + b,若P(Xp, Yp), Q(Xq, Yq),且P≠-Q,则R(Xr,Yr) = P+Q          由如下规则确定:

 Xr = (λ² - Xp - Xq) mod p

  Yr = (λ(Xp - Xr) - Yp) mod p

  其中λ = (Yq - Yp)/(Xq - Xp) mod p(若P≠Q), λ = (3Xp² + a)/2Yp mod p(若P=Q)

 因此,有限域GF(23)上的椭圆曲线y² ≡ x³ + x + 1 (mod 23),假设以(0,1)为G点,计算2G、3G、4G...xG等等,方法如下:

 计算2G:

  λ = (3x0² + 1)/2x1 mod 23 = (1/2) mod 23

= 12

  Xr = (12² - 0 - 0) mod 23 = 6

  Yr = (12(0 - 6) - 1) mod 23 = 19

  即2G为点(6,19)


Python 实现

# 获取私钥

```

def random_key():

    # Gotta be secure after that java.SecureRandom fiasco...

    #random.randrange(1, curve.n)

    entropy = os.urandom(32) \

        + str(random.randrange(2**256)) \

        + str(int(time.time() * 1000000))

    return sha256(entropy)

```



def privkey_to_pubkey(privkey):

    f = get_privkey_format(privkey)

    privkey = decode_privkey(privkey, f)

    if privkey == 0 or privkey >= N:

        raise Exception("Invalid privkey")

    if f in ['bin', 'bin_compressed', 'hex', 'hex_compressed', 'decimal']:

        return encode_pubkey(fast_multiply(G, privkey), f)

     else:

        return encode_pubkey(fast_multiply(G, privkey), f.replace('wif', 'hex'))



#获取私钥的数据格式

def get_privkey_format(priv):

    if isinstance(priv, (int, long)): return 'decimal'

    elif len(priv) == 32: return 'bin'

    elif len(priv) == 33: return 'bin_compressed'

    elif len(priv) == 64: return 'hex'

    elif len(priv) == 66: return 'hex_compressed'

    else:

        bin_p = b58check_to_bin(priv)

        if len(bin_p) == 32: return 'wif'

        elif len(bin_p) == 33: return 'wif_compressed'

        else: raise Exception("WIF does not represent privkey")



def decode(string, base):

    base = int(base)

    code_string = get_code_string(base)

    result = 0

    if base == 16:

        string = string.lower()

    while len(string) > 0:

        result *= base

        result += code_string.find(string[0])

        string = string[1:]

    return result



def decode_privkey(priv,formt=None):

    if not formt: formt = get_privkey_format(priv)

    if formt == 'decimal': return priv

    elif formt == 'bin': return decode(priv, 256)

    elif formt == 'bin_compressed': return decode(priv[:32], 256)

    elif formt == 'hex': return decode(priv, 16)

    elif formt == 'hex_compressed': return decode(priv[:64], 16)

    else:

        bin_p = b58check_to_bin(priv)

        if len(bin_p) == 32: return decode(bin_p, 256)

        elif len(bin_p) == 33: return decode(bin_p[:32], 256)

        else: raise Exception("WIF does not represent privkey")



def jordan_add(a, b):

    if jordan_isinf(a):

        return b

    if jordan_isinf(b):

        return a

    if (a[0][0] * b[0][1] - b[0][0] * a[0][1]) % P == 0:

        if (a[1][0] * b[1][1] - b[1][0] * a[1][1]) % P == 0:

            return jordan_double(a)

        else:

            return ((0, 1), (0, 1))

    xdiff = subcoords(b[0], a[0])

    ydiff = subcoords(b[1], a[1])

    m = mulcoords(ydiff, invcoords(xdiff))

    x = subcoords(subcoords(mulcoords(m, m), a[0]), b[0])

    y = subcoords(mulcoords(m, subcoords(a[0], x)), a[1])

    return (x, y)


def jordan_double(a):

    if jordan_isinf(a):

        return ((0, 1), (0, 1))

    num = addcoords(mul_by_const(mulcoords(a[0], a[0]), 3), (A, 1))

    den = mul_by_const(a[1], 2)

    m = mulcoords(num, invcoords(den))

    x = subcoords(mulcoords(m, m), mul_by_const(a[0], 2))

    y = subcoords(mulcoords(m, subcoords(a[0], x)), a[1])

    return (x, y)


# G, privkey

#13,6,3,1

def jordan_multiply(a, n):

    if jordan_isinf(a) or n == 0:

        return ((0, 0), (0, 0))

    if n == 1:

        return a

    if n < 0 or n >= N:

        return jordan_multiply(a, n % N)

    if (n % 2) == 0:

        return  jordan_double(jordan_multiply(a, n/2))

    if (n % 2) == 1:

        return jordan_add(jordan_double(jordan_multiply(a, n/2)), a)


def to_jordan(p):

    return ((p[0], 1), (p[1], 1))


def from_jordan(p):

    return (p[0][0] * inv(p[0][1], P) % P, p[1][0] * inv(p[1][1], P) % P)


#G, privkey

def fast_multiply(a, n):

    return from_jordan(jordan_multiply(to_jordan(a), n))

def fast_add(a, b):

    return from_jordan(jordan_add(to_jordan(a), to_jordan(b)))


# Elliptic curve Jordan form functions

# P = (m, n, p, q) where m/n = x, p/q = y

def isinf(p):

    return p[0] == 0 and p[1] == 0

def jordan_isinf(p):

    return p[0][0] == 0 and p[1][0] == 0

def mulcoords(c1, c2):

    return (c1[0] * c2[0] % P, c1[1] * c2[1] % P)

def mul_by_const(c, v):

    return (c[0] * v % P, c[1])

def addcoords(c1, c2):

    return ((c1[0] * c2[1] + c2[0] * c1[1]) % P, c1[1] * c2[1] % P)

def subcoords(c1, c2):

    return ((c1[0] * c2[1] - c2[0] * c1[1]) % P, c1[1] * c2[1] % P)

def invcoords(c):

    return (c[1], c[0])



# Extended Euclidean Algorithm

#p[0][1],p[1][1],p

#a%n = a- a/n * n

#x1=y2; y1=x2-(a/b)*y2;

def inv(a, n):

    lm, hm = 1, 0

    low, high = a % n, n

    while low > 1:

        r = high/low

        nm, new = hm-lm*r, high-low*r

        lm, low, hm, high = nm, new, lm, low

    return lm % n

你可能感兴趣的:(椭圆曲线算法应用之私钥生成公钥)