forked from jgarzik/python-bitcoinlib
-
Notifications
You must be signed in to change notification settings - Fork 1
/
bip38.py
43 lines (32 loc) · 1.38 KB
/
bip38.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from bitcoin.key import CKey
from bitcoin.base58 import CBase58Data, CBitcoinAddress
from bitcoin.serialize import ser_uint160, Hash160
import Crypto.Cipher.AES as AES
import Crypto.Hash.SHA256 as SHA256
import scrypt
from itertools import izip
from array import array
class Bip38:
def __init__(self, k, passphrase, ec_multiply=False, ls_numbers=False):
self.k = k
self.passphrase = passphrase
self.ec_multiply = ec_multiply
self.ls_numbers = ls_numbers
def generate(self, k, passphrase):
pass
def get_encrypted(self):
address = str(CBase58Data(ser_uint160(Hash160(self.k.get_pubkey())), CBitcoinAddress.PUBKEY_ADDRESS))
salt = SHA256.new(SHA256.new(address).digest()).digest()[:4]
derived = scrypt.hash(self.passphrase, salt, N=16384, r=8, p=8, buflen=64)
dh1 = derived[:32]
dh2 = derived[32:64]
cipher = AES.new(dh2)
pkey = self.k.get_secret()
p1 = ''.join(chr(ord(c)^ord(k)) for c,k in izip(pkey[:16], dh1[:16]))
p2 = ''.join(chr(ord(c)^ord(k)) for c,k in izip(pkey[16:32], dh1[16:32]))
eh1 = cipher.encrypt(p1)
eh2 = cipher.encrypt(p2)
flagbyte=array('B', [0])
if self.ec_multiply is False: flagbyte[0] |= 0xc0
if self.k.get_compressed() is True: flagbyte[0] |= 0x20
return '\x42' + flagbyte.tostring() + salt + eh1 + eh2