コード例 #1
0
ファイル: memo.py プロジェクト: neddykelly/bhive
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 = py23_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", default_prefix)
    s = {
        "from": format(priv.pubkey, prefix),
        "to": format(pub, prefix),
        "nonce": nonce,
        "check": check,
        "encrypted": cipher,
        "prefix": prefix
    }
    tx = Memo(**s)
    return "#" + base58encode(hexlify(py23_bytes(tx)).decode("ascii"))
コード例 #2
0
 def test_Bool(self):
     u = types.Bool(True)
     self.assertEqual(py23_bytes(u), b"\x01")
     self.assertEqual(str(u), 'true')
     u = types.Bool(False)
     self.assertEqual(py23_bytes(u), b"\x00")
     self.assertEqual(str(u), 'false')
コード例 #3
0
 def test_varint32(self):
     u = types.Varint32(2**32 - 1)
     self.assertEqual(py23_bytes(u), b"\xff\xff\xff\xff\x0f")
     self.assertEqual(str(u), str(4294967295))
     u = types.Id(2**32 - 1)
     self.assertEqual(py23_bytes(u), b"\xff\xff\xff\xff\x0f")
     self.assertEqual(str(u), str(4294967295))
コード例 #4
0
ファイル: test_py23.py プロジェクト: neddykelly/bhive
 def test_bytes_int(self):
     """
     In Py3, bytes(int) -> bytes object of size given by the parameter initialized with null
     """
     self.assertEqual(py23_bytes(5), b'\x00\x00\x00\x00\x00')
     # Test using newint:
     self.assertEqual(py23_bytes(int(5)), b'\x00\x00\x00\x00\x00')
     self.assertTrue(isinstance(py23_bytes(int(5)), bytes_types))
コード例 #5
0
    def test_string(self):
        u = types.String("HelloFoobar")
        self.assertEqual(py23_bytes(u), b"\x0bHelloFoobar")
        self.assertEqual(str(u), "HelloFoobar")

        u = types.String("\x07\x08\x09\x0a\x0b\x0c\x0d\x0e")
        self.assertEqual(py23_bytes(u), b"\x14u0007b\t\nu000bf\ru000e")
        self.assertEqual(str(u), "\x07\x08\x09\x0a\x0b\x0c\x0d\x0e")
コード例 #6
0
 def test_Optional(self):
     u = types.Optional(types.Uint16(10))
     self.assertEqual(py23_bytes(u), b"\x01\n\x00")
     self.assertEqual(str(u), '10')
     self.assertFalse(u.isempty())
     u = types.Optional(None)
     self.assertEqual(py23_bytes(u), b"\x00")
     self.assertEqual(str(u), 'None')
     self.assertTrue(u.isempty())
コード例 #7
0
ファイル: test_py23.py プロジェクト: neddykelly/bhive
    def test_isinstance_bytes_subclass(self):
        """
        Issue #89
        """
        value = py23_bytes(b'abc')

        class Magic():
            def __bytes__(self):
                return py23_bytes(b'abc')

        self.assertEqual(value, py23_bytes(Magic()))
コード例 #8
0
 def test_array(self):
     u = types.Array([types.Uint8(10) for x in range(2)] + [11])
     self.assertEqual(py23_bytes(u), b'\x03\n\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
     self.assertEqual(str(u), "[10, 10, 11]")
     u = types.Set([types.Uint16(10) for x in range(10)])
     self.assertEqual(py23_bytes(u), b"\n\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00\n\x00")
     self.assertEqual(str(u), "[10, 10, 10, 10, 10, 10, 10, 10, 10, 10]")
     u = types.Array(["Foobar"])
     # We do not support py23_bytes of Array containing String only!
     # self.assertEqual(py23_bytes(u), b'')
     self.assertEqual(str(u), '["Foobar"]')
コード例 #9
0
ファイル: test_py23.py プロジェクト: neddykelly/bhive
 def test_bytes_encoding_arg_non_kwarg(self):
     """
     As above, but with a positional argument
     """
     u = u'Unicode string: \u5b54\u5b50'
     b = py23_bytes(u, 'utf-8')
     self.assertEqual(b, u.encode('utf-8'))
コード例 #10
0
    def test_Static_variant(self):
        class Tmp(types.Uint16):
            def json(self):
                return "Foobar"

        u = types.Static_variant(Tmp(10), 10)
        self.assertEqual(py23_bytes(u), b"\n\n\x00")
        self.assertEqual(str(u), '[10, "Foobar"]')
コード例 #11
0
    def verify(self, pubkeys=[], chain=None, recover_parameter=False):
        """Returned pubkeys have to be checked if they are existing"""
        if not chain:
            raise
        chain_params = self.getChainParams(chain)
        self.deriveDigest(chain)
        signatures = self.data["signatures"].data
        pubKeysFound = []

        for signature in signatures:
            if recover_parameter:
                p = verify_message(
                    self.message,
                    py23_bytes(signature)
                )
            else:
                p = None
            if p is None:
                for i in range(4):
                    try:
                        p = verify_message(
                            self.message,
                            py23_bytes(signature),
                            recover_parameter=i
                        )
                        phex = hexlify(p).decode('ascii')
                        pubKeysFound.append(phex)
                    except Exception:
                        p = None
            else:
                phex = hexlify(p).decode('ascii')
                pubKeysFound.append(phex)

        for pubkey in pubkeys:
            if not isinstance(pubkey, PublicKey):
                raise Exception("Pubkeys must be array of 'PublicKey'")

            k = pubkey.unCompressed()[2:]
            if k not in pubKeysFound and repr(pubkey) not in pubKeysFound:
                k = PublicKey(PublicKey(k).compressed())
                f = format(k, chain_params["prefix"])
                raise Exception("Signature for %s missing!" % f)
        return pubKeysFound
コード例 #12
0
 def doit(self, printWire=False, ops=None):
     if ops is None:
         ops = [Operation(self.op)]
     tx = Signed_Transaction(ref_block_num=self.ref_block_num,
                             ref_block_prefix=self.ref_block_prefix,
                             expiration=self.expiration,
                             operations=ops)
     tx = tx.sign([self.wif], chain=self.prefix)
     tx.verify([PrivateKey(self.wif, prefix=u"STM").pubkey], self.prefix)
     txWire = hexlify(py23_bytes(tx)).decode("ascii")
コード例 #13
0
ファイル: test_py23.py プロジェクト: neddykelly/bhive
 def test_bytes_encoding_arg(self):
     """
     The bytes class has changed in Python 3 to accept an
     additional argument in the constructor: encoding.
     It would be nice to support this without breaking the
     isinstance(..., bytes) test below.
     """
     u = u'Unicode string: \u5b54\u5b50'
     b = py23_bytes(u, encoding='utf-8')
     self.assertEqual(b, u.encode('utf-8'))
コード例 #14
0
 def hash_op(event):
     """ This method generates a hash of blockchain operation. """
     if isinstance(event, dict) and "type" in event and "value" in event:
         op_type = event["type"]
         if len(op_type) > 10 and op_type[len(op_type) -
                                          10:] == "_operation":
             op_type = op_type[:-10]
         op = event["value"]
         event = [op_type, op]
     data = json.dumps(event, sort_keys=True)
     return hashlib.sha1(py23_bytes(data, 'utf-8')).hexdigest()
コード例 #15
0
ファイル: conveyor.py プロジェクト: neddykelly/bhive
    def prehash_message(self, timestamp, account, method, params, nonce):
        """ Prepare a hash for the Conveyor API request with SHA256 according
            to https://gitlab.syncad.com/hive-group//rpc-auth
            Hashing of `second` is then done inside `ecdsasig.sign_message()`.

            :param str timestamp: valid iso8601 datetime ending in "Z"
            :param str account: valid hive blockchain account name
            :param str method: Conveyor method name to be called
            :param bytes param: base64 encoded request parameters
            :param bytes nonce: random 8 bytes

        """
        first = hashlib.sha256(py23_bytes(timestamp + account + method + params, self.ENCODING))
        return self.K + first.digest() + nonce
コード例 #16
0
ファイル: test_ecdsa.py プロジェクト: neddykelly/bhive
 def test_sign_message(self, module):
     if module == "cryptography":
         if not ecda.CRYPTOGRAPHY_AVAILABLE:
             return
         ecda.SECP256K1_MODULE = "cryptography"
     elif module == "secp256k1":
         if not ecda.SECP256K1_AVAILABLE:
             return
         ecda.SECP256K1_MODULE = "secp256k1"
     else:
         ecda.SECP256K1_MODULE = module
     pub_key = py23_bytes(repr(PrivateKey(wif).pubkey), "latin")
     signature = ecda.sign_message("Foobar", wif)
     pub_key_sig = ecda.verify_message("Foobar", signature)
     self.assertEqual(hexlify(pub_key_sig), pub_key)
コード例 #17
0
    def __init__(self, url="https://conveyor.hive.blog", hive_instance=None):
        """ Initialize a Conveyor instance
            :param str url: (optional) URL to the Conveyor API, defaults to
                https://conveyor.hive.blog
            :param bhive.hive.Hive hive_instance: Hive instance

        """

        self.url = url
        self.hive = hive_instance or shared_hive_instance()
        self.id = 0
        self.ENCODING = 'utf-8'
        self.TIMEFORMAT = '%Y-%m-%dT%H:%M:%S.%f'
        self.K = hashlib.sha256(py23_bytes('steem_jsonrpc_auth',
                                           self.ENCODING)).digest()
コード例 #18
0
    def id(self):
        """ The transaction id of this transaction
        """
        # Store signatures temporarily since they are not part of
        # transaction id
        sigs = self.data["signatures"]
        self.data.pop("signatures", None)

        # Generage Hash of the seriliazed version
        h = hashlib.sha256(py23_bytes(self)).digest()

        # recover signatures
        self.data["signatures"] = sigs

        # Return properly truncated tx hash
        return hexlify(h[:20]).decode("ascii")
コード例 #19
0
 def get_tx_size(self, op):
     """Returns the tx size of an operation"""
     ops = [Operation(op)]
     prefix = u"HIVE"
     wif = "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"
     ref_block_num = 34294
     ref_block_prefix = 3707022213
     expiration = "2016-04-06T08:29:27"
     tx = Signed_Transaction(ref_block_num=ref_block_num,
                             ref_block_prefix=ref_block_prefix,
                             expiration=expiration,
                             operations=ops)
     tx = tx.sign([wif], chain=prefix)
     txWire = hexlify(py23_bytes(tx)).decode("ascii")
     tx_size = len(txWire)
     return tx_size
コード例 #20
0
    def deriveDigest(self, chain):
        chain_params = self.getChainParams(chain)
        # Chain ID
        self.chainid = chain_params["chain_id"]

        # Do not serialize signatures
        sigs = self.data["signatures"]
        self.data["signatures"] = []

        # Get message to sign
        #   bytes(self) will give the wire formated data according to
        #   GrapheneObject and the data given in __init__()
        self.message = unhexlify(self.chainid) + py23_bytes(self)
        self.digest = hashlib.sha256(self.message).digest()

        # restore signatures
        self.data["signatures"] = sigs
コード例 #21
0
ファイル: memo.py プロジェクト: neddykelly/bhive
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)
コード例 #22
0
    def upload(self, image, account, image_name=None):
        """ Uploads an image

            :param image: path to the image or image in bytes representation which should be uploaded
            :type image: str, bytes
            :param str account: Account which is used to upload. A posting key must be provided.
            :param str image_name: optional

            .. code-block:: python

                from bhive import Hive
                from bhive.imageuploader import ImageUploader
                hv = Hive(keys=["5xxx"]) # private posting key
                iu = ImageUploader(hive_instance=hv)
                iu.upload("path/to/image.png", "account_name") # "private posting key belongs to account_name

        """
        account = Account(account, hive_instance=self.hive)
        if "posting" not in account:
            account.refresh()
        if "posting" not in account:
            raise AssertionError("Could not access posting permission")
        for authority in account["posting"]["key_auths"]:
            posting_wif = self.hive.wallet.getPrivateKeyForPublicKey(
                authority[0])

        if isinstance(image, string_types):
            image_data = open(image, 'rb').read()
        elif isinstance(image, io.BytesIO):
            image_data = image.read()
        else:
            image_data = image

        message = py23_bytes(self.challenge, "ascii") + image_data
        signature = sign_message(message, posting_wif)
        signature_in_hex = hexlify(signature).decode("ascii")

        files = {image_name or 'image': image_data}
        url = "%s/%s/%s" % (self.base_url, account["name"], signature_in_hex)
        r = requests.post(url, files=files)
        return r.json()
コード例 #23
0
ファイル: memo.py プロジェクト: neddykelly/bhive
def init_aes_bts(shared_secret, nonce):
    """ Initialize AES instance

        :param hex shared_secret: Shared Secret to use as encryption key
        :param int nonce: Random nonce
        :return: AES instance
        :rtype: AES

    """
    # Shared Secret
    ss = hashlib.sha512(unhexlify(shared_secret)).digest()
    # Seed
    seed = py23_bytes(str(nonce), 'ascii') + hexlify(ss)
    seed_digest = hexlify(hashlib.sha512(seed).digest()).decode('ascii')
    # Check'sum'
    check = hashlib.sha256(unhexlify(seed_digest)).digest()
    check = struct.unpack_from("<I", check[:4])[0]
    # AES
    key = unhexlify(seed_digest[0:64])
    iv = unhexlify(seed_digest[64:96])
    return AES.new(key, AES.MODE_CBC, iv)
コード例 #24
0
ファイル: conveyor.py プロジェクト: neddykelly/bhive
    def _request(self, account, method, params, key):
        """Assemble the request, hash it, sign it and send it to the Conveyor
            instance. Returns the server response as JSON.

            :param str account: account name
            :param str method: Conveyor method name to be called
            :param dict params: request parameters as `dict`
            :param str key: Hive posting key for signing

        """
        params_bytes = py23_bytes(json.dumps(params), self.ENCODING)
        params_enc = base64.b64encode(params_bytes).decode(self.ENCODING)
        timestamp = datetime.utcnow().strftime(self.TIMEFORMAT)[:-3] + "Z"
        nonce_int = random.getrandbits(64)
        nonce_bytes = struct.pack('>Q', nonce_int)  # 64bit ULL, big endian
        nonce_str = "%016x" % (nonce_int)

        message = self.prehash_message(timestamp, account, method,
                                       params_enc, nonce_bytes)
        signature = sign_message(message, key)
        signature_hex = hexlify(signature).decode(self.ENCODING)

        request = {
            "jsonrpc": "2.0",
            "id": self.id,
            "method": method,
            "params": {
                "__signed": {
                    "account": account,
                    "nonce": nonce_str,
                    "params": params_enc,
                    "signatures": [signature_hex],
                    "timestamp": timestamp
                }
            }
        }
        r = requests.post(self.url, data=json.dumps(request))
        self.id += 1
        return r.json()
コード例 #25
0
ファイル: memo.py プロジェクト: neddykelly/bhive
def encode_memo_bts(priv, pub, nonce, message):
    """ 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 = init_aes_bts(shared_secret, nonce)
    # Checksum
    raw = py23_bytes(message, 'utf8')
    checksum = hashlib.sha256(raw).digest()
    raw = (checksum[0:4] + raw)
    # Padding
    BS = 16
    # FIXME: this adds 16 bytes even if not required
    if len(raw) % BS:
        raw = _pad(raw, BS)
    # Encryption
    return hexlify(aes.encrypt(raw)).decode('ascii')
コード例 #26
0
ファイル: memo.py プロジェクト: neddykelly/bhive
def decode_memo_bts(priv, pub, nonce, message):
    """ Decode a message with a shared secret between Alice and Bob

        :param PrivateKey priv: Private Key (of Bob)
        :param PublicKey pub: Public Key (of Alice)
        :param int nonce: Nonce used for Encryption
        :param bytes message: Encrypted Memo message
        :return: Decrypted message
        :rtype: str
        :raise ValueError: if message cannot be decoded as valid UTF-8
               string

    """
    shared_secret = get_shared_secret(priv, pub)
    aes = init_aes_bts(shared_secret, nonce)
    # Encryption
    raw = py23_bytes(message, 'ascii')
    cleartext = aes.decrypt(unhexlify(raw))
    # TODO, verify checksum
    message = cleartext[4:]
    try:
        return _unpad(message.decode('utf8'), 16)
    except Exception:
        raise ValueError(message)
コード例 #27
0
 def deriveChecksum(self, s):
     """ Derive the checksum
     """
     checksum = hashlib.sha256(py23_bytes(s, "ascii")).hexdigest()
     return checksum[:4]
コード例 #28
0
 def test_int16(self):
     u = types.Int16(2**15 - 1)
     self.assertEqual(py23_bytes(u), b"\xff\x7f")
     self.assertEqual(str(u), str(2**15 - 1))
コード例 #29
0
 def test_int64(self):
     u = types.Int64(2**63 - 1)
     self.assertEqual(py23_bytes(u), b"\xff\xff\xff\xff\xff\xff\xff\x7f")
     self.assertEqual(str(u), str(9223372036854775807))
コード例 #30
0
 def test_uint64(self):
     u = types.Uint64(2**64 - 1)
     self.assertEqual(py23_bytes(u), b"\xff\xff\xff\xff\xff\xff\xff\xff")
     self.assertEqual(str(u), str(2**64 - 1))