bitcoin-cigs 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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')