Exemple #1
0
    def test_OOP(self):
        sk_s = unhexlify("4ba96b0b5303328c7405220598a587c4"
                         "acb06ed9a9601d149f85400195f1ec3d"
                         "a66d161e090652b054740748f059f92a"
                         "5b731f1c27b05571f6d942e4f8b7b264")
        sk = ed25519.SigningKey(sk_s)
        self.assertEqual(len(sk.to_bytes()), 64)
        self.assertEqual(sk.to_bytes(), sk_s)

        sk2_seed = unhexlify("4ba96b0b5303328c7405220598a587c4"
                             "acb06ed9a9601d149f85400195f1ec3d")
        sk2 = ed25519.SigningKey(sk2_seed)
        self.assertEqual(sk2.to_bytes(), sk.to_bytes())

        vk = sk.get_verifying_key()
        self.assertEqual(len(vk.to_bytes()), 32)
        exp_vks = unhexlify("a66d161e090652b054740748f059f92a"
                            "5b731f1c27b05571f6d942e4f8b7b264")
        self.assertEqual(vk.to_bytes(), exp_vks)
        self.assertEqual(ed25519.VerifyingKey(vk.to_bytes()), vk)
        msg = b"hello world"
        sig = sk.sign(msg)
        self.assertEqual(len(sig), 64)
        exp_sig = unhexlify("6eaffe94f2972b35158b6aaa9b69c1da"
                            "97f0896aca29c41b1dd7b32e6c9e2ff6"
                            "76fc8d8b034709cdcc37d8aeb86bebfb"
                            "173ace3c319e211ea1d7e8d8884c1808")
        self.assertEqual(sig, exp_sig)
        self.assertEqual(vk.verify(sig, msg), None)  # also, don't throw
        self.assertRaises(ed25519.BadSignatureError, vk.verify, sig,
                          msg + b".. NOT!")
Exemple #2
0
def change_xrb():
    representative = parser.get('wallet', 'representative')
    previous = get_previous()

    priv_key, pub_key = seed_account(seed, index)
    public_key = ed25519.SigningKey(priv_key).get_verifying_key().to_ascii(
        encoding="hex")

    #print("Starting PoW Generation")
    work = get_pow(previous, 'change')
    #print("Completed PoW Generation")

    #Calculate signature
    bh = blake2b(digest_size=32)
    bh.update(BitArray(hex=previous).bytes)
    bh.update(BitArray(hex=xrb_account(representative)).bytes)

    sig = ed25519.SigningKey(priv_key + pub_key).sign(bh.digest())
    signature = str(binascii.hexlify(sig), 'ascii')
    finished_block = '{ "type" : "change", "previous" : "%s", "representative" : "%s" , "work" : "%s", "signature" : "%s" }' % (
        previous, representative, work, signature)

    data = json.dumps({'action': 'process', 'block': finished_block})
    #print(data)
    ws.send(data)

    block_reply = ws.recv()
def receive_xrb():
    representative = 'xrb_1kd4h9nqaxengni43xy9775gcag8ptw8ddjifnm77qes1efuoqikoqy5sjq3'
    #Get pending blocks

    rx_data = get_pending()
    for block in rx_data:
        print(block)
        block_hash = block
        print(rx_data[block])
        balance = int(rx_data[block]['amount'])
        source = rx_data[block]['source']

    previous = get_previous(str(account))

    current_balance = get_balance(previous)
    print(current_balance)
    new_balance = int(current_balance) + int(balance)
    hex_balance = hex(new_balance)
    print(hex_balance)
    hex_final_balance = hex_balance[2:].upper().rjust(32, '0')
    print(hex_final_balance)

    priv_key, pub_key = seed_account(seed, 0)
    public_key = ed25519.SigningKey(priv_key).get_verifying_key().to_ascii(
        encoding="hex")

    #print("Starting PoW Generation")
    work = get_pow(previous)
    #print("Completed PoW Generation")

    #Calculate signature
    bh = blake2b(digest_size=32)
    bh.update(
        BitArray(
            hex=
            '0x0000000000000000000000000000000000000000000000000000000000000006'
        ).bytes)
    bh.update(BitArray(hex=xrb_account(account)).bytes)
    bh.update(BitArray(hex=previous).bytes)
    bh.update(BitArray(hex=xrb_account(account)).bytes)
    bh.update(BitArray(hex=hex_final_balance).bytes)
    bh.update(BitArray(hex=block_hash).bytes)

    sig = ed25519.SigningKey(priv_key + pub_key).sign(bh.digest())
    signature = str(binascii.hexlify(sig), 'ascii')

    finished_block = '{ "type" : "state", "previous" : "%s", "representative" : "%s" , "account" : "%s", "balance" : "%s", "link" : "%s", \
            "work" : "%s", "signature" : "%s" }' % (
        previous, account, account, new_balance, block_hash, work, signature)

    print(finished_block)

    data = json.dumps({'action': 'process', 'block': finished_block})
    #print(data)
    ws.send(data)

    block_reply = ws.recv()

    print(block_reply)
Exemple #4
0
 def test_publickey(self):
     seed = unhexlify("4ba96b0b5303328c7405220598a587c4"
                      "acb06ed9a9601d149f85400195f1ec3d")
     sk = ed25519.SigningKey(seed)
     self.assertEqual(hexlify(sk.to_bytes()),
                      (b"4ba96b0b5303328c7405220598a587c4"
                       b"acb06ed9a9601d149f85400195f1ec3d"
                       b"a66d161e090652b054740748f059f92a"
                       b"5b731f1c27b05571f6d942e4f8b7b264"))
     self.assertEqual(hexlify(sk.to_seed()),
                      (b"4ba96b0b5303328c7405220598a587c4"
                       b"acb06ed9a9601d149f85400195f1ec3d"))
     self.assertRaises(ValueError, ed25519.SigningKey, b"wrong length")
     sk2 = ed25519.SigningKey(seed)
     self.assertEqual(sk, sk2)
Exemple #5
0
    def test_encoding(self):
        sk_s = b"\x88" * 32  # usually urandom(32)
        sk1 = ed25519.SigningKey(sk_s)
        vk1 = sk1.get_verifying_key()

        def check1(encoding, expected):
            PREFIX = "private0-"
            p = sk1.to_ascii(PREFIX, encoding)
            self.assertEqual(p, expected)
            sk2 = ed25519.SigningKey(p, prefix=PREFIX, encoding=encoding)
            self.assertEqual(repr(sk1.to_bytes()), repr(sk2.to_bytes()))
            self.assertEqual(sk1, sk2)

        check1("base64",
               b"private0-iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIg")
        check1(
            "base32",
            b"private0-rceirceirceirceirceirceirceirceirceirceirceirceircea")
        check1(
            "hex",
            b"private0-8888888888888888888888888888888888888888888888888888888888888888"
        )

        def check2(encoding, expected):
            PREFIX = "public0-"
            p = vk1.to_ascii(PREFIX, encoding)
            self.assertEqual(p, expected)
            vk2 = ed25519.VerifyingKey(p, prefix=PREFIX, encoding=encoding)
            self.assertEqual(repr(vk1.to_bytes()), repr(vk2.to_bytes()))
            self.assertEqual(vk1, vk2)

        check2("base64",
               b"public0-skkdlQKuKGMKK6yy4MdFEP/N0yjDNP8+E5PnWy0x59w")
        check2(
            "base32",
            b"public0-wjer3ficvyuggcrlvszobr2fcd743uziym2p6pqtsptvwljr47oa")
        check2(
            "hex",
            b"public0-b2491d9502ae28630a2bacb2e0c74510ffcdd328c334ff3e1393e75b2d31e7dc"
        )

        def check3(encoding, expected):
            msg = b"msg"
            PREFIX = "sig0-"
            sig = sk1.sign(msg, PREFIX, encoding)
            self.assertEqual(sig, expected)
            vk1.verify(sig, msg, PREFIX, encoding)

        check3(
            "base64",
            b"sig0-MNfdUir6tMlaYQ+/p8KANJ5d+bk8g2al76v5MeJCo6RiywxURda3sU580CyiW2FBG/Q7kDRswgYqxbkQw3o5CQ"
        )
        check3(
            "base32",
            b"sig0-gdl52urk7k2mswtbb672pquagspf36nzhsbwnjppvp4tdyscuosgfsymkrc5nn5rjz6nalfclnqucg7uhoidi3gcayvmloiqyn5dsci"
        )
        check3(
            "hex",
            b"sig0-30d7dd522afab4c95a610fbfa7c280349e5df9b93c8366a5efabf931e242a3a462cb0c5445d6b7b14e7cd02ca25b61411bf43b90346cc2062ac5b910c37a3909"
        )
Exemple #6
0
 def check1(encoding, expected):
     PREFIX = "private0-"
     p = sk1.to_ascii(PREFIX, encoding)
     self.assertEqual(p, expected)
     sk2 = ed25519.SigningKey(p, prefix=PREFIX, encoding=encoding)
     self.assertEqual(repr(sk1.to_bytes()), repr(sk2.to_bytes()))
     self.assertEqual(sk1, sk2)
Exemple #7
0
def send_xrb(dest_address, final_balance):
    previous = get_previous()

    priv_key, pub_key = seed_account(seed, index)

    hex_balance = hex(final_balance)
    hex_final_balance = hex_balance[2:].upper().rjust(32, '0')
    #print(final_balance)

    #print("Starting PoW Generation")
    work = get_pow(previous, 'send')
    #workbytes = pow_generate(previous)
    #work = str(workbytes, 'ascii')
    #print("Completed PoW Generation")

    #Calculate signature
    bh = blake2b(digest_size=32)
    bh.update(BitArray(hex=previous).bytes)
    bh.update(BitArray(hex=xrb_account(dest_address)).bytes)
    bh.update(BitArray(hex=hex_final_balance).bytes)

    sig = ed25519.SigningKey(priv_key + pub_key).sign(bh.digest())
    signature = str(binascii.hexlify(sig), 'ascii')

    finished_block = '{ "type" : "send", "destination" : "%s", "balance" : "%s", "previous" : "%s" , "work" : "%s", "signature" : "%s" }' % (
        dest_address, hex_final_balance, previous, work, signature)

    data = json.dumps({'action': 'process', 'block': finished_block})
    #print(data)
    ws.send(data)

    block_reply = ws.recv()
    #print(block_reply)
    return block_reply
Exemple #8
0
    def test_prefix(self):
        sk1, vk1 = ed25519.create_keypair()
        PREFIX = b"private0-"
        p = sk1.to_bytes(PREFIX)
        # that gives us a binary string with a prefix
        self.assertTrue(p[:len(PREFIX)] == PREFIX, repr(p))
        sk2 = ed25519.SigningKey(p, prefix=PREFIX)
        self.assertEqual(sk1, sk2)
        self.assertEqual(repr(sk1.to_bytes()), repr(sk2.to_bytes()))
        self.assertRaises(ed25519.BadPrefixError,
                          ed25519.SigningKey,
                          p,
                          prefix=b"WRONG-")
        # SigningKey.to_seed() can do a prefix too
        p = sk1.to_seed(PREFIX)
        self.assertTrue(p[:len(PREFIX)] == PREFIX, repr(p))
        sk3 = ed25519.SigningKey(p, prefix=PREFIX)
        self.assertEqual(sk1, sk3)
        self.assertEqual(repr(sk1.to_bytes()), repr(sk3.to_bytes()))
        self.assertRaises(ed25519.BadPrefixError,
                          ed25519.SigningKey,
                          p,
                          prefix=b"WRONG-")

        # verifying keys can do this too
        PREFIX = b"public0-"
        p = vk1.to_bytes(PREFIX)
        self.assertTrue(p.startswith(PREFIX), repr(p))
        vk2 = ed25519.VerifyingKey(p, prefix=PREFIX)
        self.assertEqual(vk1, vk2)
        self.assertEqual(repr(vk1.to_bytes()), repr(vk2.to_bytes()))
        self.assertRaises(ed25519.BadPrefixError,
                          ed25519.VerifyingKey,
                          p,
                          prefix=b"WRONG-")

        # and signatures
        PREFIX = b"sig0-"
        p = sk1.sign(b"msg", PREFIX)
        self.assertTrue(p.startswith(PREFIX), repr(p))
        vk1.verify(p, b"msg", PREFIX)
        self.assertRaises(ed25519.BadPrefixError,
                          vk1.verify,
                          p,
                          b"msg",
                          prefix=b"WRONG-")
Exemple #9
0
def open_xrb():
    representative = parser.get('wallet', 'representative')
    #Get pending blocks
    data = json.dumps({'action': 'pending', 'account': account})

    ws.send(data)

    pending_blocks = ws.recv()
    #print("Received '%s'" % pending_blocks)

    rx_data = json.loads(str(pending_blocks))
    #for blocks in rx_data['blocks']:
    #print(rx_data['blocks'][0])
    source = rx_data['blocks'][0]

    priv_key, pub_key = hd.mnemonic_to_keys(mnemonic,
                                            passphrase=password,
                                            account_number=index)
    public_key = ed25519.SigningKey(priv_key).get_verifying_key().to_ascii(
        encoding="hex")

    #print("Starting PoW Generation")
    work = get_pow(str(public_key, 'ascii'))
    #print("Completed PoW Generation")

    #Calculate signature
    bh = blake2b(digest_size=32)
    bh.update(BitArray(hex=source).bytes)
    bh.update(BitArray(hex=xrb_account(representative)).bytes)
    bh.update(BitArray(hex=xrb_account(account)).bytes)

    sig = ed25519.SigningKey(priv_key + pub_key).sign(bh.digest())
    signature = str(binascii.hexlify(sig), 'ascii')
    finished_block = '{ "type" : "open", "source" : "%s", "representative" : "%s" , "account" : "%s", "work" : "%s", "signature" : "%s" }' % (
        source, representative, account, work, signature)

    data = json.dumps({'action': 'process', 'block': finished_block})
    #print(data)
    ws.send(data)

    block_reply = ws.recv()
    logging.info(block_reply)
Exemple #10
0
    def test_object_identity(self):
        sk1_s = unhexlify("ef32972ae3f1252a5aa1395347ea008c"
                          "bd2fed0773a4ea45e2d2d06c8cf8fbd4"
                          "c024601a9c5b854fb100ff3116cf4f22"
                          "a311565f027391cb49d3bbe11c44399d")
        sk2_s = unhexlify("3d550c158900b4c2922b6656d2f80572"
                          "89de4ee65043745179685ae7d29b944d"
                          "672b8a2cb23f9e75e1d46ce249cd9c04"
                          "68f816f1c734a102822b60e18b41eacd")
        sk1a = ed25519.SigningKey(sk1_s)
        sk1b = ed25519.SigningKey(sk1_s)
        vk1a = sk1a.get_verifying_key()
        vk1b = sk1b.get_verifying_key()
        sk2 = ed25519.SigningKey(sk2_s)
        vk2 = sk2.get_verifying_key()
        self.assertEqual(sk1a, sk1b)
        self.assertNotEqual(sk1a, sk2)
        self.assertEqual(vk1a, vk1b)
        self.assertNotEqual(vk1a, vk2)

        self.assertNotEqual(sk2, b"not a SigningKey")
        self.assertNotEqual(vk2, b"not a VerifyingKey")
Exemple #11
0
    def from_raw_seed(cls, raw_seed):
        """Generate a :class:`Keypair` object via a sequence of bytes.

        Typically these bytes are random, such as the usage of
        :func:`os.urandom` in :meth:`Keypair.random`. However this class method
        allows you to use an arbitrary sequence of bytes, provided the sequence
        is 32 bytes long.

        :param bytes raw_seed: A bytes object used as the seed for generating
            the keypair.
        :return: A new :class:`Keypair` derived by the raw secret seed.

        """
        signing_key = ed25519.SigningKey(raw_seed)
        verifying_key = signing_key.get_verifying_key()
        return cls(verifying_key, signing_key)
Exemple #12
0
def receive_xrb():
    time.sleep(10)
    pending = get_pending()

    if len(pending) > 0:
        data = json.dumps({'action': 'account_info', 'account': account})
        ws.send(data)
        info = ws.recv()
        if len(info) == 37:
            #print('Not found')
            open_xrb()
        else:
            source = pending[0]

            #Get account info
            previous = get_previous()

            priv_key, pub_key = seed_account(seed, index)

            #print("Starting PoW Generation")
            work = get_pow(previous, 'receive')
            #print("Completed PoW Generation")

            #Calculate signature
            bh = blake2b(digest_size=32)
            bh.update(BitArray(hex=previous).bytes)
            bh.update(BitArray(hex=source).bytes)

            sig = ed25519.SigningKey(priv_key + pub_key).sign(bh.digest())
            signature = str(binascii.hexlify(sig), 'ascii')
            finished_block = '{ "type" : "receive", "source" : "%s", "previous" : "%s" , "work" : "%s", "signature" : "%s" }' % (
                source, previous, work, signature)

            data = json.dumps({'action': 'process', 'block': finished_block})
            #print(data)
            ws.send(data)

            block_reply = ws.recv()
            save_config('balance', str(get_balance(account)))
            #print(block_reply)
    else:
        if parser.get('wallet', 'cached_pow') == '' and parser.get(
                'wallet', 'open') == '1':
            previous = get_previous()
            work = get_pow(previous, 'cache')
            save_config('cached_pow', work)
    time.sleep(50)
Exemple #13
0
    def _add_sig(self):
        # Adding new signature to version file
        # Raw private key will need to be converted into
        # a signing key object
        private_key_raw = self._load_private_keys()
        if private_key_raw is None:
            log.error('Private Key not found. Please '
                      'import a keypack & try again')
            return

        # Load update manifest
        update_data = self._load_update_data()

        # We don't want to verify the signature
        if 'signature' in update_data:
            log.debug('Removing signatures from version file')
            del update_data['signature']

        # We create a signature from the string
        update_data_str = json.dumps(update_data, sort_keys=True)

        private_key_raw = private_key_raw.encode('utf-8')

        # Creating signing key object
        private_key = ed25519.SigningKey(private_key_raw,
                                         encoding=self.key_encoding)
        log.debug("Signing update data")
        # Signs update data with private key
        signature = private_key.sign(six.b(update_data_str),
                                     encoding=self.key_encoding).decode()
        log.debug('Sig: %s', signature)

        # Create new dict from json string
        update_data = json.loads(update_data_str)

        # Add signatures to update data
        update_data['signature'] = signature
        log.debug('Adding signature to update data')

        # Write updated version file to .pyupdater/config.pyu
        self._write_update_data(update_data)

        # Write gzipped key file
        self._write_key_file()
Exemple #14
0
def receive_xrb(_loop, _data):
    pending = get_pending()

    if len(pending) > 0:

        data = json.dumps({'action': 'account_info', 'account': account})
        ws.send(data)
        info = ws.recv()
        if len(info) == 37:
            #print('Not found')
            open_xrb()
        else:
            source = pending[0]

            #Get account info
            previous = get_previous()

            priv_key, pub_key = hd.mnemonic_to_keys(mnemonic,
                                                    passphrase=password,
                                                    account_number=index)

            #print("Starting PoW Generation")
            work = get_pow(previous)
            #print("Completed PoW Generation")

            #Calculate signature
            bh = blake2b(digest_size=32)
            bh.update(BitArray(hex=previous).bytes)
            bh.update(BitArray(hex=source).bytes)

            sig = ed25519.SigningKey(priv_key + pub_key).sign(bh.digest())
            signature = str(binascii.hexlify(sig), 'ascii')
            finished_block = '{ "type" : "receive", "source" : "%s", "previous" : "%s" , "work" : "%s", "signature" : "%s" }' % (
                source, previous, work, signature)

            data = json.dumps({'action': 'process', 'block': finished_block})
            #print(data)
            ws.send(data)

            block_reply = ws.recv()
            logging.info(block_reply)
            #print(block_reply)
    main_loop.set_alarm_in(60, receive_xrb)
Exemple #15
0
    def _gen_keypack(self, name):
        # Create new public & private key for app signing
        try:
            app_pri, app_pub = self._make_keys()
        except Exception as err:
            log.error(err)
            log.debug(err, exc_info=True)
            raise KeyHandlerError("Failed to create keypair")

        # Load app specific private & public key
        off_pri, off_pub = self._load_offline_keys(name)

        log.debug('off_pri type: %s', type(off_pri))
        off_pri = off_pri.encode()
        if six.PY2:
            app_pub = six.b(app_pub)

        signing_key = ed25519.SigningKey(off_pri, encoding=self.key_encoding)

        # Create signature from app signing public key
        signature = signing_key.sign(app_pub,
                                     encoding=self.key_encoding).decode()

        if six.PY3:
            app_pri = app_pri.decode()
            app_pub = app_pub.decode()

        keypack = {
            'upload': {
                'app_public': app_pub,
                'signature': signature
            },
            'client': {
                'offline_public': off_pub
            },
            'repo': {
                'app_private': app_pri
            }
        }
        return keypack
Exemple #16
0
def private_public(private):
    return ed25519.SigningKey(private).get_verifying_key().to_bytes()
Exemple #17
0
def test():
    seed = "9F1D53E732E48F25F94711D5B22086778278624F715D9B2BEC8FB81134E7C904"
    priv_key, pub_key = seed_account(seed, 1)

    #{
    #    "type": "send",
    #    "previous": "C8E5B875778702445B25657276ABC56AA9910B283537CA438B2CC59B0CF93712",
    #    "destination": "xrb_34bmpi65zr967cdzy4uy4twu7mqs9nrm53r1penffmuex6ruqy8nxp7ms1h1",
    #    "balance": "000000FC6F7C40458122964CFFFFFF9C",
    #    "work": "266063092558d903",
    #    "signature": "17D6EAF3438CC592333594C96D023D742F7F38669F2DA6A763877F6958B3A76572169652E55D05E0759E114252765DB9E0F3BF55FA89F28E300CAF829C89250E"
    #}

    block = "C8E5B875778702445B25657276ABC56AA9910B283537CA438B2CC59B0CF93712"
    times = []

    print("Profiling PoW...")
    for x in range(1, 11):
        print("Round " + str(x) + ": Generating PoW...")
        start = Timer()
        pow = pow_generate(block)
        end = Timer()
        elapsed = int(end - start)
        times.append(elapsed)
        print("Elapsed time: " + str(elapsed) + " seconds")
        print("Valid: " + str(pow_validate(pow, block)) + " Value: " + pow)

    print("Average elapsed time: " + str(sum(times) / len(times)) + " seconds")

    # send block
    bh = blake2b(digest_size=32)

    bh.update(
        BitArray(
            hex=
            "C8E5B875778702445B25657276ABC56AA9910B283537CA438B2CC59B0CF93712"
        ).bytes)  # previous block
    print(
        "Previous  ",
        BitArray(
            hex=
            "C8E5B875778702445B25657276ABC56AA9910B283537CA438B2CC59B0CF93712"
        ).hex)

    bh.update(
        BitArray(hex=xrb_account(
            "xrb_34bmpi65zr967cdzy4uy4twu7mqs9nrm53r1penffmuex6ruqy8nxp7ms1h1")
                 ).bytes)  # destination address
    print(
        "Dest      ",
        BitArray(hex=xrb_account(
            "xrb_34bmpi65zr967cdzy4uy4twu7mqs9nrm53r1penffmuex6ruqy8nxp7ms1h1")
                 ).hex)

    bh.update(
        BitArray(hex="000000FC6F7C40458122964CFFFFFF9C").bytes)  # balance
    print("Balance   ", BitArray(hex="000000FC6F7C40458122964CFFFFFF9C").hex)

    print("Hash      ", bh.hexdigest())

    sig = ed25519.SigningKey(priv_key + pub_key).sign(
        bh.digest())  # work is not included in signature
    print("Signature ", sig.hex())
Exemple #18
0
 def from_raw_seed(cls, raw_seed):
     signing_key = ed25519.SigningKey(raw_seed)
     verifying_key = signing_key.get_verifying_key()
     return cls(verifying_key, signing_key)
Exemple #19
0
bh = blake2b(digest_size=32)

bh.update(
    BitArray(
        hex="C8E5B875778702445B25657276ABC56AA9910B283537CA438B2CC59B0CF93712"
    ).bytes)  # previous block
print(
    "Previous  ",
    BitArray(
        hex="C8E5B875778702445B25657276ABC56AA9910B283537CA438B2CC59B0CF93712"
    ).hex)

bh.update(
    BitArray(hex=xrb_account(
        "xrb_34bmpi65zr967cdzy4uy4twu7mqs9nrm53r1penffmuex6ruqy8nxp7ms1h1")).
    bytes)  # destination address
print(
    "Dest      ",
    BitArray(hex=xrb_account(
        "xrb_34bmpi65zr967cdzy4uy4twu7mqs9nrm53r1penffmuex6ruqy8nxp7ms1h1")).
    hex)

bh.update(BitArray(hex="000000FC6F7C40458122964CFFFFFF9C").bytes)  # balance
print("Balance   ", BitArray(hex="000000FC6F7C40458122964CFFFFFF9C").hex)

print("Hash      ", bh.hexdigest())

sig = ed25519.SigningKey(priv_key + pub_key).sign(
    bh.digest())  # work is not included in signature
print("Signature ", sig.hex())