bitcoin-cigs 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/misc/jasvet.py ADDED
@@ -0,0 +1,632 @@
1
+ #!/usr/bin/env python
2
+
3
+ # jackjack's signing/verifying tool
4
+ # verifies base64 signatures from Bitcoin
5
+ # signs message in three formats:
6
+ # - Bitcoin base64 (compatible with Bitcoin)
7
+ # - ASCII armored, Clearsign
8
+ # - ASCII armored, Base64
9
+ #
10
+ # Licence: Public domain or CC0
11
+
12
+ import time
13
+ import hashlib
14
+ import random
15
+ import base64
16
+
17
+ FTVerbose=False
18
+
19
+
20
+
21
+ def randomk(): #better make it stronger
22
+ rk=0
23
+ for i in range(8):
24
+ rk= rk | long(random.random()*0xffffffff)<<(32*i)
25
+ return rk
26
+
27
+ # Common constants/functions for Bitcoin
28
+
29
+ def hash_160_to_bc_address(h160, addrtype=0):
30
+ vh160 = chr(addrtype) + h160
31
+ h = Hash(vh160)
32
+ addr = vh160 + h[0:4]
33
+ print "b58:::", base64.b64encode(addr), b58encode(addr)
34
+ return b58encode(addr)
35
+
36
+ def bc_address_to_hash_160(addr):
37
+ bytes = b58decode(addr, 25)
38
+ return bytes[1:21]
39
+
40
+ def Hash(data):
41
+ print "HASH", hashlib.sha256(hashlib.sha256(data).digest()).digest()
42
+ return hashlib.sha256(hashlib.sha256(data).digest()).digest()
43
+
44
+ def sha256(data):
45
+ return hashlib.sha256(data).digest()
46
+
47
+ def sha1(data):
48
+ return hashlib.sha1(data).digest()
49
+
50
+ __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
51
+ __b58base = len(__b58chars)
52
+
53
+ def b58encode(v):
54
+ long_value = 0L
55
+ for (i, c) in enumerate(v[::-1]):
56
+ long_value += (256**i) * ord(c)
57
+
58
+ result = ''
59
+ while long_value >= __b58base:
60
+ div, mod = divmod(long_value, __b58base)
61
+ result = __b58chars[mod] + result
62
+ long_value = div
63
+ result = __b58chars[long_value] + result
64
+
65
+ nPad = 0
66
+ for c in v:
67
+ if c == '\0': nPad += 1
68
+ else: break
69
+
70
+ return (__b58chars[0]*nPad) + result
71
+
72
+ def b58decode(v, length):
73
+ long_value = 0L
74
+ for (i, c) in enumerate(v[::-1]):
75
+ long_value += __b58chars.find(c) * (__b58base**i)
76
+
77
+ result = ''
78
+ while long_value >= 256:
79
+ div, mod = divmod(long_value, 256)
80
+ result = chr(mod) + result
81
+ long_value = div
82
+ result = chr(long_value) + result
83
+
84
+ nPad = 0
85
+ for c in v:
86
+ if c == __b58chars[0]: nPad += 1
87
+ else: break
88
+
89
+ result = chr(0)*nPad + result
90
+ if length is not None and len(result) != length:
91
+ return None
92
+
93
+ return result
94
+
95
+
96
+ def regenerate_key(sec):
97
+ b = ASecretToSecret(sec)
98
+ if not b:
99
+ return False
100
+ b = b[0:32]
101
+ secret = int('0x' + b.encode('hex'), 16)
102
+ return EC_KEY(secret)
103
+
104
+ def GetPubKey(pkey, compressed=False):
105
+ return i2o_ECPublicKey(pkey, compressed)
106
+
107
+ def GetPrivKey(pkey, compressed=False):
108
+ return i2d_ECPrivateKey(pkey, compressed)
109
+
110
+ def GetSecret(pkey):
111
+ return ('%064x' % pkey.secret).decode('hex')
112
+
113
+
114
+ def i2d_ECPrivateKey(pkey, compressed=False):#, crypted=True):
115
+ part3='a081a53081a2020101302c06072a8648ce3d0101022100' # for uncompressed keys
116
+ if compressed:
117
+ if True:#not crypted: ## Bitcoin accepts both part3's for crypted wallets...
118
+ part3='a08185308182020101302c06072a8648ce3d0101022100' # for compressed keys
119
+ key = '3081d30201010420' + \
120
+ '%064x' % pkey.secret + \
121
+ part3 + \
122
+ '%064x' % _p + \
123
+ '3006040100040107042102' + \
124
+ '%064x' % _Gx + \
125
+ '022100' + \
126
+ '%064x' % _r + \
127
+ '020101a124032200'
128
+ else:
129
+ key = '308201130201010420' + \
130
+ '%064x' % pkey.secret + \
131
+ part3 + \
132
+ '%064x' % _p + \
133
+ '3006040100040107044104' + \
134
+ '%064x' % _Gx + \
135
+ '%064x' % _Gy + \
136
+ '022100' + \
137
+ '%064x' % _r + \
138
+ '020101a144034200'
139
+
140
+ return key.decode('hex') + i2o_ECPublicKey(pkey, compressed)
141
+
142
+ def i2o_ECPublicKey(pkey, compressed=False):
143
+ if compressed:
144
+ if pkey.pubkey.point.y() & 1:
145
+ key = '03' + '%064x' % pkey.pubkey.point.x()
146
+ else:
147
+ key = '02' + '%064x' % pkey.pubkey.point.x()
148
+ else:
149
+ key = '04' + \
150
+ '%064x' % pkey.pubkey.point.x() + \
151
+ '%064x' % pkey.pubkey.point.y()
152
+
153
+ return key.decode('hex')
154
+
155
+ def hash_160(public_key):
156
+ md = hashlib.new('ripemd160')
157
+ md.update(hashlib.sha256(public_key).digest())
158
+ return md.digest()
159
+
160
+ def public_key_to_bc_address(public_key, v=0):
161
+ h160 = hash_160(public_key)
162
+ return hash_160_to_bc_address(h160, v)
163
+
164
+ def inverse_mod( a, m ):
165
+ if a < 0 or m <= a: a = a % m
166
+ c, d = a, m
167
+ uc, vc, ud, vd = 1, 0, 0, 1
168
+ while c != 0:
169
+ q, c, d = divmod( d, c ) + ( c, )
170
+ uc, vc, ud, vd = ud - q*uc, vd - q*vc, uc, vc
171
+ assert d == 1
172
+ if ud > 0: return ud
173
+ else: return ud + m
174
+
175
+ class CurveFp( object ):
176
+ def __init__( self, p, a, b ):
177
+ self.__p = p
178
+ self.__a = a
179
+ self.__b = b
180
+
181
+ def p( self ):
182
+ return self.__p
183
+
184
+ def a( self ):
185
+ return self.__a
186
+
187
+ def b( self ):
188
+ return self.__b
189
+
190
+ def contains_point( self, x, y ):
191
+ return ( y * y - ( x * x * x + self.__a * x + self.__b ) ) % self.__p == 0
192
+
193
+ class Point( object ):
194
+ def __init__( self, curve, x, y, order = None ):
195
+ print "JERE", curve, x, y, order
196
+ self.__curve = curve
197
+ self.__x = x
198
+ self.__y = y
199
+ self.__order = order
200
+ if self.__curve: assert self.__curve.contains_point( x, y )
201
+ if order: assert self * order == INFINITY
202
+
203
+ def __add__( self, other ):
204
+ if other == INFINITY: return self
205
+ if self == INFINITY: return other
206
+ assert self.__curve == other.__curve
207
+ if self.__x == other.__x:
208
+ if ( self.__y + other.__y ) % self.__curve.p() == 0:
209
+ return INFINITY
210
+ else:
211
+ return self.double()
212
+
213
+ p = self.__curve.p()
214
+ l = ( ( other.__y - self.__y ) * \
215
+ inverse_mod( other.__x - self.__x, p ) ) % p
216
+ x3 = ( l * l - self.__x - other.__x ) % p
217
+ y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
218
+ return Point( self.__curve, x3, y3 )
219
+
220
+ def __mul__( self, other ):
221
+ def leftmost_bit( x ):
222
+ assert x > 0
223
+ result = 1L
224
+ while result <= x: result = 2 * result
225
+ return result / 2
226
+
227
+ print "MULT ARG ", other
228
+ e = other
229
+ if self.__order: e = e % self.__order
230
+ print "EEEE ", e, self.__order
231
+ if e == 0: return INFINITY
232
+ if self == INFINITY: return INFINITY
233
+ assert e > 0
234
+ e3 = 3 * e
235
+ negative_self = Point( self.__curve, self.__x, -self.__y, self.__order )
236
+ i = leftmost_bit( e3 ) / 2
237
+ result = self
238
+ while i > 1:
239
+ result = result.double()
240
+ if ( e3 & i ) != 0 and ( e & i ) == 0: result = result + self
241
+ if ( e3 & i ) == 0 and ( e & i ) != 0: result = result + negative_self
242
+ i = i / 2
243
+ return result
244
+
245
+ def __rmul__( self, other ):
246
+ return self * other
247
+
248
+ def __str__( self ):
249
+ if self == INFINITY: return "infinity"
250
+ return "(%d,%d)" % ( self.__x, self.__y )
251
+
252
+ def double( self ):
253
+ if self == INFINITY:
254
+ return INFINITY
255
+
256
+ p = self.__curve.p()
257
+ a = self.__curve.a()
258
+ l = ( ( 3 * self.__x * self.__x + a ) * \
259
+ inverse_mod( 2 * self.__y, p ) ) % p
260
+ x3 = ( l * l - 2 * self.__x ) % p
261
+ y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
262
+ return Point( self.__curve, x3, y3 )
263
+
264
+ def x( self ):
265
+ return self.__x
266
+
267
+ def y( self ):
268
+ return self.__y
269
+
270
+ def curve( self ):
271
+ return self.__curve
272
+
273
+ def order( self ):
274
+ return self.__order
275
+
276
+ INFINITY = Point( None, None, None )
277
+
278
+ def str_to_long(b):
279
+ res = 0
280
+ pos = 1
281
+ for a in reversed(b):
282
+ res += ord(a) * pos
283
+ pos *= 256
284
+ return res
285
+
286
+ class Public_key( object ):
287
+ def __init__( self, generator, point, c ):
288
+ self.curve = generator.curve()
289
+ self.generator = generator
290
+ self.point = point
291
+ self.compressed = c
292
+ n = generator.order()
293
+ if not n:
294
+ raise RuntimeError, "Generator point must have order."
295
+ if not n * point == INFINITY:
296
+ raise RuntimeError, "Generator point order is bad."
297
+ if point.x() < 0 or n <= point.x() or point.y() < 0 or n <= point.y():
298
+ raise RuntimeError, "Generator point has x or y out of range."
299
+
300
+ def verify( self, hash, signature ):
301
+ if isinstance(hash, str):
302
+ hash=str_to_long(hash)
303
+ G = self.generator
304
+ n = G.order()
305
+ r = signature.r
306
+ s = signature.s
307
+ if r < 1 or r > n-1: return False
308
+ if s < 1 or s > n-1: return False
309
+ c = inverse_mod( s, n )
310
+ u1 = ( hash * c ) % n
311
+ u2 = ( r * c ) % n
312
+ xy = u1 * G + u2 * self.point
313
+ v = xy.x() % n
314
+ return v == r
315
+
316
+ def ser(self):
317
+ if self.compressed:
318
+ if self.point.y() & 1:
319
+ key = '03' + '%064x' % self.point.x()
320
+ else:
321
+ key = '02' + '%064x' % self.point.x()
322
+ else:
323
+ key = '04' + \
324
+ '%064x' % self.point.x() + \
325
+ '%064x' % self.point.y()
326
+
327
+ return key.decode('hex')
328
+
329
+
330
+ class Signature( object ):
331
+ def __init__( self, r, s ):
332
+ self.r = r
333
+ self.s = s
334
+
335
+ def ser(self):
336
+ return ("%064x%064x"%(self.r,self.s)).decode('hex')
337
+
338
+ class Private_key( object ):
339
+ def __init__( self, public_key, secret_multiplier ):
340
+ self.public_key = public_key
341
+ self.secret_multiplier = secret_multiplier
342
+
343
+ # def der( self ):
344
+ # hex_der_key = '06052b8104000a30740201010420' + \
345
+ # '%064x' % self.secret_multiplier + \
346
+ # 'a00706052b8104000aa14403420004' + \
347
+ # '%064x' % self.public_key.point.x() + \
348
+ # '%064x' % self.public_key.point.y()
349
+ # return hex_der_key.decode('hex')
350
+
351
+ def sign( self, hash, random_k ):
352
+ if isinstance(hash, str):
353
+ hash=str_to_long(hash)
354
+ G = self.public_key.generator
355
+ n = G.order()
356
+ k = random_k % n
357
+ p1 = k * G
358
+ r = p1.x()
359
+ if r == 0: raise RuntimeError, "amazingly unlucky random number r"
360
+ s = ( inverse_mod( k, n ) * \
361
+ ( hash + ( self.secret_multiplier * r ) % n ) ) % n
362
+ if s == 0: raise RuntimeError, "amazingly unlucky random number s"
363
+ return Signature( r, s )
364
+
365
+ class EC_KEY(object):
366
+ def __init__( self, secret, c=False):
367
+ curve = CurveFp( _p, _a, _b )
368
+ generator = Point( curve, _Gx, _Gy, _r )
369
+ self.pubkey = Public_key( generator, generator * secret, c )
370
+ self.privkey = Private_key( self.pubkey, secret )
371
+ self.secret = secret
372
+
373
+ def format_msg_to_sign(msg):
374
+ return "\x18Bitcoin Signed Message:\n"+chr(len(msg))+msg #todo: check 18
375
+
376
+ def sqrt_mod(a, p):
377
+ return pow(a, (p+1)/4, p)
378
+
379
+ _p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
380
+ _r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
381
+ _b = 0x0000000000000000000000000000000000000000000000000000000000000007L
382
+ _a = 0x0000000000000000000000000000000000000000000000000000000000000000L
383
+ _Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
384
+ _Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
385
+
386
+ curve_secp256k1 = CurveFp (_p, _a, _b)
387
+ generator_secp256k1 = g = Point (curve_secp256k1, _Gx, _Gy, _r)
388
+ randrange = random.SystemRandom().randrange
389
+
390
+ # Signing/verifying
391
+
392
+ def verify_message_Bitcoin(address, signature, message, pureECDSASigning=False):
393
+ print "DECODE"
394
+ print address
395
+ print base64.b64encode(b58decode(address, None))
396
+ networkversion=str_to_long(b58decode(address, None)) >> (8*24)
397
+ print "COOL"
398
+ print str_to_long(b58decode(address, None))
399
+ print "NETWORK VERSION"
400
+ print networkversion
401
+ msg=message
402
+ print msg
403
+ if not pureECDSASigning:
404
+ print "SHIT"
405
+ print message
406
+ print format_msg_to_sign(message)
407
+ msg=Hash(format_msg_to_sign(message))
408
+ print msg
409
+
410
+ compressed=False
411
+ curve = curve_secp256k1
412
+ G = generator_secp256k1
413
+ _a,_b,_p=curve.a(),curve.b(),curve.p()
414
+
415
+ order = G.order()
416
+ print "G ORDER ", order
417
+ sig = base64.b64decode(signature)
418
+ if len(sig) != 65:
419
+ raise Exception("vmB","Bad signature")
420
+ print "SIG ", sig
421
+
422
+ hb = ord(sig[0])
423
+ print "hb", hb
424
+ r,s = map(str_to_long,[sig[1:33],sig[33:65]])
425
+ print "r, s", r, s
426
+
427
+ if hb < 27 or hb >= 35:
428
+ raise Exception("vmB","Bad first byte")
429
+ if hb >= 31:
430
+ compressed = True
431
+ hb -= 4
432
+
433
+ recid = hb - 27
434
+ x = (r + (recid/2) * order) % _p
435
+ y2 = ( pow(x,3,_p) + _a*x + _b ) % _p
436
+ print "y2, p", y2, _p
437
+ yomy = sqrt_mod(y2, _p)
438
+ print "yomy", yomy
439
+ if (yomy - recid) % 2 == 0:
440
+ y=yomy
441
+ else:
442
+ y=_p - yomy
443
+ print "y", y
444
+
445
+ R = Point(curve, x, y, order)
446
+ print "R", R
447
+ e = str_to_long(msg)
448
+ minus_e = -e % order
449
+ print "e, -e: ", e, minus_e
450
+ inv_r = inverse_mod(r,order)
451
+ print "inv_r", inv_r
452
+ print "s", s
453
+
454
+ Q = inv_r * ( R*s + G*minus_e )
455
+ print "Q", Q
456
+
457
+ public_key = Public_key(G, Q, compressed)
458
+ print "SER", public_key.ser()
459
+ addr = public_key_to_bc_address(public_key.ser(), networkversion)
460
+ if address != addr:
461
+ raise Exception("vmB","Bad address. Signing: %s, received: %s"%(addr,address))
462
+
463
+
464
+ def sign_message(secret, message, pureECDSASigning=False):
465
+ if len(secret) == 32:
466
+ pkey = EC_KEY(str_to_long(secret))
467
+ compressed = False
468
+ elif len(secret) == 33:
469
+ pkey = EC_KEY(str_to_long(secret[:-1]))
470
+ secret=secret[:-1]
471
+ compressed = True
472
+ else:
473
+ raise Exception("sm","Bad private key size")
474
+
475
+ msg=message
476
+ if not pureECDSASigning:
477
+ msg=Hash(format_msg_to_sign(message))
478
+
479
+ eckey = EC_KEY(str_to_long(secret), compressed)
480
+ private_key = eckey.privkey
481
+ public_key = eckey.pubkey
482
+ addr = public_key_to_bc_address(GetPubKey(eckey,eckey.pubkey.compressed))
483
+
484
+ sig = private_key.sign(msg, randomk())
485
+ if not public_key.verify(msg, sig):
486
+ raise Exception("sm","Problem signing message")
487
+ return [sig,addr,compressed,public_key]
488
+
489
+
490
+ def sign_message_Bitcoin(secret, msg, pureECDSASigning=False):
491
+ sig,addr,compressed,public_key=sign_message(secret, msg, pureECDSASigning)
492
+
493
+
494
+ for i in range(4):
495
+ hb=27+i
496
+ if compressed:
497
+ hb+=4
498
+ sign=base64.b64encode(chr(hb)+sig.ser())
499
+ try:
500
+ verify_message_Bitcoin(addr, sign, msg, pureECDSASigning)
501
+ return {'address':addr, 'b64-signature':sign, 'signature':chr(hb)+sig.ser(), 'message':msg}
502
+ except Exception as e:
503
+ # print e.args
504
+ pass
505
+
506
+ raise Exception("smB","Unable to construct recoverable key")
507
+
508
+ def FormatText(t, sigctx, verbose=False): #sigctx: False=what is displayed, True=what is signed
509
+ r=''
510
+ te=t.split('\n')
511
+ for l in te:
512
+ while len(l) and l[len(l)-1] in [' ', '\t', chr(9)]:
513
+ l=l[:-1]
514
+ if not len(l) or l[len(l)-1]!='\r':
515
+ l+='\r'
516
+ if not sigctx:
517
+ if len(l) and l[0]=='-':
518
+ l='- '+l[1:]
519
+ r+=l+'\n'
520
+ r=r[:-2]
521
+
522
+ global FTVerbose
523
+ if FTVerbose:
524
+ print ' -- Sent: '+t.encode('hex')
525
+ if sigctx:
526
+ print ' -- Signed: '+r.encode('hex')
527
+ else:
528
+ print ' -- Displayed: '+r.encode('hex')
529
+
530
+ return r
531
+
532
+
533
+ def crc24(m):
534
+ INIT = 0xB704CE
535
+ POLY = 0x1864CFB
536
+ crc = INIT
537
+ r = ''
538
+ for o in m:
539
+ o=ord(o)
540
+ crc ^= (o << 16)
541
+ for i in xrange(8):
542
+ crc <<= 1
543
+ if crc & 0x1000000:
544
+ crc ^= POLY
545
+ for i in range(3):
546
+ r += chr( ( crc & (0xff<<(8*i))) >> (8*i) )
547
+ return r
548
+
549
+ def chunks(t, n):
550
+ return [t[i:i+n] for i in range(0, len(t), n)]
551
+
552
+ def ASCIIArmory(block, name):
553
+ r='-----BEGIN '+name+'-----\r\n'
554
+ r+='\r\n'.join(chunks(base64.b64encode(block), 64))+'\r\n='
555
+ r+=base64.b64encode(crc24(block))+'\r\n'
556
+ r+='-----END '+name+'-----'
557
+ return r
558
+
559
+
560
+ #==============================================
561
+
562
+ def verifySignature(addr, b64sig, msg):
563
+ return verify_message_Bitcoin(addr, b64sig, FormatText(msg, True))
564
+
565
+ def ASv0(privkey, msg):
566
+ return sign_message_Bitcoin(privkey, FormatText(msg, True))
567
+
568
+ def ASv1CS(privkey, msg):
569
+ sig=ASv0(privkey, msg)
570
+ r='-----BEGIN SIGNED BITCOIN MESSAGE-----\r\n\r\n'
571
+ r+=FormatText(msg, False)+'\r\n'
572
+ r+=ASCIIArmory(sig['signature'], 'BITCOIN SIGNATURE')
573
+ return r
574
+
575
+ def ASv1B64(privkey, msg):
576
+ sig=ASv0(privkey, msg)
577
+ return ASCIIArmory(sig['signature']+sig['message'], 'BITCOIN SIGNED MESSAGE')
578
+
579
+
580
+
581
+ #==============================================
582
+
583
+ #
584
+ # Some tests with ugly output
585
+ # You can delete the print commands in FormatText() after testing
586
+ #
587
+
588
+ pvk1='\x01'*32
589
+ text0='Hello world!'
590
+ text1='Hello world!\n'
591
+ text2='Hello world!\n\t'
592
+ text3='Hello world!\n-jackjack'
593
+ text4='Hello world!\n-jackjack '
594
+ text5='Hello world!'
595
+
596
+ FTVerbose=True
597
+ # sv0=ASv0(pvk1, text1)
598
+ # print "STUFF TO SIGN"
599
+ # print sv0
600
+ # print "KK"
601
+ # print verifySignature(sv0['address'], sv0['b64-signature'], sv0['message'])
602
+ # print
603
+ # print ASv1B64(pvk1, text1)
604
+ # print
605
+ # print ASv1CS(pvk1, text1)
606
+ # print
607
+ # print ASv1CS(pvk1, text2)
608
+ # print
609
+ # print ASv1CS(pvk1, text3)
610
+ # print
611
+ # print ASv1CS(pvk1, text4)
612
+ # print
613
+ # print ASv1CS(pvk1, text5)
614
+
615
+ public_key = "11o51X3ciSjoLWFN3sbg3yzCM8RSuD2q9"
616
+ # private_key = "5JFZuDkLgbEXK4CUEiXyyz4fUqzAsQ5QUqufdJy8MoLA9S1RdNX" # WIF Base58 51 char (start w 5)
617
+ # private_key = "Ky9JDVGHsk6gnh7dDYKkWWsAquDLZSrSdtsTVGJjUoVZN7sYjyyP" # WIF Base58 52 char (start w K or L)
618
+ # private_key = "39678A14ECA8479B3C58DCD25A5C94BE768389E823435C4DDFCAEB13519AB10E" # HEX 64 chars
619
+ # private_key = "OWeKFOyoR5s8WNzSWlyUvnaDiegjQ1xN38rrE1GasQ4=" # Base64 44 chars
620
+ ## ["39678A14ECA8479B3C58DCD25A5C94BE768389E823435C4DDFCAEB13519AB10E"].pack('H*')
621
+ private_key = "9g\x8A\x14\xEC\xA8G\x9B<X\xDC\xD2Z\\\x94\xBEv\x83\x89\xE8#C\\M\xDF\xCA\xEB\x13Q\x9A\xB1\x0E"
622
+ msg = "this is a message"
623
+ signature = sign_message_Bitcoin(private_key, msg)['b64-signature']
624
+ print signature
625
+
626
+ # print verifySignature(public_key, signature, msg)
627
+
628
+ #print verifySignature(public_key, signature, msg)
629
+
630
+ #print verifySignature('13C5HZKutjMDeuc7f5mPj6XGpJCZu7xKh2', 'H55JIuwEi4YXzINOzx2oU6VsfBcTOScpFtp10pP/M4EWV336ClH65SObwPXnRf/fMXDu8hs8nweB42CtpWgngeM=', 'abc')
631
+
632
+ #print verifySignature('13C5HZKutjMDeuc7f5mPj6XGpJCZu7xKh2', 'H55JIuwEi4YXzINOzx2oU6VsfBcTOScpFtp10pP/M4EWV336ClH65SObwPXnRf/fMXDu8hs8nweB42CtpWgngeM=', 'aaa')