Ejemplo n.º 1
0
def compute_tx_key(spend_key_private,
                   tx_prefix_hash,
                   salt=None,
                   rand_mult=None):
    """

    :param spend_key_private:
    :param tx_prefix_hash:
    :param salt:
    :param rand_mult:
    :return:
    """
    if not salt:
        salt = crypto.random_bytes(32)

    if not rand_mult:
        rand_mult_num = crypto.random_scalar()
        rand_mult = crypto.encodeint(rand_mult_num)
    else:
        rand_mult_num = crypto.decodeint(rand_mult)

    rand_inp = crypto.sc_add(spend_key_private, rand_mult_num)
    passwd = crypto.keccak_2hash(crypto.encodeint(rand_inp) + tx_prefix_hash)
    tx_key = crypto.compute_hmac(salt, passwd)
    # tx_key = crypto.pbkdf2(passwd, salt, count=100)
    return tx_key, salt, rand_mult
Ejemplo n.º 2
0
    async def save_account(self, file):
        """
        Stores account data
        :param file:
        :return:
        """
        if self.wallet_salt is None:
            self.wallet_salt = crypto.random_bytes(32)

        # Wallet view key encryption
        wallet_enc_key = misc.wallet_enc_key(self.wallet_salt,
                                             self.wallet_password)
        ciphertext = chacha_poly.encrypt_pack(wallet_enc_key,
                                              crypto.encodeint(self.priv_view))

        with open(file, "w") as fh:
            data = {
                "view_key_enc": binascii.hexlify(ciphertext).decode("ascii"),
                "address": self.address.decode("ascii"),
                "network_type": self.network_type,
                "wallet_salt":
                binascii.hexlify(self.wallet_salt).decode("ascii"),
                "rpc_addr": self.rpc_addr,
                "wallet_file": self.wallet_file,
                "monero_bin": self.monero_bin,
            }
            json.dump(data, fh, indent=2)
Ejemplo n.º 3
0
    async def init(self, ctx, msg):
        from apps.monero.controller import wrapper

        self.ctx = ctx
        self.creds = await wrapper.monero_get_creds(self.ctx, msg.address_n
                                                    or (), msg.network_type)
        self._state_init()
        self.a = self.creds.view_key_private
        self.A = self.creds.view_key_public
        self.b = self.creds.spend_key_private
        self.B = self.creds.spend_key_public
        self.key_enc = crypto.random_bytes(
            32)  # WARNING: potentially dangerous for whole session.
Ejemplo n.º 4
0
 def new_random_wallet(cls, user_entropy=None, network=BitcoinMainNet):
     """
     Generate a new wallet using a randomly generated 512 bit seed.
     Args:
         user_entropy: Optional user-supplied entropy which is combined
             combined with the random seed, to help counteract compromised
             PRNGs.
     You are encouraged to add an optional `user_entropy` string to protect
     against a compromised CSPRNG. This will be combined with the output
     from the CSPRNG. Note that if you do supply this value it only adds
     additional entropy and will not be sufficient to recover the random
     wallet. If you're even saving `user_entropy` at all, you're doing it
     wrong.
     """
     seed = crypto.random_bytes(64)
     if user_entropy:
         user_entropy = str(user_entropy)  # allow for int/long
         seed += user_entropy
     return cls.from_master_secret(seed, network=network)
Ejemplo n.º 5
0
    async def init(self, ctx, msg: MoneroKeyImageExportInitRequest):
        self.ctx = ctx
        await self.derive_creds(msg)

        confirmation = await self.iface.confirm_ki_sync(msg, ctx=ctx)
        if not confirmation:
            return Failure(code=FailureType.ActionCancelled, message="rejected")

        self.num = msg.num
        self.hash = msg.hash
        self.enc_key = crypto.random_bytes(32)

        # Sub address precomputation
        if msg.subs and len(msg.subs) > 0:
            for sub in msg.subs:
                monero.compute_subaddresses(
                    self.creds, sub.account, sub.minor_indices, self.subaddresses
                )
        return MoneroKeyImageExportInitAck()
Ejemplo n.º 6
0
    async def open_account_file(self, file):
        """
        Opens account file
        :param file:
        :return:
        """
        with open(file) as fh:
            js = json.load(fh)

        # Wallet key encryption
        self.wallet_password = await self.prompt_password()
        self.wallet_salt = common.defvalkey(js, "wallet_salt")
        if self.wallet_salt is None:
            self.wallet_salt = crypto.random_bytes(32)
        else:
            self.wallet_salt = binascii.unhexlify(self.wallet_salt)

        # Wallet view key dec.
        if "view_key" in js:
            self.priv_view = crypto.b16_to_scalar(
                js["view_key"].encode("utf8"))

        elif "view_key_enc" in js:
            wallet_enc_key = misc.wallet_enc_key(self.wallet_salt,
                                                 self.wallet_password)
            plain = chacha_poly.decrypt_pack(
                wallet_enc_key, binascii.unhexlify(js["view_key_enc"]))
            self.priv_view = crypto.decodeint(plain)

        self.address = js["address"].encode("utf8")
        self.wallet_file = js["wallet_file"]
        self.monero_bin = js["monero_bin"]
        self.set_network_type(js["network_type"])
        self.rpc_addr = js["rpc_addr"]

        await self.open_with_keys(self.priv_view, self.address)
Ejemplo n.º 7
0
    async def store_cdata(self, cdata, signed_tx, tx, transfers):
        """
        Stores transaction data for later usage.
            - cdata.enc_salt1, cdata.enc_salt2, cdata.enc_keys
            - tx_keys are AEAD protected, key derived from spend key - only token can open.
            - construction data for further proofs.

        :param cdata:
        :param signed_tx:
        :param tx:
        :param transfers:
        :return:
        """
        hash = cdata.tx_prefix_hash
        prefix = binascii.hexlify(hash[:12])

        tx_key_salt = crypto.random_bytes(32)
        tx_key_inp = hash + crypto.encodeint(self.priv_view)
        tx_view_key = crypto.pbkdf2(tx_key_inp, tx_key_salt, 2048)

        unsigned_data = xmrtypes.UnsignedTxSet()
        unsigned_data.txes = [tx]
        unsigned_data.transfers = transfers if transfers is not None else []

        writer = xmrserialize.MemoryReaderWriter()
        ar = xmrboost.Archive(writer, True)
        await ar.root()
        await ar.message(unsigned_data)

        unsigned_key = crypto.keccak_2hash(b'unsigned;' + tx_view_key)
        ciphertext = chacha_poly.encrypt_pack(unsigned_key,
                                              bytes(writer.get_buffer()))

        # Serialize signed transaction
        writer = xmrserialize.MemoryReaderWriter()
        ar = xmrserialize.Archive(writer, True)
        await ar.root()
        await ar.message(signed_tx)
        signed_tx_bytes = writer.get_buffer()
        signed_tx_hmac_key = crypto.keccak_2hash(b'hmac;' + tx_view_key)
        signed_tx_hmac = crypto.compute_hmac(signed_tx_hmac_key,
                                             signed_tx_bytes)

        try:
            js = {
                "time": int(time.time()),
                "hash": binascii.hexlify(hash).decode("ascii"),
                "enc_salt1": binascii.hexlify(cdata.enc_salt1).decode("ascii"),
                "enc_salt2": binascii.hexlify(cdata.enc_salt2).decode("ascii"),
                "tx_keys": binascii.hexlify(cdata.enc_keys).decode("ascii"),
                "unsigned_data": binascii.hexlify(ciphertext).decode("ascii"),
                "tx_salt": binascii.hexlify(tx_key_salt).decode("ascii"),
                "tx_signed": binascii.hexlify(signed_tx_bytes).decode("ascii"),
                "tx_signed_hmac":
                binascii.hexlify(signed_tx_hmac).decode("ascii"),
            }

            with open("transaction_%s.json" % prefix.decode("ascii"),
                      "w") as fh:
                json.dump(js, fh, indent=2)
                fh.write("\n")

        except Exception as e:
            self.trace_logger.log(e)
            print("Unable to save transaction data for transaction %s" %
                  binascii.hexlify(hash).decode("ascii"))
Ejemplo n.º 8
0
    def create_wallet(self, line):
        """
        Creates a new account
        :return:
        """
        if self.args.account_file:
            if os.path.exists(self.args.account_file):
                logger.error("Wallet file exists, could not overwrite")
                return

        print("Generating new wallet...")
        seed = crypto.random_bytes(32)

        wl = bip32.Wallet.from_master_secret(seed)
        seed_bip32_words, seed_bip32_words_indices = wl.to_seed_words()
        seed_bip32_b58 = wl.serialize_b58()

        # Generate private keys based on the gen mechanism. Bip44 path + Monero backward compatible
        data = wl.get_child_for_path("m/44'/128'/0'/0/0")
        to_hash = data.chain_code + binascii.unhexlify(
            data.private_key.get_key())

        # to_hash is initial seed in the Monero sense, recoverable from this seed
        hashed = crypto.cn_fast_hash(to_hash)
        electrum_words = " ".join(mnemonic.mn_encode(hashed))

        keys = monero.generate_monero_keys(hashed)
        spend_sec, spend_pub, view_sec, view_pub = keys

        print("Seed:             0x%s" %
              binascii.hexlify(seed).decode("ascii"))
        print("Seed bip39 words: %s" % " ".join(seed_bip32_words))
        print("Seed bip32 b58:   %s" % seed_bip32_b58)

        print("Seed Monero:      0x%s" %
              binascii.hexlify(hashed).decode("ascii"))
        print("Seed Monero wrds: %s" % electrum_words)

        print("")
        print("Spend key priv:   0x%s" %
              binascii.hexlify(crypto.encodeint(spend_sec)).decode("ascii"))
        print("View key priv:    0x%s" %
              binascii.hexlify(crypto.encodeint(view_sec)).decode("ascii"))
        print("")
        print("Spend key pub:    0x%s" %
              binascii.hexlify(crypto.encodepoint(spend_pub)).decode("ascii"))
        print("View key pub:     0x%s" %
              binascii.hexlify(crypto.encodepoint(view_pub)).decode("ascii"))

        self.init_with_keys(spend_sec, view_sec)
        print("")
        print("Address:          %s" % self.creds.address.decode("ascii"))

        self.account_data = collections.OrderedDict()
        self.account_data["seed"] = binascii.hexlify(seed).decode("ascii")
        self.account_data["spend_key"] = binascii.hexlify(
            crypto.encodeint(spend_sec)).decode("ascii")
        self.account_data["view_key"] = binascii.hexlify(
            crypto.encodeint(view_sec)).decode("ascii")
        self.account_data["meta"] = collections.OrderedDict([
            ("addr", self.creds.address.decode("ascii")),
            ("bip44_seed", binascii.hexlify(seed).decode("ascii")),
            ("bip32_39_words", " ".join(seed_bip32_words)),
            ("bip32_b58", seed_bip32_b58),
            ("monero_seed", binascii.hexlify(hashed).decode("ascii")),
            ("monero_words", electrum_words),
        ])

        if self.args.account_file:
            with open(self.args.account_file, "w+") as fh:
                json.dump(self.account_data, fh, indent=2)
        print("Wallet generated")
        self.update_prompt()