def test_shared_secrets_equal(self): wifs = cycle([x[0] for x in test_shared_secrets]) for i in range(len(test_shared_secrets)): sender_private_key = PrivateKey(next(wifs)) sender_public_key = sender_private_key.pubkey receiver_private_key = PrivateKey(next(wifs)) receiver_public_key = receiver_private_key.pubkey self.assertEqual( get_shared_secret(sender_private_key, receiver_public_key), get_shared_secret(receiver_private_key, sender_public_key), )
def encode_memo(priv, pub, nonce, message, **kwargs): """ Encode a message with a shared secret between Alice and Bob. :param PrivateKey priv: Private Key (of Alice) :param PublicKey pub: Public Key (of Bob) :param int nonce: Random nonce :param str message: Memo message :return: Encrypted message :rtype: hex """ shared_secret = get_shared_secret(priv, pub) aes, check = init_aes(shared_secret, nonce) raw = bytes(message, "utf8") " Padding " bs = 16 if len(raw) % bs: raw = _pad(raw, bs) " Encryption " cipher = hexlify(aes.encrypt(raw)).decode("ascii") prefix = kwargs.pop("prefix") op = { "from": format(priv.pubkey, prefix), "to": format(pub, prefix), "nonce": nonce, "check": check, "encrypted": cipher, } tx = Memo(**op) return "#" + base58encode(hexlify(bytes(tx)).decode("ascii"))
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 Exception: raise ValueError(message)
def test_shared_secret(self): for s in test_shared_secrets: priv = PrivateKey(s[0]) pub = PublicKey(s[1], prefix="GPH") shared_secret = get_shared_secret(priv, pub) self.assertEqual(s[2], shared_secret)