Bitcoin Forum
February 07, 2023, 06:31:33 PM
 News: Latest Bitcoin Core release: 24.0.1 [Torrent]
 Home Help Search Login Register More
 Pages: [1]
 Author Topic: [SOLVED] python secp256k1  (Read 10586 times)
Lis (OP)
Sr. Member

Offline

Activity: 293
Merit: 251

Spice must flow!

 June 27, 2011, 03:42:02 PMLast edit: July 14, 2011, 07:08:35 AM by Lis

Code:
#! /usr/bin/env python

import random

class CurveFp( object ):
def __init__( self, p, a, b ):
self.__p = p
self.__a = a
self.__b = b

def p( self ):
return self.__p

def a( self ):
return self.__a

def b( self ):
return self.__b

def contains_point( self, x, y ):
return ( y * y - ( x * x * x + self.__a * x + self.__b ) ) % self.__p == 0

class Point( object ):
def __init__( self, curve, x, y, order = None ):
self.__curve = curve
self.__x = x
self.__y = y
self.__order = order
if self.__curve: assert self.__curve.contains_point( x, y )
if order: assert self * order == INFINITY

if other == INFINITY: return self
if self == INFINITY: return other
assert self.__curve == other.__curve
if self.__x == other.__x:
if ( self.__y + other.__y ) % self.__curve.p() == 0:
return INFINITY
else:
return self.double()

p = self.__curve.p()
l = ( ( other.__y - self.__y ) * \
inverse_mod( other.__x - self.__x, p ) ) % p
x3 = ( l * l - self.__x - other.__x ) % p
y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
return Point( self.__curve, x3, y3 )

def __mul__( self, other ):
def leftmost_bit( x ):
assert x > 0
result = 1L
while result <= x: result = 2 * result
return result / 2

e = other
if self.__order: e = e % self.__order
if e == 0: return INFINITY
if self == INFINITY: return INFINITY
assert e > 0
e3 = 3 * e
negative_self = Point( self.__curve, self.__x, -self.__y, self.__order )
i = leftmost_bit( e3 ) / 2
result = self
while i > 1:
result = result.double()
if ( e3 & i ) != 0 and ( e & i ) == 0: result = result + self
if ( e3 & i ) == 0 and ( e & i ) != 0: result = result + negative_self
i = i / 2
return result

def __rmul__( self, other ):
return self * other

def __str__( self ):
if self == INFINITY: return "infinity"
return "(%d,%d)" % ( self.__x, self.__y )

def double( self ):
if self == INFINITY:
return INFINITY

p = self.__curve.p()
a = self.__curve.a()
l = ( ( 3 * self.__x * self.__x + a ) * \
inverse_mod( 2 * self.__y, p ) ) % p
x3 = ( l * l - 2 * self.__x ) % p
y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
return Point( self.__curve, x3, y3 )

def x( self ):
return self.__x

def y( self ):
return self.__y

def curve( self ):
return self.__curve

def order( self ):
return self.__order

INFINITY = Point( None, None, None )

def inverse_mod( a, m ):
if a < 0 or m <= a: a = a % m
c, d = a, m
uc, vc, ud, vd = 1, 0, 0, 1
while c != 0:
q, c, d = divmod( d, c ) + ( c, )
uc, vc, ud, vd = ud - q*uc, vd - q*vc, uc, vc
assert d == 1
if ud > 0: return ud
else: return ud + m

# secp256k1
_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
_b = 0x0000000000000000000000000000000000000000000000000000000000000007L
_a = 0x0000000000000000000000000000000000000000000000000000000000000000L
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L

class Signature( object ):
def __init__( self, r, s ):
self.r = r
self.s = s

class Public_key( object ):
def __init__( self, generator, point ):
self.curve = generator.curve()
self.generator = generator
self.point = point
n = generator.order()
if not n:
raise RuntimeError, "Generator point must have order."
if not n * point == INFINITY:
raise RuntimeError, "Generator point order is bad."
if point.x() < 0 or n <= point.x() or point.y() < 0 or n <= point.y():
raise RuntimeError, "Generator point has x or y out of range."

def verifies( self, hash, signature ):
G = self.generator
n = G.order()
r = signature.r
s = signature.s
if r < 1 or r > n-1: return False
if s < 1 or s > n-1: return False
c = inverse_mod( s, n )
u1 = ( hash * c ) % n
u2 = ( r * c ) % n
xy = u1 * G + u2 * self.point
v = xy.x() % n
return v == r

class Private_key( object ):
def __init__( self, public_key, secret_multiplier ):
self.public_key = public_key
self.secret_multiplier = secret_multiplier

def der( self ):
hex_der_key = '06052b8104000a30740201010420' + \
'%064x' % self.secret_multiplier + \
'a00706052b8104000aa14403420004' + \
'%064x' % self.public_key.point.x() + \
'%064x' % self.public_key.point.y()
return hex_der_key.decode('hex')

def sign( self, hash, random_k ):
G = self.public_key.generator
n = G.order()
k = random_k % n
p1 = k * G
r = p1.x()
if r == 0: raise RuntimeError, "amazingly unlucky random number r"
s = ( inverse_mod( k, n ) * \
( hash + ( self.secret_multiplier * r ) % n ) ) % n
if s == 0: raise RuntimeError, "amazingly unlucky random number s"
return Signature( r, s )

curve_256 = CurveFp( _p, _a, _b )
generator_256 = Point( curve_256, _Gx, _Gy, _r )
g = generator_256

if __name__ == "__main__":
print '======================================================================='
### generate privkey
randrange = random.SystemRandom().randrange
n = g.order()
secret = randrange( 1, n )
### set privkey
### print privkey
print 'secret', hex(secret)

### generate pubkey
pubkey = Public_key( g, g * secret )
### set pubkey
#pubkey = Public_key(g, Point( curve_256, 0x40f9f833a25c725402e242965410b5bb992dc4fea1328681f0a74571c3104e36L,
#                                         0x0882ea6ae14b6b1316e71e76cc51867cba20cafabd349753058b8c4677be50caL))
### print pubkey
print 'pubkey', hex(pubkey.point.x()), hex(pubkey.point.y())

privkey = Private_key( pubkey, secret )

# set hash
#hash = randrange( 1, n )
hash = 0x0000000000000000000000000000000000000000000000000000000000000000L

### make signature on hash
signature = privkey.sign( hash, randrange( 1, n ) )
### set signature
#signature = Signature(0x0000000000000000000000000000000000000000000000000000000000000000L,
#                      0x0000000000000000000000000000000000000000000000000000000000000000L)

### print signature
print 'signature', hex(signature.r), hex(signature.s)

#print '======================================================================='
print 'verifies', pubkey.verifies( hash, signature )
print '======================================================================='

Умеет, генерировать privkey, делать из него pubkey, подписывать хеш проверять подпись.
Вопрос знатокам, у меня сигнатура получается 64 bytes 2x32b. Даже если добавить 0x30 спереди выходит 65b.
В то время как http://blockexplorer.com/rawtx/a2844948747244e5582b385e86de85b386443353cfe6803091ac50257baf7ee7
Code:
71 bytes
ЧЯДНТ

зы. спасибо Sipa, за то что терпел мое каверканье международного, мне стыдно
ззы. код народное достояние.

You would like to thank?
btc: 14tAPpwzrfZqBeFVvfBZHiBdByYhsoFofn
1675794693
Hero Member

Offline

Posts: 1675794693

Ignore
 1675794693

1675794693
 Report to moderator
1675794693
Hero Member

Offline

Posts: 1675794693

Ignore
 1675794693

1675794693
 Report to moderator
Whoever mines the block which ends up containing your transaction will get its fee.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1675794693
Hero Member

Offline

Posts: 1675794693

Ignore
 1675794693

1675794693
 Report to moderator
1675794693
Hero Member

Offline

Posts: 1675794693

Ignore
 1675794693

1675794693
 Report to moderator
1675794693
Hero Member

Offline

Posts: 1675794693

Ignore
 1675794693

1675794693
 Report to moderator
LZ
Legendary

Offline

Activity: 1722
Merit: 1069

P2P Cryptocurrency

 June 28, 2011, 07:11:58 AMLast edit: June 28, 2011, 12:09:58 PM by lzsaver

Разберем вышеприведенный пример сигнатуры.

30 - какая-то DER метка

44 - длина, вроде hex(len(hex(signature.r))/2+len(hex(signature.s))/2+2)

02 - разделитель, далее используем r

20 - длина, вроде hex(len(hex(signature.r))/2)

02 - разделитель, далее используем s

20 - длина, вроде hex(len(hex(signature.s))/2)

3bf9d2d0b52cd1734ccaf7bebc831c128737fb1309f83b79cab500dc274b5322 - это hex(signature.s)

01 - конец сигнатуры

My OpenPGP fingerprint: 5099EB8C0F2E68C63B4ECBB9A9D0993E04143362
Lis (OP)
Sr. Member

Offline

Activity: 293
Merit: 251

Spice must flow!

 June 28, 2011, 09:51:23 AMLast edit: July 13, 2011, 09:44:27 AM by Lis

Спасибо большое

в догонку еще код на общественное пользование.
Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import hashlib

b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def hex_open_key_to_hex_hesh160(hex_open_key):
h160 = hashlib.new('ripemd160')
h160.update(hashlib.sha256(('04'+hex_open_key).decode('hex')).hexdigest().decode('hex'))
return h160.hexdigest()

return '00'+hex_hesh160+hashlib.sha256(hashlib.sha256(('00'+hex_hesh160).decode('hex')).hexdigest().decode('hex')).hexdigest()[0:8]

def hex_to_base58(hex_data):
base58 = ''
int_data = int(hex_data, 16)
while int_data >= len(b58chars):
base58 = b58chars[int_data%len(b58chars)] + base58
int_data = int_data/len(b58chars)
base58 = b58chars[int_data%len(b58chars)] + base58
for i in xrange(len(hex_data)/2):
if hex_data[i*2:i*2+2] == '00':
base58 = '1' + base58
else:
break
return base58

def base58_to_hex(base58):
hex_data = ''
int_data = 0
for i in xrange(-1, -len(base58)-1, -1):
int_data += (b58chars.index(base58[i]))*58**(-i-1)
hex_data = hex(int_data)[2:-1]
for i in xrange(len(base58)):
if base58[i] == '1':
hex_data = '00' + hex_data
else:
break
return hex_data

hex_open_key = '40f9f833a25c725402e242965410b5bb992dc4fea1328681f0a74571c3104e360882ea6ae14b6b1316e71e76cc51867cba20cafabd349753058b8c4677be50ca'

Код сырой будет, дописываться.

You would like to thank?
btc: 14tAPpwzrfZqBeFVvfBZHiBdByYhsoFofn
Lis (OP)
Sr. Member

Offline

Activity: 293
Merit: 251

Spice must flow!

 July 09, 2011, 03:59:06 PM

excellent work )

Is it possible to write out privkey to file in PEM format directly ==
without pyopenssl and/or M2Crypto ?

Like this one example :

-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEILcyvoUzP5fLtJAaEQnVvqOy+TW1P5/ui4olcu8Vi9lhoAcGBSuBBAAK
oUQDQgAELa18gopT7X7Ii+Y3FEfAgssdCLjghXvXV926pyPiXSkqhbGkOfWi7s3+
xjBcZnMwKx18Pp4N6BI+7CaX6J7qDw==
-----END EC PRIVATE KEY-----

Or maybe in DER form ?

I appreciate you help )
Да возможно
постараюсь в понедельник

You would like to thank?
btc: 14tAPpwzrfZqBeFVvfBZHiBdByYhsoFofn
Lis (OP)
Sr. Member

Offline

Activity: 293
Merit: 251

Spice must flow!

 July 12, 2011, 07:35:59 AMLast edit: July 12, 2011, 10:40:16 AM by Lis

Добавил der. Код в первом посте.
Вызывается так:
Code:
if __name__ == "__main__":