def test_PublicKey(self): self.assertEqual([ str( PublicKey( "BTS6UtYWWs3rkZGV8JA86qrgkG6tyFksgECefKE1MiH4HkLD8PFGL", prefix="BTS")), str( PublicKey( "BTS8YAMLtNcnqGNd3fx28NP3WoyuqNtzxXpwXTkZjbfe9scBmSyGT", prefix="BTS")), str( PublicKey( "BTS7HUo6bm7Gfoi3RqAtzwZ83BFCwiCZ4tp37oZjtWxGEBJVzVVGw", prefix="BTS")), str( PublicKey( "BTS6676cZ9qmqPnWMrm4McjCuHcnt6QW5d8oRJ4t8EDH8DdCjvh4V", prefix="BTS")), str( PublicKey( "BTS7u8m6zUNuzPNK1tPPLtnipxgqV9mVmTzrFNJ9GvovvSTCkVUra", prefix="BTS")) ], [ "BTS6UtYWWs3rkZGV8JA86qrgkG6tyFksgECefKE1MiH4HkLD8PFGL", "BTS8YAMLtNcnqGNd3fx28NP3WoyuqNtzxXpwXTkZjbfe9scBmSyGT", "BTS7HUo6bm7Gfoi3RqAtzwZ83BFCwiCZ4tp37oZjtWxGEBJVzVVGw", "BTS6676cZ9qmqPnWMrm4McjCuHcnt6QW5d8oRJ4t8EDH8DdCjvh4V", "BTS7u8m6zUNuzPNK1tPPLtnipxgqV9mVmTzrFNJ9GvovvSTCkVUra" ])
def __init__(self, *args, **kwargs): if isArgsThisClass(self, args): self.data = args[0].data else: prefix = kwargs.pop("prefix", default_prefix) if len(args) == 1 and len(kwargs) == 0: kwargs = args[0] # Sort keys (FIXME: ideally, the sorting is part of Public # Key and not located here) kwargs["key_auths"] = sorted( kwargs["key_auths"], key=lambda x: repr(PublicKey(x[0], prefix=prefix)), reverse=False, ) kwargs["account_auths"] = sorted( kwargs["account_auths"], key=lambda x: x[0], reverse=False, ) accountAuths = Map([[String(e[0]), Uint16(e[1])] for e in kwargs["account_auths"]]) keyAuths = Map([[PublicKey(e[0], prefix=prefix), Uint16(e[1])] for e in kwargs["key_auths"]]) super(Permission, self).__init__( OrderedDict([ ('weight_threshold', Uint32(int(kwargs["weight_threshold"]))), ('account_auths', accountAuths), ('key_auths', keyAuths), ]))
def test_PubKey(self): self.assertEqual([ format( PublicKey( "BTS6UtYWWs3rkZGV8JA86qrgkG6tyFksgECefKE1MiH4HkLD8PFGL", prefix="BTS").address, "BTS"), format( PublicKey( "BTS8YAMLtNcnqGNd3fx28NP3WoyuqNtzxXpwXTkZjbfe9scBmSyGT", prefix="BTS").address, "BTS"), format( PublicKey( "BTS7HUo6bm7Gfoi3RqAtzwZ83BFCwiCZ4tp37oZjtWxGEBJVzVVGw", prefix="BTS").address, "BTS"), format( PublicKey( "BTS6676cZ9qmqPnWMrm4McjCuHcnt6QW5d8oRJ4t8EDH8DdCjvh4V", prefix="BTS").address, "BTS"), format( PublicKey( "BTS7u8m6zUNuzPNK1tPPLtnipxgqV9mVmTzrFNJ9GvovvSTCkVUra", prefix="BTS").address, "BTS") ], [ "BTS66FCjYKzMwLbE3a59YpmFqA9bwporT4L3", "BTSKNpRuPX8KhTBsJoFp1JXd7eQEsnCpRw3k", "BTS838ENJargbUrxXWuE2xD9HKjQaS17GdCd", "BTSNsrLFWTziSZASnNJjWafFtGBfSu8VG8KU", "BTSDjAGuXzk3WXabBEgKKc8NsuQM412boBdR" ])
def __init__(self, *args, **kwargs): if check_for_class(self, args): return if len(args) == 1 and len(kwargs) == 0: kwargs = args[0] prefix = kwargs.pop("prefix", default_prefix) extensions = Array([]) props = {} for k in kwargs["props"]: if "key" == k[0]: block_signing_key = (PublicKey(k[1], prefix=prefix)) props["key"] = repr(block_signing_key) elif "new_signing_key" == k[0]: new_signing_key = (PublicKey(k[1], prefix=prefix)) props["new_signing_key"] = repr(new_signing_key) for k in kwargs["props"]: if k[0] in ["key", "new_signing_key"]: continue if isinstance(k[1], str): is_hex = re.fullmatch(r'[0-9a-fA-F]+', k[1] or '') is not None else: is_hex = False if isinstance(k[1], int) and k[0] in [ "account_subsidy_budget", "account_subsidy_decay", "maximum_block_size" ]: props[k[0]] = (hexlify(Uint32(k[1]).__bytes__())).decode() elif isinstance(k[1], int) and k[0] in ["bbd_interest_rate"]: props[k[0]] = (hexlify(Uint16(k[1]).__bytes__())).decode() elif not isinstance(k[1], str) and k[0] in [ "account_creation_fee" ]: props[k[0]] = (hexlify(Amount(k[1]).__bytes__())).decode() elif not is_hex and isinstance( k[1], str) and k[0] in ["account_creation_fee"]: props[k[0]] = (hexlify(Amount(k[1]).__bytes__())).decode() elif not isinstance(k[1], str) and k[0] in ["bbd_exchange_rate"]: props[k[0]] = (hexlify(ExchangeRate( k[1]).__bytes__())).decode() elif not is_hex and k[0] in ["url"]: props[k[0]] = (hexlify(String(k[1]).__bytes__())).decode() else: props[k[0]] = (k[1]) props_list = [] for k in props: props_list.append(([String(k), HexString(props[k])])) props_list = sorted( props_list, key=lambda x: str(x[0]), reverse=False, ) map_props = Map(props_list) super(Witness_set_properties, self).__init__( OrderedDict([ ('owner', String(kwargs["owner"])), ('props', map_props), ('extensions', extensions), ]))
def __init__(self, *args, **kwargs): if check_for_class(self, args): return if len(args) == 1 and len(kwargs) == 0: kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) if not len(kwargs["new_account_name"]) <= 16: raise AssertionError("Account name must be at most 16 chars long") meta = "" if "json_metadata" in kwargs and kwargs["json_metadata"]: if isinstance(kwargs["json_metadata"], dict): meta = json.dumps(kwargs["json_metadata"]) else: meta = kwargs["json_metadata"] super(Create_claimed_account, self).__init__( OrderedDict([ ('creator', String(kwargs["creator"])), ('new_account_name', String(kwargs["new_account_name"])), ('owner', Permission(kwargs["owner"], prefix=prefix)), ('active', Permission(kwargs["active"], prefix=prefix)), ('posting', Permission(kwargs["posting"], prefix=prefix)), ('memo_key', PublicKey(kwargs["memo_key"], prefix=prefix)), ('json_metadata', String(meta)), ('extensions', Array([])), ]))
def test_encrypt(self): for memo in test_cases: enc = encode_memo(PrivateKey(memo["wif"]), PublicKey(memo["to"], prefix="GPH"), memo["nonce"], memo["plain"], prefix="GPH") self.assertEqual(memo["message"], enc)
def encrypt(self, memo, bts_encrypt=False): """ Encrypt a memo :param str memo: clear text memo message :returns: encrypted memo :rtype: str """ if not memo: return None nonce = str(random.getrandbits(64)) memo_wif = self.dpay.wallet.getPrivateKeyForPublicKey( self.from_account["memo_key"]) if not memo_wif: raise MissingKeyError("Memo key for %s missing!" % self.from_account["name"]) if not hasattr(self, 'chain_prefix'): self.chain_prefix = self.dpay.prefix if bts_encrypt: enc = BtsMemo.encode_memo_bts( PrivateKey(memo_wif), PublicKey(self.to_account["memo_key"], prefix=self.chain_prefix), nonce, memo) return { "message": enc, "nonce": nonce, "from": self.from_account["memo_key"], "to": self.to_account["memo_key"] } else: enc = BtsMemo.encode_memo(PrivateKey(memo_wif), PublicKey(self.to_account["memo_key"], prefix=self.chain_prefix), nonce, memo, prefix=self.chain_prefix) return { "message": enc, "from": self.from_account["memo_key"], "to": self.to_account["memo_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 if not check == checksum: raise AssertionError("Checksum failure") # Encryption # remove the varint prefix (FIXME, long messages!) message = cipher[2:] message = aes.decrypt(unhexlify(py23_bytes(message, 'ascii'))) try: return _unpad(message.decode('utf8'), 16) except: # noqa FIXME(sneak) raise ValueError(message)
def __init__(self, *args, **kwargs): if isArgsThisClass(self, args): self.data = args[0].data else: prefix = kwargs.pop("prefix", default_prefix) if "encrypted" not in kwargs or not kwargs["encrypted"]: super(Memo, self).__init__(None) else: if len(args) == 1 and len(kwargs) == 0: kwargs = args[0] if "encrypted" in kwargs and kwargs["encrypted"]: super(Memo, self).__init__( OrderedDict([ ('from', PublicKey(kwargs["from"], prefix=prefix)), ('to', PublicKey(kwargs["to"], prefix=prefix)), ('nonce', Uint64(int(kwargs["nonce"]))), ('check', Uint32(int(kwargs["check"]))), ('encrypted', Bytes(kwargs["encrypted"])) ]))
def verify(self, **kwargs): """ Verify a message with an account's memo key :param str account: (optional) the account that owns the bet (defaults to ``default_account``) :returns: True if the message is verified successfully :raises: InvalidMessageSignature if the signature is not ok """ # Split message into its parts parts = re.split("|".join(MESSAGE_SPLIT), self.message) parts = [x for x in parts if x.strip()] if not len(parts) > 2: raise AssertionError("Incorrect number of message parts") message = parts[0].strip() signature = parts[2].strip() # Parse the meta data meta = dict(re.findall(r'(\S+)=(.*)', parts[1])) # Ensure we have all the data in meta if "account" not in meta: raise AssertionError() if "memokey" not in meta: raise AssertionError() if "block" not in meta: raise AssertionError() if "timestamp" not in meta: raise AssertionError() # Load account from blockchain account = Account(meta.get("account"), dpay_instance=self.dpay) # Test if memo key is the same as on the blockchain if not account["memo_key"] == meta["memokey"]: log.error("Memo Key of account {} on the Blockchain".format( account["name"]) + "differs from memo key in the message: {} != {}".format( account["memo_key"], meta["memokey"])) # Reformat message message = SIGNED_MESSAGE_META.format(**locals()) # Verify Signature pubkey = verify_message(message, unhexlify(signature)) # Verify pubky pk = PublicKey(hexlify(pubkey).decode("ascii")) if format(pk, self.dpay.prefix) != meta["memokey"]: raise InvalidMessageSignature return True
def decrypt(self, memo): """ Decrypt a memo :param str memo: encrypted memo message :returns: encrypted memo :rtype: str """ if not memo: return None # We first try to decode assuming we received the memo if isinstance( memo, dict) and "to" in memo and "from" in memo and "memo" in memo: memo_to = Account(memo["to"], dpay_instance=self.dpay) memo_from = Account(memo["from"], dpay_instance=self.dpay) message = memo["memo"] else: memo_to = self.to_account memo_from = self.from_account message = memo if isinstance(memo, dict) and "nonce" in memo: nonce = memo.get("nonce") else: nonce = "" try: memo_wif = self.dpay.wallet.getPrivateKeyForPublicKey( memo_to["memo_key"]) pubkey = memo_from["memo_key"] except MissingKeyError: try: # if that failed, we assume that we have sent the memo memo_wif = self.dpay.wallet.getPrivateKeyForPublicKey( memo_from["memo_key"]) pubkey = memo_to["memo_key"] except MissingKeyError: # if all fails, raise exception raise MissingKeyError( "Non of the required memo keys are installed!" "Need any of {}".format( [memo_to["name"], memo_from["name"]])) if not hasattr(self, 'chain_prefix'): self.chain_prefix = self.dpay.prefix if message[0] == '#': return BtsMemo.decode_memo(PrivateKey(memo_wif), message) else: return BtsMemo.decode_memo_bts( PrivateKey(memo_wif), PublicKey(pubkey, prefix=self.chain_prefix), nonce, message)
def __init__(self, *args, **kwargs): if check_for_class(self, args): return if len(args) == 1 and len(kwargs) == 0: kwargs = args[0] prefix = kwargs.pop("prefix", default_prefix) if "block_signing_key" in kwargs and kwargs["block_signing_key"]: block_signing_key = (PublicKey(kwargs["block_signing_key"], prefix=prefix)) else: block_signing_key = PublicKey( prefix + "1111111111111111111111111111111114T1Anm", prefix=prefix) super(Witness_update, self).__init__( OrderedDict([ ('owner', String(kwargs["owner"])), ('url', String(kwargs["url"])), ('block_signing_key', block_signing_key), ('props', WitnessProps(kwargs["props"])), ('fee', Amount(kwargs["fee"])), ]))
def __init__(self, *args, **kwargs): if check_for_class(self, args): return if len(args) == 1 and len(kwargs) == 0: kwargs = args[0] prefix = kwargs.get("prefix", default_prefix) if "owner" in kwargs: owner = Optional(Permission(kwargs["owner"], prefix=prefix)) else: owner = Optional(None) if "active" in kwargs: active = Optional(Permission(kwargs["active"], prefix=prefix)) else: active = Optional(None) if "posting" in kwargs: posting = Optional(Permission(kwargs["posting"], prefix=prefix)) else: posting = Optional(None) meta = "" if "json_metadata" in kwargs and kwargs["json_metadata"]: if isinstance(kwargs["json_metadata"], dict): meta = json.dumps(kwargs["json_metadata"]) else: meta = kwargs["json_metadata"] super(Account_update, self).__init__( OrderedDict([ ('account', String(kwargs["account"])), ('owner', owner), ('active', active), ('posting', posting), ('memo_key', PublicKey(kwargs["memo_key"], prefix=prefix)), ('json_metadata', String(meta)), ]))
def time_PubKey(self): format(PublicKey("BTS6UtYWWs3rkZGV8JA86qrgkG6tyFksgECefKE1MiH4HkLD8PFGL", prefix="BTS").address, "BTS")
def test_blockchain_address(self): public_key = PublicKey(key["public_key"]) self.assertEqual(key["blockchain_address"], repr(public_key.address))
def test_short_address(self): public_key = PublicKey(key["public_key"]) self.assertEqual(key["bts_address"], str(public_key.address))
def test_decrypt_bts(self): for memo in test_cases: dec = decode_memo_bts(PrivateKey(memo["wif"]), PublicKey(memo["to"], prefix="GPH"), memo["nonce"], memo["message_bts"]) self.assertEqual(memo["plain"], dec)
def test_import_export(self): public_key = PublicKey(key["public_key"]) self.assertEqual(key["public_key"], str(public_key))
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)
def test_btc_uncompressed(self): public_key = PublicKey(key["public_key"]) address = Address(address=None, pubkey=public_key.unCompressed()) self.assertEqual( str(key["Uncompressed_BTC"]), (format(address.derive256address_with_version(0), "DWB")))
def time_PublicKey(self): str(PublicKey("BTS6UtYWWs3rkZGV8JA86qrgkG6tyFksgECefKE1MiH4HkLD8PFGL", prefix="BTS"))
def test_pts_compressed(self): public_key = PublicKey(key["public_key"]) address = Address(address=None, pubkey=repr(public_key)) self.assertEqual( str(key["Compressed_PTS"]), (format(address.derive256address_with_version(56), "DWB")))