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 _get_confirmation_code(flagbyte, ownerentropy, factorb, derived_half1, derived_half2, addresshash): k = CKey() k.set_compressed(True) k.generate(secret=factorb) pointb = k.get_pubkey() if len(pointb) != 33: return AssertionError('pointb (' + hexlify(pointb) + ') is ' + str(len(pointb)) + ' bytes. It should be 33 bytes.') if pointb[:1] != '\x02' and pointb[:1] != '\x03': return ValueError('pointb is not correct.') pointbprefix = Bip38.xor_zip( pointb[:1], chr(ord(derived_half2[31:32]) & ord('\x01'))) cipher = AES.new(derived_half2) pointbx1 = cipher.encrypt( Bip38.xor_zip(pointb[1:17], derived_half1[:16])) pointbx2 = cipher.encrypt( Bip38.xor_zip(pointb[17:33], derived_half1[16:32])) encryptedpointb = pointbprefix + pointbx1 + pointbx2 if len(encryptedpointb) != 33: return AssertionError('encryptedpointb is not 33 bytes long.') magic = '\x3b\xf6\xa8\x9a' return str( CBase58Data( magic + flagbyte.tostring() + addresshash + ownerentropy + encryptedpointb, 0x64))
def encrypt_no_ec_multiply(self): address = self.k.get_pubkey(form=CKeyForm.BASE58) addresshash = SHA256.new(SHA256.new(address).digest()).digest()[:4] derived = scrypt.hash(self.passphrase, addresshash, 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 = Bip38.xor_zip(pkey[:16], dh1[:16]) p2 = Bip38.xor_zip(pkey[16:32], dh1[16:32]) eh1 = cipher.encrypt(p1) eh2 = cipher.encrypt(p2) flagbyte = array('B', [0]) flagbyte[0] |= 0xc0 if self.k.get_compressed() is True: flagbyte[0] |= 0x20 prefix = '\x42' return str( CBase58Data(prefix + flagbyte.tostring() + addresshash + eh1 + eh2, 0x01))
def get_intermediate(self, salt=None, lot=0, sequence=0): if salt is None: if self.ls_numbers is True: salt = os.urandom(4) ownerentropy = salt + pack('>I', (lot * 4096) + sequence) else: salt = os.urandom(8) ownerentropy = salt else: if self.ls_numbers is True: ownerentropy = salt + pack('>I', (lot * 4096) + sequence) else: ownerentropy = salt prefactor = scrypt.hash(self.passphrase, salt, N=16384, r=8, p=8, buflen=32) if self.ls_numbers is True: passfactor = SHA256.new( SHA256.new(prefactor + ownerentropy).digest()).digest() else: passfactor = prefactor passpoint = Bip38._compute_passpoint(passfactor) if self.ls_numbers is True: magic = '\xE9\xB3\xE1\xFF\x39\xE2\x51' else: magic = '\xE9\xB3\xE1\xFF\x39\xE2\x53' return str(CBase58Data(magic + ownerentropy + passpoint, 0x2c))
def get_script(self): text = self.template.text variables = {} for var_name, v in self.variable_widgets.items(): var = str(v.text()) var_type = self.template.variables[var_name] # Convert input to appropriate format. if var_type == 'address': try: h160 = CBase58Data(var).to_bytes() except Exception: return 'Error: Could not decode <{}> address.'.format( var_name) var = ''.join(['0x', h160.encode('hex')]) elif var_type == 'text': # var = ''.join(['"', var, '"']) var = var.encode('hex') variables[var_name] = var # Replace the <variable> occurrences with their values. for k, v in variables.items(): old = ''.join(['<', k, '>']) text = text.replace(old, v) return text
def test_json_roundtrip(self): VALUES = [ 42, 0, -42, 2100000000000000, -2100000000000000, "basic string", "\u1111Unicode", "\U00010000Wide Unicode", "\x00\n\t\r\nEscape codes", "\"'\"Quotes", "", None, b"\x00\x01\xFFBinary data", b"", CBase58Data.from_bytes(b'\x00\x01\xFF', 42), P2SHBitcoinAddress.from_bytes(b'\x00\x01\xFF'), P2PKHBitcoinAddress.from_bytes(b'\x00\x01\xFF'), CMutableTxIn(COutPoint(b'\x00' * 16 + b'\xFF' * 16, 42), CScript(b'\x00\x01\xFF'), 42), CMutableTxOut(42, CScript(b'\x00\x01\xFF')), CMutableTransaction([ CMutableTxIn(COutPoint(b'\x00' * 32, 42), CScript(b'\x00\x01\xFF'), 42), CMutableTxIn(COutPoint(b'\xFF' * 32, 42), CScript(b'\xFF\x01\x00'), 43) ], [ CMutableTxOut(42, CScript(b'\x00\x01\xFF')), CMutableTxOut(43, CScript(b'\xFF\x01\x00')) ], 42, 3), [ 1, b'\x00\x01\xFF', "List Test", ], { 'a': 1, 'key': b'\xFF\x01\x00', 1: 'Dictionary Test' }, [ { 3: [ 0, 1, 2, ], }, [ [ b'\xFFRecursion Test', ], ], ], ] for value in VALUES: self.assertEqual(from_json(to_json(value)), value)
def BitcoinAddress(address): """Bitcoin address validation accepts both testnet and mainnet""" try: assert isinstance(address, str) assert 25 < len(address) < 36 addr = CBase58Data(address) assert addr.nVersion in BITCOIN_VERSION_BYTES return address except Exception: raise ValueError('{} is not a valid bitcoin address'.format(address))
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 scriptpubkey2dict(scriptPubKey): s = cscript2dict(scriptPubKey)['script'] if s[0]['opcode'] == "OP_HASH160": assert len(s) == 3, "unexpected script length" assert s[2]['opcode'] == 'OP_EQUAL', "unexpected scriptPubKey" return { 'type': "P2SH_OR_P2PKWH", 'address': str(CBase58Data.from_bytes(lx(s[1]['data']), 5)) } elif s[0]['opcode'] == 'OP_DUP': assert s[1]['opcode'] == 'OP_HASH160', "unexpected scriptPubKey" assert s[3]['opcode'] == 'OP_EQUALVERIFY', "unexpected scriptPubKey" assert s[4]['opcode'] == 'OP_CHECKSIG', "unexpected scriptPubKey" return { 'type': "P2PKH", 'address': str(CBase58Data.from_bytes(lx(s[2]['data']), 0)) } else: assert False, "unexpected scriptPubKey"
def encryptBIP0038(pubkey, privkey, secret): k = CKey() #decode the wallet import format by base58 decoding then dropping the last 4 bytes and the first byte decoded = b58decode(privkey) decoded = decoded[:-4] decoded = decoded[1:] k.generate(decoded) k.set_compressed(False) b = Bip38(k, secret) return str(CBase58Data(b.get_encrypted(), 0x01))
def decode_address(self): txt = str(self.address_line.text()) try: addr = CBase58Data(txt) except Exception: self.hash_line.setText('Could not decode address.') self.addr_version.setValue(0) return self.hash_line.setText(addr.to_bytes().encode('hex')) self.addr_version.setValue(addr.nVersion)
def decode_address(txt): """Decode txt into a RIPEMD-160 hash. Will raise if txt is not a valid address. Returns: Two-tuple of (raw_bytes, address_version) """ addr = CBase58Data(txt) raw = addr.to_bytes() return (addr.to_bytes(), addr.nVersion)
def format_variable_value(value, var_type): """Returns a 2-tuple of (is_valid, formatted_value).""" if var_type == 'address': try: h160 = CBase58Data(value).to_bytes() except Exception: # Check if value is a hash160. if is_hex(value) and len( format_hex_string(value, with_prefix=False)) == 40: h160 = format_hex_string(value, with_prefix=False).decode('hex') else: return False, 'Error: Could not decode address.' return True, '0x' + h160.encode('hex') elif var_type == 'pubkey': if not is_hex(value): return False, 'Error: Pubkey must be hex.' key_hex = format_hex_string(value, with_prefix=False) pub = CPubKey(key_hex.decode('hex')) if not pub.is_fullyvalid: return False, 'Error: Pubkey is invalid.' return True, '0x' + key_hex elif var_type == 'text': try: return True, '0x' + value.encode('hex') except Exception as e: return False, 'Error: ' + str(e) elif var_type == 'signature': if not is_hex(value): return False, 'Error: Signature must be hex.' # We remain algorithm-agnostic by not checking the length. return True, format_hex_string(value, with_prefix=True) elif var_type == 'script': if not is_hex(value): try: scr = Script.from_human(value) return True, format_hex_string(scr.get_hex(), with_prefix=True) except Exception: return False, 'Error: Cannot parse human-readable script.' try: scr = Script( format_hex_string(value, with_prefix=False).decode('hex')) return True, format_hex_string(value, with_prefix=True) except Exception: return False, 'Error: Cannot parse script.' return True, value
def encode_address(self): hash160 = str(self.hash_line.text()) if len(hash160) != 40: self.address_line.setText('Hash160 must be 40 characters.') self.status_message('Hash160 must be 40 characters.', True) return try: i = int(hash160, 16) except ValueError: self.address_line.setText('Hash160 must contain only hex characters.') self.status_message('Hash160 must contain only hex characters.', True) return version = self.addr_version.value() addr = CBase58Data.from_bytes(hash160.decode('hex'), version) self.address_line.setText(str(addr)) self.status_message('Encoded address "%s".' % str(addr))
def encode_address(self): hash160 = str(self.hash_line.text()) if len(hash160) != 40: self.address_line.setText("Hash160 must be 40 characters.") self.status_message("Hash160 must be 40 characters.", True) return try: i = int(hash160, 16) except ValueError: self.address_line.setText("Hash160 must contain only hex characters.") self.status_message("Hash160 must contain only hex characters.", True) return version = self.addr_version.value() addr = CBase58Data.from_bytes(hash160.decode("hex"), version) self.address_line.setText(str(addr)) self.status_message('Encoded address "%s".' % str(addr))
def is_valid_bitcoin_address(address, testnet=True): """ Check the address is a valide P2SH or P2PK bitcoin address Arguments: address(str) testnet(bool): True to also accept testnet addresses Returns: (bool): True if it is a valid, False otherwise """ try: assert isinstance(address, str) assert 25 < len(address) < 36 addr = CBase58Data(address) assert addr.nVersion in BITCOIN_VERSION_BYTES return True except Exception: return False
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 test_json_roundtrip(self): VALUES = [ 42, 0, -42, 2100000000000000, -2100000000000000, "basic string", "\u1111Unicode", "\U00010000Wide Unicode", "\x00\n\t\r\nEscape codes", '"\'"Quotes', "", None, b"\x00\x01\xFFBinary data", b"", CBase58Data.from_bytes(b"\x00\x01\xFF", 42), P2SHBitcoinAddress.from_bytes(b"\x00\x01\xFF"), P2PKHBitcoinAddress.from_bytes(b"\x00\x01\xFF"), CMutableTxIn(COutPoint(b"\x00" * 16 + b"\xFF" * 16, 42), CScript(b"\x00\x01\xFF"), 42), CMutableTxOut(42, CScript(b"\x00\x01\xFF")), CMutableTransaction( [ CMutableTxIn(COutPoint(b"\x00" * 32, 42), CScript(b"\x00\x01\xFF"), 42), CMutableTxIn(COutPoint(b"\xFF" * 32, 42), CScript(b"\xFF\x01\x00"), 43), ], [CMutableTxOut(42, CScript(b"\x00\x01\xFF")), CMutableTxOut(43, CScript(b"\xFF\x01\x00"))], 42, 3, ), [1, b"\x00\x01\xFF", "List Test"], {"a": 1, "key": b"\xFF\x01\x00", 1: "Dictionary Test"}, [{3: [0, 1, 2]}, [[b"\xFFRecursion Test"]]], ] for value in VALUES: self.assertEqual(from_json(to_json(value)), value)
def coerce_address(v): addr_data = CBase58Data(v) if len(v) >= 26 and len(v) <= 35: return addr_data
def test_CBase58Data_version(self): self.assertEqual(from_json(to_json(CBase58Data.from_bytes(b"\x00\x01\xFF", 42))).nVersion, 42)
def validate_address_list_arg(settings): for a in settings.addresses: CBase58Data(a)
def decryptBIP0038(privkey, password): return str(CBase58Data(Bip38.decrypt(privkey, password), 128))
def test_CBase58Data_version(self): self.assertEqual( from_json(to_json(CBase58Data.from_bytes(b'\x00\x01\xFF', 42))).nVersion, 42)
def copy_h160(x): h160 = CBase58Data(x).encode('hex') QApplication.clipboard().setText(h160)
def encode_address(hash160, addr_version=0): """Encode hash160 into an address.""" assert len(hash160) == 20, 'Invalid RIPEMD-160 hash' addr = CBase58Data.from_bytes(hash160, addr_version) return addr
def is_address(x): try: data = CBase58Data(x) except Exception: return False return len(x) >= 26 and len(x) <= 35
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: