def decrypt(k, passphrase): if passphrase is None or passphrase == '': raise ValueError('Passphrase must not be empty.') k_buffer = CBase58Data.from_str(k) if k_buffer[0:1] == '\x42': return Bip38._decrypt_no_ec_multiply(k_buffer, passphrase) elif k_buffer[0:1] == '\x43': return Bip38._decrypt_ec_multiply(k_buffer, passphrase) else: raise Exception('Unknown key type.')
def encrypt_ec_multiply(intermediate, seedb=None): i_buffer = CBase58Data.from_str(intermediate) ownerentropy = i_buffer[7:7 + 8] passpoint_hex = i_buffer[15:15 + 33] flagbyte = array('B', [0]) if i_buffer[6:7] == '\x51': flagbyte[0] |= 0x04 if seedb is None: seedb = os.urandom(24) factorb_hex = SHA256.new(SHA256.new(seedb).digest()).digest() NID_secp256k1 = 714 k = ssl.EC_KEY_new_by_curve_name(NID_secp256k1) group = ssl.EC_KEY_get0_group(k) pub_key = ssl.EC_POINT_new(group) ctx = ssl.BN_CTX_new() passpoint = ssl.EC_POINT_new(group) ssl.EC_POINT_oct2point(group, passpoint, passpoint_hex, 33, ctx) factorb = ssl.BN_bin2bn(factorb_hex, 32, ssl.BN_new()) ssl.EC_POINT_mul(group, pub_key, None, passpoint, factorb, ctx) # FIXME: set correct compression ssl.EC_KEY_set_public_key(k, pub_key) size = ssl.i2o_ECPublicKey(k, 0) mb = ctypes.create_string_buffer(size) ssl.i2o_ECPublicKey(k, ctypes.byref(ctypes.pointer(mb))) generatedaddress = str( CBase58Data(ser_uint160(Hash160(mb.raw)), CBitcoinAddress.PUBKEY_ADDRESS)) addresshash = SHA256.new( SHA256.new(generatedaddress).digest()).digest()[:4] derived = scrypt.hash(passpoint_hex, addresshash + ownerentropy, N=1024, r=1, p=1, buflen=64) derived_half1 = derived[:32] derived_half2 = derived[32:64] #confirmation = Bip38._get_confirmation_code(flagbyte, ownerentropy, factorb_hex, derived_half1, derived_half2, addresshash) cipher = AES.new(derived_half2) ep1 = cipher.encrypt(Bip38.xor_zip(seedb[:16], derived_half1[:16])) ep2 = cipher.encrypt( Bip38.xor_zip(ep1[8:16] + seedb[16:24], derived_half1[16:32])) prefix = '\x43' return str( CBase58Data( prefix + flagbyte.tostring() + addresshash + ownerentropy + ep1[:8] + ep2, 0x01))
def encrypt_ec_multiply(intermediate, seedb=None): i_buffer = CBase58Data.from_str(intermediate) ownerentropy = i_buffer[7:7+8] passpoint_hex = i_buffer[15:15+33] flagbyte=array('B', [0]) if i_buffer[6:7] == '\x51': flagbyte[0] |= 0x04 if seedb is None: seedb = os.urandom(24) factorb_hex = SHA256.new(SHA256.new(seedb).digest()).digest() NID_secp256k1 = 714 k = ssl.EC_KEY_new_by_curve_name(NID_secp256k1) group = ssl.EC_KEY_get0_group(k) pub_key = ssl.EC_POINT_new(group) ctx = ssl.BN_CTX_new() passpoint = ssl.EC_POINT_new(group) ssl.EC_POINT_oct2point(group, passpoint, passpoint_hex, 33, ctx) factorb = ssl.BN_bin2bn(factorb_hex, 32, ssl.BN_new()) ssl.EC_POINT_mul(group, pub_key, None, passpoint, factorb, ctx) # FIXME: set correct compression ssl.EC_KEY_set_public_key(k, pub_key) size = ssl.i2o_ECPublicKey(k, 0) mb = ctypes.create_string_buffer(size) ssl.i2o_ECPublicKey(k, ctypes.byref(ctypes.pointer(mb))) generatedaddress = str(CBase58Data(ser_uint160(Hash160(mb.raw)), CBitcoinAddress.PUBKEY_ADDRESS)) addresshash = SHA256.new(SHA256.new(generatedaddress).digest()).digest()[:4] derived = scrypt.hash(passpoint_hex, addresshash + ownerentropy, N=1024, r=1, p=1, buflen=64) derived_half1 = derived[:32] derived_half2 = derived[32:64] #confirmation = Bip38._get_confirmation_code(flagbyte, ownerentropy, factorb_hex, derived_half1, derived_half2, addresshash) cipher = AES.new(derived_half2) ep1 = cipher.encrypt(Bip38.xor_zip(seedb[:16], derived_half1[:16])) ep2 = cipher.encrypt(Bip38.xor_zip(ep1[8:16] + seedb[16:24], derived_half1[16:32])) prefix = '\x43' return str(CBase58Data(prefix + flagbyte.tostring() + addresshash + ownerentropy + ep1[:8] + ep2, 0x01))
return str(CBase58Data(h160, v)) def double_sha256(x): x = hashlib.sha256(x).digest() x = hashlib.sha256(x).digest() return x #pubkey = '1PE6TQi6HTVNz5DLwB1LcpMBALubfuN2z2' # test vector #pubkey = '1nsEdR3HqU6jaAPtqEwXRd9WFkrFzGn9r' #aąc pubkey = '1KmMbhS2hSmLFDNXTYH3okE4k84gwZaiwV' pubd = double_sha256(pubkey) #privkey = '6PfQu77ygVyJLZjfvMLyhLMQbYnu5uguoJJ4kMCLqWwPEdfpwANVS76gTX' # test vector #privkey = '6PfS9Qamt8GMLGgNCcnvban9SPzGTvCp9Xjhxdz6wVCV2wpGqkHtsSNr6N' #aąc privkey = '6PfYU8C5sLGsjDNWsCHRYD6G5noFmc184Q4owtnfvXrUdpsfNkeTq2HDV8' privkey = CBase58Data.from_str(privkey) print 'key', b2a_hex(privkey) print 'version', privkey.nVersion assert(privkey[0] == '\x43') print "EC multiplication is used" assert(len(privkey) == 1+1+4+16+16) flags = ord(privkey[1]) if flags & 0x20: use_compressed = True print "Should be compressed" else: use_compressed = False print "Should not be compressed" if flags & 0x04: