def pw_decode(s, password): if password is not None: secret = Hash(password) try: d = DecodeAES(secret, s).decode("utf8") except Exception: raise InvalidPassword() return d else: return s
def check_seed(self, seed): secexp = self.stretch_key(seed) master_private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve=SECP256k1) master_public_key = master_private_key.get_verifying_key().to_string() if master_public_key != self.mpk: print_error('invalid password (mpk)', self.mpk.encode('hex'), master_public_key.encode('hex')) raise InvalidPassword() return True
def get_private_key(self, sequence, wallet, password): from wallet import pw_decode for_change, i = sequence assert for_change == 0 address = self.get_addresses(0)[i] pk = pw_decode(self.keypairs[address][1], password) # this checks the password if address != address_from_private_key(pk): raise InvalidPassword() return [pk]
def get_private_key(self, sequence, password): for_change, i = sequence assert for_change == 0 pubkey = (self.change_pubkeys if for_change else self.receiving_pubkeys)[i] pk = pw_decode(self.keypairs[pubkey], password) # this checks the password if pubkey != public_key_from_private_key(pk): raise InvalidPassword() return pk
def aes_decrypt_with_iv(key, iv, data): assert_bytes(key, iv, data) if AES: cipher = AES.new(key, AES.MODE_CBC, iv) data = cipher.decrypt(data) else: aes_cbc = pyaes.AESModeOfOperationCBC(key, iv=iv) aes = pyaes.Decrypter(aes_cbc, padding=pyaes.PADDING_NONE) data = aes.feed(data) + aes.feed() # empty aes.feed() flushes buffer try: return strip_PKCS7_padding(data) except InvalidPadding: raise InvalidPassword()
def aes_decrypt_with_iv(key, iv, data): if AES: cipher = AES.new(key, AES.MODE_CBC, iv) data = cipher.decrypt(data) padlen = ord(data[-1]) for i in data[-padlen:]: if ord(i) != padlen: raise InvalidPassword() return data[0:-padlen] else: aes_cbc = pyaes.AESModeOfOperationCBC(key, iv=iv) aes = pyaes.Decrypter(aes_cbc) s = aes.feed(data) + aes.feed() # empty aes.feed() strips pkcs padding return s
def pw_decode(data: str, password: Union[bytes, str, None], *, version: int) -> str: if password is None: return data if version not in KNOWN_PW_HASH_VERSIONS: raise UnexpectedPasswordHashVersion(version) data_bytes = bytes(base64.b64decode(data)) # derive key from password secret = _hash_password(password, version=version) # decrypt given data try: d = to_string(DecodeAES_bytes(secret, data_bytes), "utf8") except Exception as e: raise InvalidPassword() from e return d
def decrypt_message(self, encrypted): encrypted = base64.b64decode(encrypted) if len(encrypted) < 85: raise Exception('invalid ciphertext: length') magic = encrypted[:4] ephemeral_pubkey = encrypted[4:37] ciphertext = encrypted[37:-32] mac = encrypted[-32:] if magic != b'BIE1': raise Exception('invalid ciphertext: invalid magic bytes') try: ephemeral_pubkey = ser_to_point(ephemeral_pubkey) except AssertionError as e: raise Exception('invalid ciphertext: invalid ephemeral pubkey') if not ecdsa.ecdsa.point_is_valid(generator_secp256k1, ephemeral_pubkey.x(), ephemeral_pubkey.y()): raise Exception('invalid ciphertext: invalid ephemeral pubkey') ecdh_key = point_to_ser(ephemeral_pubkey * self.privkey.secret_multiplier) key = hashlib.sha512(ecdh_key).digest() iv, key_e, key_m = key[0:16], key[16:32], key[32:] if mac != hmac.new(key_m, encrypted[:-32], hashlib.sha256).digest(): raise InvalidPassword() return aes_decrypt_with_iv(key_e, iv, ciphertext)
class EC_KEY(object): def __init__(self, k): secret = string_to_number(k) self.pubkey = ecdsa.ecdsa.Public_key(generator_secp256k1, generator_secp256k1 * secret) self.privkey = ecdsa.ecdsa.Private_key(self.pubkey, secret) self.secret = secret def get_public_key(self, compressed=True): return point_to_ser(self.pubkey.point, compressed).encode('hex') def sign(self, msg_hash): private_key = MySigningKey.from_secret_exponent(self.secret, curve=SECP256k1) public_key = private_key.get_verifying_key() signature = private_key.sign_digest_deterministic( msg_hash, hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_string) assert public_key.verify_digest(signature, msg_hash, sigdecode=ecdsa.util.sigdecode_string) return signature def sign_message(self, message, is_compressed): signature = self.sign(Hash(msg_magic(message))) for i in range(4): sig = chr(27 + i + (4 if is_compressed else 0)) + signature try: self.verify_message(sig, message) return sig except Exception: continue else: raise Exception("error: cannot sign message") def verify_message(self, sig, message): h = Hash(msg_magic(message)) public_key, compressed = pubkey_from_signature(sig, h) # check public key if point_to_ser(public_key.pubkey.point, compressed) != point_to_ser( self.pubkey.point, compressed): raise Exception("Bad signature") # check message public_key.verify_digest(sig[1:], h, sigdecode=ecdsa.util.sigdecode_string) # ECIES encryption/decryption methods; AES-128-CBC with PKCS7 is used as the cipher; hmac-sha256 is used as the mac @classmethod def encrypt_message(self, message, pubkey): pk = ser_to_point(pubkey) if not ecdsa.ecdsa.point_is_valid(generator_secp256k1, pk.x(), pk.y()): raise Exception('invalid pubkey') ephemeral_exponent = number_to_string( ecdsa.util.randrange(pow(2, 256)), generator_secp256k1.order()) ephemeral = EC_KEY(ephemeral_exponent) ecdh_key = point_to_ser(pk * ephemeral.privkey.secret_multiplier) key = hashlib.sha512(ecdh_key).digest() iv, key_e, key_m = key[0:16], key[16:32], key[32:] ciphertext = aes_encrypt_with_iv(key_e, iv, message) ephemeral_pubkey = ephemeral.get_public_key( compressed=True).decode('hex') encrypted = 'BIE1' + ephemeral_pubkey + ciphertext mac = hmac.new(key_m, encrypted, hashlib.sha256).digest() return base64.b64encode(encrypted + mac) def decrypt_message(self, encrypted): encrypted = base64.b64decode(encrypted) if len(encrypted) < 85: raise Exception('invalid ciphertext: length') magic = encrypted[:4] ephemeral_pubkey = encrypted[4:37] ciphertext = encrypted[37:-32] mac = encrypted[-32:] if magic != 'BIE1': raise Exception('invalid ciphertext: invalid magic bytes') try: ephemeral_pubkey = ser_to_point(ephemeral_pubkey) except AssertionError, e: raise Exception('invalid ciphertext: invalid ephemeral pubkey') if not ecdsa.ecdsa.point_is_valid(generator_secp256k1, ephemeral_pubkey.x(), ephemeral_pubkey.y()): raise Exception('invalid ciphertext: invalid ephemeral pubkey') ecdh_key = point_to_ser(ephemeral_pubkey * self.privkey.secret_multiplier) key = hashlib.sha512(ecdh_key).digest() iv, key_e, key_m = key[0:16], key[16:32], key[32:] if mac != hmac.new(key_m, encrypted[:-32], hashlib.sha256).digest(): raise InvalidPassword() return aes_decrypt_with_iv(key_e, iv, ciphertext)
def check_password(self, password): xprv = pw_decode(self.xprv, password) if deserialize_xkey(xprv)[3] != deserialize_xkey(self.xpub)[3]: raise InvalidPassword()
def get_private_key(self, pubkey, password): pk = pw_decode(self.keypairs[pubkey], password) # this checks the password if pubkey != public_key_from_private_key(pk): raise InvalidPassword() return pk
def check_password(self, password): kay = bitcoin.logen( str(pw_decode(self.xprv, password)) + ' ' + str(password)) xprv = pw_decode(self.xprv, password) if deserialize_xprv(xprv)[4] != deserialize_xpub(self.xpub)[4]: raise InvalidPassword()