#! /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
def __add__( self, other ):
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
_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
_b = 0x0000000000000000000000000000000000000000000000000000000000000007L
_a = 0x0000000000000000000000000000000000000000000000000000000000000000L
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
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
IyEgL3Vzci9iaW4vZW52IHB5dGhvbgoKaW1wb3J0IHJhbmRvbQoKY2xhc3MgQ3VydmVGcCggb2JqZWN0ICk6CiAgZGVmIF9faW5pdF9fKCBzZWxmLCBwLCBhLCBiICk6CiAgICBzZWxmLl9fcCA9IHAKICAgIHNlbGYuX19hID0gYQogICAgc2VsZi5fX2IgPSBiCgogIGRlZiBwKCBzZWxmICk6CiAgICByZXR1cm4gc2VsZi5fX3AKCiAgZGVmIGEoIHNlbGYgKToKICAgIHJldHVybiBzZWxmLl9fYQoKICBkZWYgYiggc2VsZiApOgogICAgcmV0dXJuIHNlbGYuX19iCgogIGRlZiBjb250YWluc19wb2ludCggc2VsZiwgeCwgeSApOgogICAgcmV0dXJuICggeSAqIHkgLSAoIHggKiB4ICogeCArIHNlbGYuX19hICogeCArIHNlbGYuX19iICkgKSAlIHNlbGYuX19wID09IDAKCmNsYXNzIFBvaW50KCBvYmplY3QgKToKICBkZWYgX19pbml0X18oIHNlbGYsIGN1cnZlLCB4LCB5LCBvcmRlciA9IE5vbmUgKToKICAgIHNlbGYuX19jdXJ2ZSA9IGN1cnZlCiAgICBzZWxmLl9feCA9IHgKICAgIHNlbGYuX195ID0geQogICAgc2VsZi5fX29yZGVyID0gb3JkZXIKICAgIGlmIHNlbGYuX19jdXJ2ZTogYXNzZXJ0IHNlbGYuX19jdXJ2ZS5jb250YWluc19wb2ludCggeCwgeSApCiAgICBpZiBvcmRlcjogYXNzZXJ0IHNlbGYgKiBvcmRlciA9PSBJTkZJTklUWQogCiAgZGVmIF9fYWRkX18oIHNlbGYsIG90aGVyICk6CiAgICBpZiBvdGhlciA9PSBJTkZJTklUWTogcmV0dXJuIHNlbGYKICAgIGlmIHNlbGYgPT0gSU5GSU5JVFk6IHJldHVybiBvdGhlcgogICAgYXNzZXJ0IHNlbGYuX19jdXJ2ZSA9PSBvdGhlci5fX2N1cnZlCiAgICBpZiBzZWxmLl9feCA9PSBvdGhlci5fX3g6CiAgICAgIGlmICggc2VsZi5fX3kgKyBvdGhlci5fX3kgKSAlIHNlbGYuX19jdXJ2ZS5wKCkgPT0gMDoKICAgICAgICByZXR1cm4gSU5GSU5JVFkKICAgICAgZWxzZToKICAgICAgICByZXR1cm4gc2VsZi5kb3VibGUoKQoKICAgIHAgPSBzZWxmLl9fY3VydmUucCgpCiAgICBsID0gKCAoIG90aGVyLl9feSAtIHNlbGYuX195ICkgKiBcCiAgICAgICAgICBpbnZlcnNlX21vZCggb3RoZXIuX194IC0gc2VsZi5fX3gsIHAgKSApICUgcAogICAgeDMgPSAoIGwgKiBsIC0gc2VsZi5fX3ggLSBvdGhlci5fX3ggKSAlIHAKICAgIHkzID0gKCBsICogKCBzZWxmLl9feCAtIHgzICkgLSBzZWxmLl9feSApICUgcAogICAgcmV0dXJuIFBvaW50KCBzZWxmLl9fY3VydmUsIHgzLCB5MyApCgogIGRlZiBfX211bF9fKCBzZWxmLCBvdGhlciApOgogICAgZGVmIGxlZnRtb3N0X2JpdCggeCApOgogICAgICBhc3NlcnQgeCA+IDAKICAgICAgcmVzdWx0ID0gMUwKICAgICAgd2hpbGUgcmVzdWx0IDw9IHg6IHJlc3VsdCA9IDIgKiByZXN1bHQKICAgICAgcmV0dXJuIHJlc3VsdCAvIDIKCiAgICBlID0gb3RoZXIKICAgIGlmIHNlbGYuX19vcmRlcjogZSA9IGUgJSBzZWxmLl9fb3JkZXIKICAgIGlmIGUgPT0gMDogcmV0dXJuIElORklOSVRZCiAgICBpZiBzZWxmID09IElORklOSVRZOiByZXR1cm4gSU5GSU5JVFkKICAgIGFzc2VydCBlID4gMAogICAgZTMgPSAzICogZQogICAgbmVnYXRpdmVfc2VsZiA9IFBvaW50KCBzZWxmLl9fY3VydmUsIHNlbGYuX194LCAtc2VsZi5fX3ksIHNlbGYuX19vcmRlciApCiAgICBpID0gbGVmdG1vc3RfYml0KCBlMyApIC8gMgogICAgcmVzdWx0ID0gc2VsZgogICAgd2hpbGUgaSA+IDE6CiAgICAgIHJlc3VsdCA9IHJlc3VsdC5kb3VibGUoKQogICAgICBpZiAoIGUzICYgaSApICE9IDAgYW5kICggZSAmIGkgKSA9PSAwOiByZXN1bHQgPSByZXN1bHQgKyBzZWxmCiAgICAgIGlmICggZTMgJiBpICkgPT0gMCBhbmQgKCBlICYgaSApICE9IDA6IHJlc3VsdCA9IHJlc3VsdCArIG5lZ2F0aXZlX3NlbGYKICAgICAgaSA9IGkgLyAyCiAgICByZXR1cm4gcmVzdWx0CgogIGRlZiBfX3JtdWxfXyggc2VsZiwgb3RoZXIgKToKICAgIHJldHVybiBzZWxmICogb3RoZXIKCiAgZGVmIF9fc3RyX18oIHNlbGYgKToKICAgIGlmIHNlbGYgPT0gSU5GSU5JVFk6IHJldHVybiAiaW5maW5pdHkiCiAgICByZXR1cm4gIiglZCwlZCkiICUgKCBzZWxmLl9feCwgc2VsZi5fX3kgKQoKICBkZWYgZG91YmxlKCBzZWxmICk6CiAgICBpZiBzZWxmID09IElORklOSVRZOgogICAgICByZXR1cm4gSU5GSU5JVFkKCiAgICBwID0gc2VsZi5fX2N1cnZlLnAoKQogICAgYSA9IHNlbGYuX19jdXJ2ZS5hKCkKICAgIGwgPSAoICggMyAqIHNlbGYuX194ICogc2VsZi5fX3ggKyBhICkgKiBcCiAgICAgICAgICBpbnZlcnNlX21vZCggMiAqIHNlbGYuX195LCBwICkgKSAlIHAKICAgIHgzID0gKCBsICogbCAtIDIgKiBzZWxmLl9feCApICUgcAogICAgeTMgPSAoIGwgKiAoIHNlbGYuX194IC0geDMgKSAtIHNlbGYuX195ICkgJSBwCiAgICByZXR1cm4gUG9pbnQoIHNlbGYuX19jdXJ2ZSwgeDMsIHkzICkKCiAgZGVmIHgoIHNlbGYgKToKICAgIHJldHVybiBzZWxmLl9feAoKICBkZWYgeSggc2VsZiApOgogICAgcmV0dXJuIHNlbGYuX195CgogIGRlZiBjdXJ2ZSggc2VsZiApOgogICAgcmV0dXJuIHNlbGYuX19jdXJ2ZQogIAogIGRlZiBvcmRlciggc2VsZiApOgogICAgcmV0dXJuIHNlbGYuX19vcmRlcgogICAgCklORklOSVRZID0gUG9pbnQoIE5vbmUsIE5vbmUsIE5vbmUgKQoKZGVmIGludmVyc2VfbW9kKCBhLCBtICk6CiAgaWYgYSA8IDAgb3IgbSA8PSBhOiBhID0gYSAlIG0KICBjLCBkID0gYSwgbQogIHVjLCB2YywgdWQsIHZkID0gMSwgMCwgMCwgMQogIHdoaWxlIGMgIT0gMDoKICAgIHEsIGMsIGQgPSBkaXZtb2QoIGQsIGMgKSArICggYywgKQogICAgdWMsIHZjLCB1ZCwgdmQgPSB1ZCAtIHEqdWMsIHZkIC0gcSp2YywgdWMsIHZjCiAgYXNzZXJ0IGQgPT0gMQogIGlmIHVkID4gMDogcmV0dXJuIHVkCiAgZWxzZTogcmV0dXJuIHVkICsgbQoKCl9wID0gMHhGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRUZGRkZGQzJGTApfciA9IDB4RkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkVCQUFFRENFNkFGNDhBMDNCQkZEMjVFOENEMDM2NDE0MUwKX2IgPSAweDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDdMCl9hID0gMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwTApfR3ggPSAweDc5QkU2NjdFRjlEQ0JCQUM1NUEwNjI5NUNFODcwQjA3MDI5QkZDREIyRENFMjhEOTU5RjI4MTVCMTZGODE3OThMCl9HeSA9IDB4NDgzYWRhNzcyNmEzYzQ2NTVkYTRmYmZjMGUxMTA4YThmZDE3YjQ0OGE2ODU1NDE5OWM0N2QwOGZmYjEwZDRiOEwKCmNsYXNzIFNpZ25hdHVyZSggb2JqZWN0ICk6CiAgZGVmIF9faW5pdF9fKCBzZWxmLCByLCBzICk6CiAgICBzZWxmLnIgPSByCiAgICBzZWxmLnMgPSBzCiAgICAKY2xhc3MgUHVibGljX2tleSggb2JqZWN0ICk6CiAgZGVmIF9faW5pdF9fKCBzZWxmLCBnZW5lcmF0b3IsIHBvaW50ICk6CiAgICBzZWxmLmN1cnZlID0gZ2VuZXJhdG9yLmN1cnZlKCkKICAgIHNlbGYuZ2VuZXJhdG9yID0gZ2VuZXJhdG9yCiAgICBzZWxmLnBvaW50ID0gcG9pbnQKICAgIG4gPSBnZW5lcmF0b3Iub3JkZXIoKQogICAgaWYgbm90IG46CiAgICAgIHJhaXNlIFJ1bnRpbWVFcnJvciwgIkdlbmVyYXRvciBwb2ludCBtdXN0IGhhdmUgb3JkZXIuIgogICAgaWYgbm90IG4gKiBwb2ludCA9PSBJTkZJTklUWToKICAgICAgcmFpc2UgUnVudGltZUVycm9yLCAiR2VuZXJhdG9yIHBvaW50IG9yZGVyIGlzIGJhZC4iCiAgICBpZiBwb2ludC54KCkgPCAwIG9yIG4gPD0gcG9pbnQueCgpIG9yIHBvaW50LnkoKSA8IDAgb3IgbiA8PSBwb2ludC55KCk6CiAgICAgIHJhaXNlIFJ1bnRpbWVFcnJvciwgIkdlbmVyYXRvciBwb2ludCBoYXMgeCBvciB5IG91dCBvZiByYW5nZS4iCgogIGRlZiB2ZXJpZmllcyggc2VsZiwgaGFzaCwgc2lnbmF0dXJlICk6CiAgICBHID0gc2VsZi5nZW5lcmF0b3IKICAgIG4gPSBHLm9yZGVyKCkKICAgIHIgPSBzaWduYXR1cmUucgogICAgcyA9IHNpZ25hdHVyZS5zCiAgICBpZiByIDwgMSBvciByID4gbi0xOiByZXR1cm4gRmFsc2UKICAgIGlmIHMgPCAxIG9yIHMgPiBuLTE6IHJldHVybiBGYWxzZQogICAgYyA9IGludmVyc2VfbW9kKCBzLCBuICkKICAgIHUxID0gKCBoYXNoICogYyApICUgbgogICAgdTIgPSAoIHIgKiBjICkgJSBuCiAgICB4eSA9IHUxICogRyArIHUyICogc2VsZi5wb2ludAogICAgdiA9IHh5LngoKSAlIG4KICAgIHJldHVybiB2ID09IHIK