Example #1
0
 def test_pts_uncompressed(self):
     public_key = PublicKey(key["public_key"])
     address = Address.from_pubkey(public_key.uncompressed(),
                                   compressed=False,
                                   version=56)
     self.assertEqual(str(key["Uncompressed_PTS"]),
                      (format(address, "STM")))
Example #2
0
 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"
     ])
Example #3
0
 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"
     ])
Example #4
0
    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),
                ]))
Example #5
0
    def test_transfer_2of2_offline(self):
        # Send a 2 of 2 transaction from beem5 which needs beem4's cosign to send
        # funds but sign the transaction with beem5's key and then serialize the transaction
        # and deserialize the transaction.  After that, sign with beem4's key.
        steem = self.bts
        steem.nobroadcast = False
        steem.wallet.unlock("123")
        # steem.wallet.removeAccount("beem4")
        steem.wallet.removePrivateKeyFromPublicKey(str(PublicKey(self.active_private_key_of_beem4, prefix=core_unit)))

        tx = TransactionBuilder(use_condenser_api=True, steem_instance=steem)
        tx.appendOps(Transfer(**{"from": 'beem5',
                                 "to": 'beem',
                                 "amount": Amount("0.01 STEEM", steem_instance=steem),
                                 "memo": '2 of 2 serialized/deserialized transaction'}))

        tx.appendSigner("beem5", "active")
        tx.addSigningInformation("beem5", "active")
        tx.sign()
        tx.clearWifs()
        self.assertEqual(len(tx['signatures']), 1)
        # steem.wallet.removeAccount("beem5")
        steem.wallet.removePrivateKeyFromPublicKey(str(PublicKey(self.active_private_key_of_beem5, prefix=core_unit)))
        steem.wallet.addPrivateKey(self.active_private_key_of_beem4)
        tx.appendMissingSignatures()
        tx.sign(reconstruct_tx=False)
        self.assertEqual(len(tx['signatures']), 2)
        tx.broadcast()
        steem.nobroadcast = True
        steem.wallet.addPrivateKey(self.active_private_key_of_beem5)
Example #6
0
    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)
        if 'prefix' not in kwargs['props']:
            kwargs['props']['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"], prefix=prefix)),
            ]))
def validate_hivekeychain_ans(ans):
    """ takes in the answer from hivekeychain and checks everything """
    """ https://bit.ly/keychainpython """

    acc_name = ans['data']['username']
    pubkey = PublicKey(ans['publicKey'])
    enc_msg = ans['data']['message']
    signature = ans['result']

    msgkey = verify_message(enc_msg, unhexlify(signature))
    pk = PublicKey(hexlify(msgkey).decode("ascii"))
    if str(pk) == str(pubkey):
        app.logger.info(f'{acc_name} SUCCESS: signature matches given pubkey')
        acc = Account(acc_name, lazy=True)
        match = False, 0
        for key in acc['posting']['key_auths']:
            match = match or ans['publicKey'] in key
        if match:
            app.logger.info(f'{acc_name} Matches public key from Hive')
            mtime = json.loads(enc_msg)['timestamp']
            time_since = time.time() - mtime
            if time_since < 30:
                app.logger.info(f'{acc_name} SUCCESS: in {time_since} seconds')
                return True, time_since
            else:
                app.logger.warning(f'{acc_name} ERROR: answer took too long.')
    else:
        app.logger.warning(
            f'{acc_name} ERROR: message was signed with a different key')
        return False, 0
Example #8
0
    def encrypt(self,
                memo,
                bts_encrypt=False,
                return_enc_memo_only=False,
                nonce=None):
        """ Encrypt a memo

            :param str memo: clear text memo message
            :param bool return_enc_memo_only: When True, only the encoded memo is returned
            :param str nonce: when not set, a random string is generated and used
            :returns: encrypted memo
            :rtype: dict
        """
        if not memo:
            return None
        if nonce is None:
            nonce = str(random.getrandbits(64))
        if isinstance(self.from_account, Account):
            memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey(
                self.from_account["memo_key"])
            memo_wif = PrivateKey(memo_wif)
        else:
            memo_wif = self.from_account
        if isinstance(self.to_account, Account):
            pubkey = self.to_account["memo_key"]
        else:
            pubkey = self.to_account
        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.blockchain.prefix

        if bts_encrypt:
            enc = BtsMemo.encode_memo_bts(
                PrivateKey(memo_wif),
                PublicKey(pubkey, prefix=self.chain_prefix), nonce, memo)

            return {
                "message": enc,
                "nonce": nonce,
                "from": str(PrivateKey(memo_wif).pubkey),
                "to": str(pubkey)
            }
        else:
            enc = BtsMemo.encode_memo(PrivateKey(memo_wif),
                                      PublicKey(pubkey,
                                                prefix=self.chain_prefix),
                                      nonce,
                                      memo,
                                      prefix=self.chain_prefix)
            if return_enc_memo_only:
                return enc
            return {
                "message": enc,
                "from": str(PrivateKey(memo_wif).pubkey),
                "to": str(pubkey)
            }
Example #9
0
    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) and PY3:
                is_hex = re.fullmatch(r'[0-9a-fA-F]+', k[1] or '') is not None
            elif isinstance(k[1], str) and PY2:
                is_hex = re.match(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 ["sbd_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], prefix=prefix).__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], prefix=prefix).__bytes__())).decode()
            elif not isinstance(k[1], str) and k[0] in ["sbd_exchange_rate"]:
                if 'prefix' not in k[1]:
                    k[1]['prefix'] = prefix
                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),
        ]))
Example #10
0
    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.steem.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.steem.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"]
            }
Example #11
0
def extract_memo_data(message):
    """ Returns the stored pubkey keys, nonce, checksum and encrypted message of a memo"""
    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
    return from_key, to_key, nonce, check, cipher
Example #12
0
    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([])),
            ]))
Example #13
0
    def __init__(
        self,
        from_account=None,
        to_account=None,
        blockchain_instance=None,
        **kwargs
    ):
        if blockchain_instance is None:
            if kwargs.get("steem_instance"):
                blockchain_instance = kwargs["steem_instance"]
            elif kwargs.get("hive_instance"):
                blockchain_instance = kwargs["hive_instance"]
        self.blockchain = blockchain_instance or shared_blockchain_instance()

        if to_account and len(to_account) < 51:
            self.to_account = Account(to_account, blockchain_instance=self.blockchain)
        elif to_account and len(to_account) >= 51:
            self.to_account = PublicKey(to_account)
        else:
            self.to_account = None
        if from_account and len(from_account) < 51:
            self.from_account = Account(from_account, blockchain_instance=self.blockchain)
        elif from_account and len(from_account) >= 51:
            self.from_account = PrivateKey(from_account)
        else:
            self.from_account = None
Example #14
0
    def encrypt_binary(self, infile, outfile, buffer_size=2048, nonce=None):
        """ Encrypt a binary file

            :param str infile: input file name
            :param str outfile: output file name
            :param int buffer_size: write buffer size
            :param str nonce: when not set, a random string is generated and used
        """
        if not os.path.exists(infile):
            raise ValueError("%s does not exists!" % infile)

        if nonce is None:
            nonce = str(random.getrandbits(64))
        if isinstance(self.from_account, Account):
            memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey(
                self.from_account["memo_key"]
            )
        else:
            memo_wif = self.from_account
        if isinstance(self.to_account, Account):
            pubkey = self.to_account["memo_key"]
        else:
            pubkey = self.to_account        
        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.blockchain.prefix

        file_size = os.path.getsize(infile)
        priv = PrivateKey(memo_wif)
        pub = PublicKey(
                pubkey,
                prefix=self.chain_prefix
            )
        enc = BtsMemo.encode_memo(
            priv,
            pub,
            nonce,
            "beem/%s" % __version__,
            prefix=self.chain_prefix
        )
        enc = unhexlify(base58decode(enc[1:]))
        shared_secret = BtsMemo.get_shared_secret(priv, pub)
        aes, check = BtsMemo.init_aes(shared_secret, nonce)
        with open(outfile, 'wb') as fout:
            fout.write(struct.pack('<Q', len(enc)))
            fout.write(enc)
            fout.write(struct.pack('<Q', file_size))
            with open(infile, 'rb') as fin:
                while True:
                    data = fin.read(buffer_size)
                    n = len(data)
                    if n == 0:
                        break
                    elif n % 16 != 0:
                        data += b' ' * (16 - n % 16) # <- padded with spaces
                    encd = aes.encrypt(data)
                    fout.write(encd)
Example #15
0
 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)
Example #16
0
    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"], steem_instance=self.steem)
            memo_from = Account(memo["from"], steem_instance=self.steem)
            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.steem.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.steem.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.steem.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
            )
Example #17
0
 def test_decrypt_bugged_padding_bts(self):
     for memo in not_enough_padding:
         dec = decode_memo_bts(
             PrivateKey(memo["wif"]),
             PublicKey(memo["to"], prefix="GPH"),
             memo["nonce"],
             memo["message_bts"],
         )
         self.assertEqual(memo["plain"], dec)
Example #18
0
 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"]))
                 ]))
Example #19
0
 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)
Example #20
0
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)
Example #21
0
    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"),
                          blockchain_instance=self.blockchain)

        # 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.blockchain.prefix) != meta["memokey"]:
            raise InvalidMessageSignature

        return True
Example #22
0
def request_recovery(account):
    """ Request the recovery of ACCOUNT. This action has to be
    initiated/signed by the recovery partner of ACCOUNT.

    """
    acc = Account(account.replace("@", ""))
    if acc.get_owner_history() == []:
        logger.error("The owner key of @%s was not changed within "
                     "the last 30 days - recovering this account is "
                     "not possible!" % (acc['name']))
        return

    # Ask and verify the new pubkey for the to-be-recovered account
    new_owner_key = input("Enter new PUBLIC owner key for @%s: " %
                          (acc['name']))
    # PublicKey call to make sure it is a valid public key
    pk_validity_check = PublicKey(new_owner_key, prefix=acc.blockchain.prefix)
    if format(pk_validity_check, acc.blockchain.prefix) != new_owner_key:
        raise ValueError("Invalid public owner key!")

    # Ask and verify the active key of the recovery account
    recovery_ak = getpass("Enter active key, owner key or master "
                          "password for @%s: " % (acc['recovery_account']))
    recovery_ak = passwordkey_to_key(recovery_ak,
                                     acc['recovery_account'],
                                     "active",
                                     prefix=acc.blockchain.prefix)

    # Assemble the account recovery request operation
    new_owner_authority = {
        'key_auths': [[new_owner_key, 1]],
        'account_auths': [],
        'weight_threshold': 1,
        'prefix': acc.blockchain.prefix
    }
    op = operations.Request_account_recovery(
        **{
            'account_to_recover': acc['name'],
            'recovery_account': acc['recovery_account'],
            'new_owner_authority': new_owner_authority,
            'extensions': [],
            'prefix': acc.blockchain.prefix
        })

    # Send the operation to the blockchain
    tb = TransactionBuilder(blockchain_instance=acc.steem)
    tb.appendOps([op])
    tb.appendWif(recovery_ak)
    tb.sign()
    tx = tb.broadcast()
    logger.debug(tx)
    logger.info("@%s requested account recovery for @%s." %
                (acc['recovery_account'], acc['name']))
Example #23
0
    def test_mnemorickey(self):
        word_list = "news clever spot drama infant detail sword cover color throw foot primary when slender rhythm clog autumn ecology enough bronze math you modify excuse"
        mk = MnemonicKey(word_list)
        mk.set_path_BIP48(role="owner")
        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L2cgypn75kre1s7JUkTK6H7Y656GwDbNnSNZKWSQ2Rnnx6qM11KD")))
        self.assertEqual(str(mk.get_public_key()), str(PublicKey("02821aa2d26c4fd9b735dd1fed148b96fec978eae1440adf79a4bf95e118b2d8f1")))
        
        mk = MnemonicKey(word_list)
        mk.set_path_BIP48(role="owner", key_sequence=5)
        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L5cJSZPcBMBtmuRaK9C48yyXK5JpaH15BsjKLZkmamEWKKx25Kx7")))
        self.assertEqual(str(mk.get_public_key()), str(PublicKey("0309a45aa9add2c7421e0553e23b1800e51d95e525fa4eae1bcc5fb58186e07ed5")))

        mk = MnemonicKey(word_list)
        mk.set_path_BIP48(role="owner", account_sequence=2)
        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L4A95nfp1kyJtUtaTqzMyLQkz6NYSfk4R8pejcgKXQSUtPysiFgv")))
        self.assertEqual(str(mk.get_public_key()), str(PublicKey("02b164dc8819830cd50fca4217ad35fa7371cf29db1bc6a07456cc0090ca8ea8fe")))

        mk = MnemonicKey(word_list)
        mk.set_path_BIP48(role="active")
        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("KygWePihetfhKYCHahcHjMebNSy53HtcXkccYuTn6R8QLydyPUWt")))
        self.assertEqual(str(mk.get_public_key()), str(PublicKey("035c679454155c4c41e8956ecb8e514d37d2d28da91db81c3a22f216a09af94605")))

        mk = MnemonicKey(word_list)
        mk.set_path_BIP48(role="posting")        
        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L53K986B756VbqatsCi3jjPLHCq8Y38AZyXf19w6CcxuGH84Rrhs")))
        self.assertEqual(str(mk.get_public_key()), str(PublicKey("0200e7d987dfd5aaecf822420475ddcbadc8503a99893d50d06f87da48e85a8206")))

        mk = MnemonicKey(word_list)
        mk.set_path_BIP48(role="memo")        
        self.assertEqual(str(mk.get_private_key()), str(PrivateKey("L5GrFqdRsroM1Ym4aMdALQBL7xN9kNMru9JTgtwbHVZ4iGvx1184")))
        self.assertEqual(str(mk.get_public_key()), str(PublicKey("02fa2cdf5a007b01b1911615a4fba9c2a864a1c1ed079d222e5d549d207412c601")))
Example #24
0
 def get_pubkey(self,
                path="48'/13'/0'/0'/0'",
                request_screen_approval=False,
                prefix="STM"):
     from ledgerblue.comm import getDongle
     dongle = getDongle(True)
     apdu = self.build_apdu_pubkey(path, request_screen_approval)
     result = dongle.exchange(py23_bytes(apdu))
     dongle.close()
     offset = 1 + result[0]
     address = result[offset + 1:offset + 1 + result[offset]]
     # public_key = result[1: 1 + result[0]]
     return PublicKey(address.decode(), prefix=prefix)
Example #25
0
    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)
        extensions = Array([])

        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)

        if "memo_key" in kwargs:
            memo_key = Optional(PublicKey(kwargs["memo_key"], prefix=prefix))
        else:
            memo_key = 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"]
        posting_meta = ""
        if "posting_json_metadata" in kwargs and kwargs[
                "posting_json_metadata"]:
            if isinstance(kwargs["posting_json_metadata"], dict):
                posting_meta = json.dumps(kwargs["posting_json_metadata"])
            else:
                posting_meta = kwargs["posting_json_metadata"]

        super(Account_update2, self).__init__(
            OrderedDict([('account', String(kwargs["account"])),
                         ('owner', owner), ('active', active),
                         ('posting', posting), ('memo_key', memo_key),
                         ('json_metadata', String(meta)),
                         ('posting_json_metadata', String(posting_meta)),
                         ('extensions', extensions)]))
Example #26
0
    def decrypt_binary(self, infile, outfile, buffer_size=2048):
        """ Decrypt a binary file

            :param str infile: encrypted binary file
            :param str outfile: output file name
            :param int buffer_size: read buffer size
            :returns: encrypted memo information
            :rtype: dict
        """
        if not os.path.exists(infile):
            raise ValueError("%s does not exists!" % infile)
        if buffer_size % 16 != 0:
            raise ValueError("buffer_size must be dividable by 16")
        with open(infile, 'rb') as fin:
            memo_size = struct.unpack('<Q', fin.read(struct.calcsize('<Q')))[0]
            memo = fin.read(memo_size)
            orig_file_size = struct.unpack('<Q', fin.read(struct.calcsize('<Q')))[0]
        memo = '#' + base58encode(hexlify(memo).decode("ascii"))
        memo_to = self.to_account
        memo_from = self.from_account
        from_key, to_key, nonce, check, cipher = BtsMemo.extract_memo_data(memo)
        if memo_to is None and memo_from is None:
            try:
                memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey(
                    str(to_key)
                )
                pubkey = from_key
            except MissingKeyError:
                try:
                    # if that failed, we assume that we have sent the memo
                    memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey(
                        str(from_key)
                    )
                    pubkey = to_key
                except MissingKeyError:
                    # if all fails, raise exception
                    raise MissingKeyError(
                        "Non of the required memo keys are installed!"
                        "Need any of {}".format(
                        [str(to_key), str(from_key)]))
        elif memo_to is not None and memo_from is not None and isinstance(memo_from, PrivateKey):
            memo_wif = memo_from
            if isinstance(memo_to, Account):
                pubkey = memo_to["memo_key"]
            else:
                pubkey = memo_to
        elif memo_to is not None and memo_from is not None and isinstance(memo_to, PrivateKey):
            memo_wif = memo_to
            if isinstance(memo_from, Account):
                pubkey = memo_from["memo_key"]
            else:
                pubkey = memo_from           
        else:
            
            try:
                memo_wif = self.blockchain.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.blockchain.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.blockchain.prefix
        priv = PrivateKey(memo_wif)
        pubkey = PublicKey(pubkey, prefix=self.chain_prefix)
        beem_version = BtsMemo.decode_memo(
                priv,
                memo
            )
        shared_secret = BtsMemo.get_shared_secret(priv, pubkey)
        # Init encryption
        aes, checksum = BtsMemo.init_aes(shared_secret, nonce)
        with open(infile, 'rb') as fin:
            memo_size = struct.unpack('<Q', fin.read(struct.calcsize('<Q')))[0]
            memo = fin.read(memo_size)
            file_size = struct.unpack('<Q', fin.read(struct.calcsize('<Q')))[0]
            with open(outfile, 'wb') as fout:
                while True:
                    data = fin.read(buffer_size)
                    n = len(data)
                    if n == 0:
                        break
                    decd = aes.decrypt(data)
                    n = len(decd)
                    if file_size > n:
                        fout.write(decd)
                    else:
                        fout.write(decd[:file_size]) # <- remove padding on last block
                    file_size -= n        
        return {
            "file_size": orig_file_size,
            "from_key": str(from_key),
            "to_key": str(to_key),
            "nonce": nonce,
            "beem_version": beem_version
        }
Example #27
0
    def decrypt(self, memo):
        """ Decrypt a memo

            :param str memo: encrypted memo message
            :returns: encrypted memo
            :rtype: str
        """
        if not memo:
            return None
        memo_wif = 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"], blockchain_instance=self.blockchain)
            memo_from = Account(memo["from"], blockchain_instance=self.blockchain)
            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 = ""
        
        if memo_to is None or memo_from is None:
            from_key, to_key, nonce, check, cipher = BtsMemo.extract_memo_data(message)
            try:
                memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey(
                    str(to_key)
                )
                pubkey = from_key
            except MissingKeyError:
                try:
                    # if that failed, we assume that we have sent the memo
                    memo_wif = self.blockchain.wallet.getPrivateKeyForPublicKey(
                        str(from_key)
                    )
                    pubkey = to_key
                except MissingKeyError:
                    # if all fails, raise exception
                    raise MissingKeyError(
                        "Non of the required memo keys are installed!"
                        "Need any of {}".format(
                        [str(to_key), str(from_key)]))
        elif memo_to is not None and memo_from is not None and isinstance(memo_from, PrivateKey):
            memo_wif = memo_from
            pubkey = memo_to
        elif memo_to is not None and memo_from is not None and isinstance(memo_to, PrivateKey):
            memo_wif = memo_to
            pubkey = memo_from           
        else:
            try:
                memo_wif = self.blockchain.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.blockchain.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.blockchain.prefix

        if message[0] == '#' or memo_to is None or memo_from is None:
            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
            )
Example #28
0
    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(self.MESSAGE_SPLIT), self.message)
        parts = [x for x in parts if x.strip()]

        assert len(parts) > 2, "Incorrect number of message parts"

        # Strip away all whitespaces before and after the message
        message = parts[0].strip()
        signature = parts[2].strip()
        # Parse the meta data
        meta = dict(re.findall(r"(\S+)=(.*)", parts[1]))

        log.info("Message is: {}".format(message))
        log.info("Meta is: {}".format(json.dumps(meta)))
        log.info("Signature is: {}".format(signature))

        # Ensure we have all the data in meta
        assert "account" in meta, "No 'account' could be found in meta data"
        assert "memokey" in meta, "No 'memokey' could be found in meta data"
        assert "block" in meta, "No 'block' could be found in meta data"
        assert "timestamp" in meta, "No 'timestamp' could be found in meta data"

        account_name = meta.get("account").strip()
        memo_key = meta["memokey"].strip()

        try:
            PublicKey(memo_key, prefix=self.blockchain.prefix)
        except Exception:
            raise InvalidMemoKeyException(
                "The memo key in the message is invalid")

        # Load account from blockchain
        try:
            account = Account(account_name,
                              blockchain_instance=self.blockchain)
        except AccountDoesNotExistsException:
            raise AccountDoesNotExistsException(
                "Could not find account {}. Are you connected to the right chain?"
                .format(account_name))

        # Test if memo key is the same as on the blockchain
        if not account["memo_key"] == memo_key:
            raise WrongMemoKey("Memo Key of account {} on the Blockchain ".
                               format(account["name"]) +
                               "differs from memo key in the message: {} != {}"
                               .format(account["memo_key"], memo_key))

        # Reformat message
        enc_message = self.SIGNED_MESSAGE_META.format(**locals())

        # Verify Signature
        pubkey = verify_message(enc_message, unhexlify(signature))

        # Verify pubky
        pk = PublicKey(hexlify(pubkey).decode("ascii"),
                       prefix=self.blockchain.prefix)
        if format(pk, self.blockchain.prefix) != memo_key:
            raise InvalidMessageSignature(
                "The signature doesn't match the memo key")

        self.signed_by_account = account
        self.signed_by_name = account["name"]
        self.meta = meta
        self.plain_message = message

        return True
Example #29
0
    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
        """
        if not isinstance(self.message, dict):
            try:
                self.message = json.loads(self.message)
            except Exception:
                raise ValueError("Message must be valid JSON")

        payload = self.message.get("payload")
        assert payload, "Missing payload"
        payload_dict = {k[0]: k[1] for k in zip(payload[::2], payload[1::2])}
        signature = self.message.get("signature")

        account_name = payload_dict.get("from").strip()
        memo_key = payload_dict.get("key").strip()

        assert account_name, "Missing account name 'from'"
        assert memo_key, "missing 'key'"

        try:
            Account(memo_key, prefix=self.blockchain.prefix)
        except Exception:
            raise InvalidMemoKeyException(
                "The memo key in the message is invalid")

        # Load account from blockchain
        try:
            account = Account(account_name,
                              blockchain_instance=self.blockchain)
        except AccountDoesNotExistsException:
            raise AccountDoesNotExistsException(
                "Could not find account {}. Are you connected to the right chain?"
                .format(account_name))

        # Test if memo key is the same as on the blockchain
        if not account["memo_key"] == memo_key:
            raise WrongMemoKey("Memo Key of account {} on the Blockchain ".
                               format(account["name"]) +
                               "differs from memo key in the message: {} != {}"
                               .format(account["memo_key"], memo_key))

        # Ensure payload and signed match
        signed_target = json.dumps(self.message.get("payload"),
                                   separators=(",", ":"))
        signed_actual = self.message.get("signed")
        assert (signed_target == signed_actual
                ), "payload doesn't match signed message: \n{}\n{}".format(
                    signed_target, signed_actual)

        # Reformat message
        enc_message = self.message.get("signed")

        # Verify Signature
        pubkey = verify_message(enc_message, unhexlify(signature))

        # Verify pubky
        pk = PublicKey(hexlify(pubkey).decode("ascii"),
                       prefix=self.blockchain.prefix)
        if format(pk, self.blockchain.prefix) != memo_key:
            raise InvalidMessageSignature(
                "The signature doesn't match the memo key")

        self.signed_by_account = account
        self.signed_by_name = account["name"]
        self.plain_message = payload_dict.get("text")

        return True
Example #30
0
                    help="Interest rate to advertise as a witness",
                    type=int)
args = parser.parse_args()
if (args.operation[0] == "update"):
    if checkwit(args.account[0]):
        if not checkkey(args.account[0], args.privateactivekey[0], "active"):
            sys.exit("Private active key " + args.privateactivekey[0] +
                     " doesn't prove authority for user " + args.account[0])
        wit = Witness(args.account[0], steem_instance=stmf)
        #Witness exists
        #take stuff from blockchain, if the user doesn't provide the args
        if not args.publicownerkey:
            my_publickey = str(wit.json()["signing_key"])
        else:
            try:
                PublicKey(args.publicownerkey, prefix="EUR")
            except:
                sys.exit("Wrong public key syntax " + args.publicownerkey)
            else:
                my_publickey = str(args.publicownerkey)

        if not args.url:
            my_url = str(wit.json()["url"])
        else:
            my_url = str(args.url)

        if not args.creationfee:
            my_fee = str(wit.json()["props"]["account_creation_fee"])
        else:
            my_fee = str(args.creationfee)