def test_base58decode(self): self.assertEqual([base58decode('5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'), base58decode('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss'), base58decode('5KfazyjBBtR2YeHjNqX5D6MXvqTUd2iZmWusrdDSUqoykTyWQZB')], ['800c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d507a5b8d', '80e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8555c5bbb26', '80f3a375e00cc5147f30bee97bb5d54b31a12eee148a1ac31ac9edc4ecd13bc1f80cc8148e'])
def involved_keys(message): " decode structure " raw = base58decode(message[1:]) from_key = PublicKey(raw[:66]) raw = raw[66:] to_key = PublicKey(raw[:66]) return [from_key, to_key]
def decode_memo(priv, message): """ Decode a message with a shared secret between Alice and Bob :param PrivateKey priv: Private Key (of Bob) :param base58encoded message: Encrypted Memo message :return: Decrypted message :rtype: str :raise ValueError: if message cannot be decoded as valid UTF-8 string """ " decode structure " raw = base58decode(message[1:]) from_key = PublicKey(raw[:66]) raw = raw[66:] to_key = PublicKey(raw[:66]) raw = raw[66:] nonce = str(struct.unpack_from("<Q", unhexlify(raw[:16]))[0]) raw = raw[16:] check = struct.unpack_from("<I", unhexlify(raw[:8]))[0] raw = raw[8:] cipher = raw if repr(to_key) == repr(priv.pubkey): shared_secret = get_shared_secret(priv, from_key) elif repr(from_key) == repr(priv.pubkey): shared_secret = get_shared_secret(priv, to_key) else: raise ValueError("Incorrect PrivateKey") " Init encryption " aes, checksum = init_aes(shared_secret, nonce) " Check " assert check == checksum, "Checksum failure" " Encryption " # remove the varint prefix (FIXME, long messages!) message = cipher[2:] message = aes.decrypt(unhexlify(bytes(message, 'ascii'))) try: return _unpad(message.decode('utf8'), 16) except: raise ValueError(message)
def decrypt(encrypted_privkey, passphrase): """BIP0038 non-ec-multiply decryption. Returns WIF privkey. :param Base58 encrypted_privkey: Private key :param str passphrase: UTF-8 encoded passphrase for decryption :return: BIP0038 non-ec-multiply decrypted key :rtype: Base58 :raises SaltException: if checksum verification failed (e.g. wrong password) """ d = unhexlify(base58decode(encrypted_privkey)) d = d[2:] # remove trailing 0x01 and 0x42 flagbyte = d[0:1] # get flag byte d = d[1:] # get payload assert flagbyte == b'\xc0', "Flagbyte has to be 0xc0" salt = d[0:4] d = d[4:-4] if SCRYPT_MODULE == "scrypt": key = scrypt.hash(passphrase, salt, 16384, 8, 8) elif SCRYPT_MODULE == "pylibscrypt": key = scrypt.scrypt(bytes(passphrase, "utf-8"), salt, 16384, 8, 8) else: raise ValueError("No scrypt module loaded") derivedhalf1 = key[0:32] derivedhalf2 = key[32:64] encryptedhalf1 = d[0:16] encryptedhalf2 = d[16:32] aes = AES.new(derivedhalf2) decryptedhalf2 = aes.decrypt(encryptedhalf2) decryptedhalf1 = aes.decrypt(encryptedhalf1) privraw = decryptedhalf1 + decryptedhalf2 privraw = ('%064x' % (int(hexlify(privraw), 16) ^ int(hexlify(derivedhalf1), 16))) wif = Base58(privraw) """ Verify Salt """ privkey = PrivateKey(format(wif, "wif")) addr = format(privkey.uncompressed.address, "BTC") a = bytes(addr, 'ascii') saltverify = hashlib.sha256(hashlib.sha256(a).digest()).digest()[0:4] if saltverify != salt: raise SaltException('checksum verification failed! Password may be incorrect.') return wif