Beispiel #1
0
    def poc2(self):
        print('[+] PoC Ledger-app-Monero 1.4.2 spend key extraction, v2')
        self.reset()
        self.set_mode()
        self.open_tx()

        # 1. get A, find x, s.t.: [8*a*x*G]_pt == [8*a*x*G]_sc
        A = self.scalarmult(self.fake_a)
        Apt = crypto.decodepoint(A)
        x, A8x = self.find_confusion(Apt)
        Gx = crypto.encodepoint(crypto.scalarmult_base(crypto.sc_init(x)))

        print('  1. Confusion found, x: %d' % (x, ))
        print('     8xA:  %s' % binascii.hexlify(A8x).decode('ascii'))
        print('       A:  %s' % binascii.hexlify(A).decode('ascii'))
        print('      xG:  %s' % binascii.hexlify(Gx).decode('ascii'))

        # 2. gen_deriv (8*a*x*G) = enc(8x*A) = enc(P); we know {P, enc(P)};
        # It holds that P=8xA is also a valid scalar value, from the step above.
        P = self.gen_derivation(Gx, self.fake_a)
        print('  2.   P:  %s' % (self.fmtkey(P).decode('ascii'), ))

        # 3. get_secret_key: s1 = Hs(P||0) + s
        sp = self.derive_secret_key(P, 0, self.fake_b)
        print('  3.   sp: %s' % (self.fmtkey(sp).decode('ascii'), ))

        # 4. mlsag_hash(p2=1, opt=0x80) = c
        c = self.mlsag_hash()
        print('  4.   c:  %s' % (binascii.hexlify(c).decode('ascii'), ))

        # 5. mlsag_sign(s1, enc(P)), r1 = enc(s1 - Pc) = enc(Hs(P||0) + s - Pc);
        # We have R = Hs(P||0) + s - Pc -> R - Hs(P||0) + Pc = s
        r = self.mlsag_sign_s(P, sp)
        print('  5.   r:  %s' % (binascii.hexlify(r[0]).decode('ascii'), ))

        # Extract the spend key
        hs0 = crypto.hash_to_scalar(bytearray(A8x) + bytearray(1))
        rsc = crypto.decodeint(r[0])
        rsc = crypto.sc_sub(rsc, hs0)
        bsc = crypto.sc_add(
            rsc, crypto.sc_mul(crypto.decodeint(c), crypto.decodeint(A8x)))
        b = crypto.encodeint(bsc)
        print('  5.   b:  %s' % binascii.hexlify(b).decode('ascii'))

        B = crypto.scalarmult_base(bsc)
        print('  5.   B:  %s' %
              binascii.hexlify(crypto.encodepoint(B)).decode('ascii'))

        # 6. Verify
        BB = self.scalarmult(self.fake_b)
        print('  6.   bG: %s\n' % binascii.hexlify(BB).decode('ascii'))

        if BB == crypto.encodepoint(B):
            print('[+] PoC successful')
        else:
            print('[-] PoC not working')

        print('\nCommands: ')
        for x in self.commands:
            print('  %s' % x)
Beispiel #2
0
    async def live_refresh(self, view_key_private, out_key, recv_deriv,
                           real_out_idx, major, minor):
        msg = MoneroLiveRefreshStepRequest(
            out_key=out_key,
            recv_deriv=recv_deriv,
            real_out_idx=real_out_idx,
            sub_addr_major=major,
            sub_addr_minor=minor,
        )
        t_res = await self.trezor.live_refresh(
            msg)  # type: MoneroLiveRefreshStepAck
        self.handle_error(t_res)

        enc_key = self._compute_ki_enc_key_host(view_key_private, out_key,
                                                t_res.salt)
        decr = chacha_poly.decrypt_pack(enc_key, t_res.key_image)

        ki_bin = decr[:32]
        ki = crypto.decodepoint(ki_bin)
        sig = [[crypto.decodeint(decr[32:64]), crypto.decodeint(decr[64:])]]

        if not ring_ct.check_ring_singature(
                ki_bin, ki, [crypto.decodepoint(out_key)], sig):
            raise ValueError("Invalid ring sig on KI")

        return ki
Beispiel #3
0
    async def _rct_offload(self, idx, dst):
        if (self.ct.rsig_batches[self.ct.cur_batch_idx] >
                self.ct.cur_output_in_batch_idx):
            return None

        rsig_data = MoneroTransactionRsigData()
        batch_size = self.ct.rsig_batches[self.ct.cur_batch_idx]

        if not self._is_req_bulletproof():
            if batch_size > 1:
                raise ValueError("Borromean cannot batch outputs")

            mask = crypto.decodeint(self.ct.rsig_gamma[idx])
            C, a, R = ring_ct.prove_range_mem(dst.amount, mask)
            rsig_data.rsig = tmisc.dump_msg(R)
            self.ct.tx_out_rsigs.append(R)

        else:
            amounts = []
            masks = []
            for i in range(batch_size):
                amounts.append(
                    self.ct.tx_data.splitted_dsts[1 + idx - batch_size +
                                                  i].amount)
                masks.append(
                    crypto.decodeint(self.ct.rsig_gamma[1 + idx - batch_size +
                                                        i]))

            bp = await ring_ct.prove_range_bp_batch(amounts, masks)
            self.ct.tx_out_rsigs.append(bp)

            rsig_data.rsig = await tmisc.dump_msg(bp)
        return rsig_data
Beispiel #4
0
    async def mlsag_prepare(self):
        Hi = None
        xin = None
        options = 0

        if len(self.c_msg) > 1:
            options = 1
            Hi = crypto.decodepoint(self._fetch())
            if self.options & 0x40:
                xin = crypto.decodeint(self._fetch())
            else:
                xin = crypto.decodeint(self._fetch_decrypt())

        alpha = crypto.random_scalar()
        self._insert_encrypt(crypto.encodeint(alpha))

        # ai.G
        self._insert(crypto.encodepoint(crypto.scalarmult_base(alpha)))

        if options:
            # ai * Hi
            self._insert(crypto.encodepoint(crypto.scalarmult(Hi, alpha)))
            # xin * Hi
            self._insert(crypto.encodepoint(crypto.scalarmult(Hi, xin)))
        return SW_OK
Beispiel #5
0
    def unblind_int(self, v, k, AKout):
        AKout = crypto.hash_to_scalar(AKout)
        k = crypto.sc_sub(crypto.decodeint(k), AKout)

        AKout = crypto.hash_to_scalar(crypto.encodeint(AKout))
        v = crypto.sc_sub(crypto.decodeint(v), AKout)

        return v, k, AKout
Beispiel #6
0
 def __init__(self, secret_exponent=None, key=None, hex_key=None, *args, **kwargs):
     self._hex_key = hex_key
     self._key = None
     if secret_exponent:
         self._key = crypto.decodeint(bytes(ec_py.EdScalar(secret_exponent)))
     elif hex_key:
         self._key = crypto.decodeint(hex_key)
     else:
         self._key = key
Beispiel #7
0
    async def open_account(self):
        """
        Handles account open / management
        :return:
        """
        self.update_intro()
        self.update_prompt()

        priv_spend_key = None
        priv_view_key = None

        if not self.args.account_file and not self.args.spend_key:
            logger.debug(
                "No account file nor spend key. Please generate new account")
            return

        acc_file_exists = False
        if self.args.account_file:
            acc_file_exists = os.path.exists(self.args.account_file)

            if acc_file_exists and self.args.spend_key:
                logger.error("Account file exists, spend key is ignored")
            if acc_file_exists and self.args.view_key:
                logger.error("Account file exists, view key is ignored")
            if acc_file_exists:
                with open(self.args.account_file) as fh:
                    self.account_data = json.load(fh)
                priv_spend_key = crypto.decodeint(
                    binascii.unhexlify(
                        self.account_data["spend_key"].encode("ascii")))
                priv_view_key = crypto.decodeint(
                    binascii.unhexlify(
                        self.account_data["view_key"].encode("ascii")))

        if not acc_file_exists and self.args.spend_key:
            priv_view = self.args.view_key.encode("utf8")
            priv_spend = self.args.spend_key.encode("utf8")
            priv_view_key = crypto.b16_to_scalar(priv_view)
            priv_spend_key = crypto.b16_to_scalar(priv_spend)

            self.account_data = {
                "spend_key": priv_spend_key,
                "view_key": priv_view_key
            }
            with open(self.args.account_file, "w") as fh:
                json.dump(
                    {
                        "spend_key": priv_spend.decode("ascii"),
                        "view_key": priv_view.decode("ascii"),
                    },
                    fh,
                    indent=2,
                )

        if priv_spend_key and priv_view_key:
            self.init_with_keys(priv_spend_key, priv_view_key)
Beispiel #8
0
    def gen_clsag_sig(self, ring_size=11, index=None):
        msg = bytearray(random.getrandbits(8) for _ in range(32))
        amnt = crypto.sc_init(random.randint(0, 0xFFFFFF) + 12)
        priv = crypto.random_scalar()
        msk = crypto.random_scalar()
        alpha = crypto.random_scalar()
        P = crypto.scalarmult_base(priv)
        C = crypto.add_keys2(msk, amnt, crypto.xmr_H())
        Cp = crypto.add_keys2(alpha, amnt, crypto.xmr_H())

        ring = []
        for i in range(ring_size - 1):
            tk = TmpKey(
                crypto.encodepoint(
                    crypto.scalarmult_base(crypto.random_scalar())),
                crypto.encodepoint(
                    crypto.scalarmult_base(crypto.random_scalar())),
            )
            ring.append(tk)

        index = index if index is not None else random.randint(0, len(ring))
        ring.insert(index, TmpKey(crypto.encodepoint(P),
                                  crypto.encodepoint(C)))
        ring2 = list(ring)
        mg_buffer = []

        self.assertTrue(
            crypto.point_eq(crypto.scalarmult_base(priv),
                            crypto.decodepoint(ring[index].dest)))
        self.assertTrue(
            crypto.point_eq(
                crypto.scalarmult_base(crypto.sc_sub(msk, alpha)),
                crypto.point_sub(crypto.decodepoint(ring[index].commitment),
                                 Cp),
            ))

        mlsag2.generate_clsag_simple(
            msg,
            ring,
            CtKey(dest=priv, mask=msk),
            alpha,
            Cp,
            index,
            mg_buffer,
        )

        sD = crypto.decodepoint(mg_buffer[-1])
        sc1 = crypto.decodeint(mg_buffer[-2])
        scalars = [crypto.decodeint(x) for x in mg_buffer[1:-2]]
        H = crypto.new_point()
        sI = crypto.new_point()

        crypto.hash_to_point_into(H, crypto.encodepoint(P))
        crypto.scalarmult_into(sI, H, priv)  # I = p*H
        return msg, scalars, sc1, sI, sD, ring2, Cp
Beispiel #9
0
    async def put_key(self):
        sec = crypto.decodeint(self._fetch(32))
        pub = crypto.decodepoint(self._fetch(32))
        if not crypto.point_eq(pub, crypto.scalarmult_base(sec)):
            return SW_WRONG_DATA
        self.a = sec

        sec = crypto.decodeint(self._fetch(32))
        pub = crypto.decodepoint(self._fetch(32))
        if not crypto.point_eq(pub, crypto.scalarmult_base(sec)):
            return SW_WRONG_DATA
        self.b = sec
        return SW_OK
Beispiel #10
0
    def parse_keys(self, keyvar, ktype="current"):
        if keyvar is None:
            return None
        if len(keyvar) != 2 * 2 * 32:
            raise ValueError(
                "Keys for the %s destination length invalid. Format: SpendKey || ViewKey hexcoded"
                % ktype
            )
        keys_bin = binascii.unhexlify(keyvar)
        spend_key = crypto.decodeint(keys_bin[:32])
        view_key = crypto.decodeint(keys_bin[32:64])

        return AccountCreds.new_wallet(view_key, spend_key)
Beispiel #11
0
def generate_monero_keys(seed):
    """
    Generates spend key / view key from the seed in the same manner as Monero code does.

    account.cpp:
    crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random).
    :param seed:
    :return:
    """
    spend_sec, spend_pub = generate_keys(crypto.decodeint(seed))
    hash = crypto.cn_fast_hash(crypto.encodeint(spend_sec))
    view_sec, view_pub = generate_keys(crypto.decodeint(hash))
    return spend_sec, spend_pub, view_sec, view_pub
 async def verify_ki_export(self, res, exp):
     """
     Verifies key image export
     :param res:
     :param exp:
     :return:
     """
     self.assertTrue(len(res) > 0)
     for idx, kie in enumerate(res):
         td = exp.tds[idx]
         ki = crypto.decodepoint(kie[0])
         pkey = crypto.decodepoint(td.m_tx.vout[td.m_internal_output_index].target.key)
         sig = [[crypto.decodeint(kie[1][0]), crypto.decodeint(kie[1][1])]]
         self.assertTrue(ring_ct.check_ring_singature(kie[0], ki, [pkey], sig))
Beispiel #13
0
    async def mlsag_sign(self):
        if self.sig_mode == TRANSACTION_CREATE_FAKE:
            xin = crypto.decodeint(self._fetch())
            alpha = crypto.decodeint(self._fetch())
        elif self.sig_mode == TRANSACTION_CREATE_REAL:
            xin = crypto.decodeint(self._fetch_decrypt())
            alpha = crypto.decodeint(self._fetch_decrypt())
        else:
            raise ValueError("Invalid mode")

        ss2 = crypto.sc_mulsub(self.c, xin, alpha)
        self._insert(crypto.encodeint(ss2))
        self._insert_u32(self.sig_mode)
        return SW_OK
Beispiel #14
0
    def verify_monero_generated(self, clsag):
        msg = ubinascii.unhexlify(clsag["msg"])
        sI = crypto.decodepoint(ubinascii.unhexlify(clsag["sI"]))
        sD = crypto.decodepoint(ubinascii.unhexlify(clsag["sD"]))
        sc1 = crypto.decodeint(ubinascii.unhexlify(clsag["sc1"]))
        Cout = crypto.decodepoint(ubinascii.unhexlify(clsag["cout"]))
        scalars = [
            crypto.decodeint(ubinascii.unhexlify(x)) for x in clsag["ss"]
        ]
        ring = []
        for e in clsag["ring"]:
            ring.append(
                TmpKey(ubinascii.unhexlify(e[0]), ubinascii.unhexlify(e[1])))

        mlsag2.verify_clsag(msg, scalars, sc1, sI, sD, ring, Cout)
Beispiel #15
0
def ecdh_encdec(masked, receiver_sk=None, derivation=None, v2=False, enc=True, dest=None):
    """
    Elliptic Curve Diffie-Helman: encodes and decodes the amount b and mask a
    where C= aG + bH
    """
    rv = xmrtypes.EcdhTuple() if dest is None else dest
    if derivation is None:
        derivation = crypto.scalarmult(masked.senderPk, receiver_sk)

    if v2:
        amnt = masked.amount
        rv.mask = monero.commitment_mask(derivation)
        rv.amount = bytearray(32)
        crypto.encodeint_into(rv.amount, amnt)
        crypto.xor8(rv.amount, monero.ecdh_hash(derivation))
        rv.amount = crypto.decodeint(rv.amount)
        return rv

    else:
        amount_key_hash_single = crypto.hash_to_scalar(derivation)
        amount_key_hash_double = crypto.hash_to_scalar(
            crypto.encodeint(amount_key_hash_single)
        )

        sc_fnc = crypto.sc_add if enc else crypto.sc_sub
        rv.mask = sc_fnc(masked.mask, amount_key_hash_single)
        rv.amount = sc_fnc(masked.amount, amount_key_hash_double)
        return rv
Beispiel #16
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
Beispiel #17
0
def ver_borromean(P1, P2, s0, s1, ee):
    """
    Verify range proof signature, Borromean
    (c.f. gmax/andytoshi's paper)
    :param P1:
    :param P2:
    :param s0:
    :param s1:
    :param ee:
    :return:
    """
    n = len(P1)
    Lv1 = key_vector(n)
    for ii in range(n):
        LL = crypto.add_keys2(s0[ii], ee, P1[ii])
        chash = crypto.hash_to_scalar(crypto.encodepoint(LL))
        Lv1[ii] = crypto.add_keys2(s1[ii], chash, P2[ii])

    kck = crypto.get_keccak()
    for ii in range(n):
        kck.update(crypto.encodepoint(Lv1[ii]))

    # ee_computed = crypto.hash_to_scalar(crypto.encodepoint(Lv1))
    ee_computed = crypto.decodeint(kck.digest())

    return crypto.sc_eq(ee_computed, ee)
Beispiel #18
0
    def extra_poc(self, zero, hs0, B):
        #  --- Extra ---
        # Extract view key and address reconstruction.
        # Not needed for the PoC
        print('\nExtracting view-key...')
        encr = self.derive_secret_key(zero, 0, self.fake_a)
        r = self.mlsag_sign_s(zero, encr)
        rsc = crypto.decodeint(r[0])
        asc = crypto.sc_sub(rsc, hs0)
        a = crypto.encodeint(asc)
        print('  a:  %s' % binascii.hexlify(a).decode('ascii'))

        A = crypto.scalarmult_base(asc)
        print('  A:  %s' %
              binascii.hexlify(crypto.encodepoint(A)).decode('ascii'))

        AA = self.scalarmult(self.fake_a)
        print('  aG: %s' % binascii.hexlify(AA).decode('ascii'))

        main_addr = addr.encode_addr(
            xmr_net.net_version(xmr_net.NetworkTypes.MAINNET),
            crypto.encodepoint(B),
            crypto.encodepoint(A),
        )

        test_addr = addr.encode_addr(
            xmr_net.net_version(xmr_net.NetworkTypes.TESTNET),
            crypto.encodepoint(B),
            crypto.encodepoint(A),
        )

        print('Mainnet address: %s' % main_addr.decode('ascii'))
        print('Testnet address: %s' % test_addr.decode('ascii'))
Beispiel #19
0
    async def load_watchonly(self):
        """
        Loads watch-only credentials from connected Trezor
        :return:
        """
        if not await self.is_connected():
            logger.error("Trezor is not connected")
            raise agent_misc.TrezorNotRunning(
                "Could not load watch-only credentials")

        try:
            print(
                "Loading watch-only credentials from Trezor. Please, confirm the request on Trezor."
            )
            self.set_network_type(monero.NetworkTypes.TESTNET if self.args.
                                  testnet else monero.NetworkTypes.MAINNET)

            res = await self.agent.get_watch_only(
            )  # type: messages.MoneroWatchKey

            self.priv_view = crypto.decodeint(res.watch_key)
            self.address = res.address
            await self.open_with_keys(self.priv_view, self.address)

        except Exception as e:
            raise ValueError(e)
Beispiel #20
0
    def set_seed(self, seed, path=None, slip0010=False):
        """
        Sets master secret for BIP44 derivation
        :param seed:
        :param path:
        :param slip0010:
        :return:
        """
        self.master_seed = seed
        self.is_slip0010 = slip0010
        if path is None:
            self.path = DEFAULT_BIP44_PATH if not slip0010 else DEFAULT_SLIP0010_PATH
        else:
            self.path = path
        wl = bip32.Wallet.from_master_secret(seed, use_ed25519=slip0010)

        # Generate private keys based on the gen mechanism. Bip44 path + Monero backward compatible
        data = wl.get_child_for_path(self.path)
        self.pre_hash = binascii.unhexlify(data.private_key.get_key())

        if slip0010:
            self.monero_master = crypto.encodeint(
                crypto.decodeint(self.pre_hash))

        else:
            # Ledger way = words -> bip39 pbkdf -> master seed -> bip32 normal with
            #  "Bitcoin seed" seed, get private key node -> cn_fast_hash -> monero master secret
            self.monero_master = crypto.cn_fast_hash(self.pre_hash)

        self.set_monero_seed(self.monero_master)
Beispiel #21
0
    async def amplify_inputs(self, tx, new_keys=None, new_subs=None):
        lst = tx.sources[-1]
        orig_amount = lst.amount
        partial = orig_amount // (self.args.inputs + 1)

        amnt_sum = partial
        lst.amount = partial
        commitment = crypto.encodepoint(crypto.gen_c(crypto.decodeint(lst.mask), partial))
        lst.outputs[lst.real_output][1].mask = commitment

        for i in range(1, self.args.inputs + 1):
            is_lst = i >= self.args.inputs
            new_amnt = orig_amount - amnt_sum if is_lst else partial
            amnt_sum += partial

            commitment = crypto.encodepoint(crypto.gen_c(crypto.decodeint(lst.mask), new_amnt))
            new_inp = TxSourceEntry(outputs=list(lst.outputs),
                                    real_output=lst.real_output,
                                    real_out_tx_key=lst.real_out_tx_key,
                                    real_out_additional_tx_keys=lst.real_out_additional_tx_keys,
                                    real_output_in_tx_index=lst.real_output_in_tx_index,
                                    amount=new_amnt,
                                    rct=lst.rct,
                                    mask=lst.mask,
                                    multisig_kLRki=lst.multisig_kLRki)

            # Amount changed -> update the commitment
            orig_key = new_inp.outputs[new_inp.real_output][1]
            new_inp.outputs[new_inp.real_output] = (0, CtKey(dest=orig_key.dest, mask=commitment))

            # Randomize mixin values
            for i in range(new_inp.real_output + 1, len(new_inp.outputs)):
                new_inp.outputs[i] = (0, CtKey(
                    mask=crypto.encodepoint(self.random_pub()),
                    dest=crypto.encodepoint(self.random_pub())))

                if new_inp.real_out_additional_tx_keys:
                    new_inp.real_out_additional_tx_keys[i] = crypto.encodepoint(self.random_pub())

            self.check_input(new_inp, new_keys, new_subs)

            if not crypto.point_eq(
                    crypto.decodepoint(new_inp.outputs[new_inp.real_output][1].mask),
                    crypto.gen_c(crypto.decodeint(new_inp.mask), new_inp.amount),
                ): raise ValueError("Real source entry's mask does not equal spend key's")

            tx.sources.append(new_inp)
Beispiel #22
0
def gen_mlsag_ext(message, pk, xx, kLRki, mscout, index, dsRows):
    """
    Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)

    :param message:
    :param pk: matrix of points, point form (not encoded)
    :param xx:
    :param kLRki:
    :param mscout:
    :param index:
    :param dsRows:
    :return:
    """
    rows, cols = gen_mlsag_assert(pk, xx, kLRki, mscout, index, dsRows)

    rv = xmrtypes.MgSig()
    c, L, R, Hi = 0, None, None, None

    c_old, Ip, alpha = gen_mlsag_rows(message, rv, pk, xx, kLRki, index,
                                      dsRows, rows, cols)

    i = (index + 1) % cols
    if i == 0:
        rv.cc = c_old

    while i != index:
        rv.ss[i] = scalar_gen_vector(rows)
        hasher = hasher_message(message)

        for j in range(dsRows):
            L = crypto.add_keys2(rv.ss[i][j], c_old, pk[i][j])
            Hi = crypto.hash_to_point(crypto.encodepoint(
                pk[i][j]))  # originally hashToPoint()
            R = crypto.add_keys3(rv.ss[i][j], Hi, c_old, Ip[j])
            hasher.update(crypto.encodepoint(pk[i][j]))
            hasher.update(crypto.encodepoint(L))
            hasher.update(crypto.encodepoint(R))

        for j in range(dsRows, rows):
            L = crypto.add_keys2(rv.ss[i][j], c_old, pk[i][j])
            hasher.update(crypto.encodepoint(pk[i][j]))
            hasher.update(crypto.encodepoint(L))

        c = crypto.decodeint(hasher.digest())
        c_old = c
        i = (i + 1) % cols

        if i == 0:
            rv.cc = c_old

    for j in range(rows):
        rv.ss[index][j] = crypto.sc_mulsub(
            c, xx[j],
            alpha[j])  # alpha[j] - c * xx[j]; sc_mulsub in original does c-ab

    if mscout:
        mscout(c)

    return rv, c
Beispiel #23
0
    async def _step_set_outputs(self, idx, dst):
        self.ct.cur_output_idx = idx
        self.ct.cur_output_in_batch_idx += 1

        msg = MoneroTransactionSetOutputRequest(
            dst_entr=tmisc.translate_monero_dest_entry_pb(dst),
            dst_entr_hmac=self.ct.tx_out_entr_hmacs[idx],
        )

        # Range sig offloading to the host
        if not self._is_offloading():
            return msg

        if (self.ct.rsig_batches[self.ct.cur_batch_idx] >
                self.ct.cur_output_in_batch_idx):
            return msg

        rsig_data = MoneroTransactionRsigData()
        batch_size = self.ct.rsig_batches[self.ct.cur_batch_idx]

        if not self._is_req_bulletproof():
            if batch_size > 1:
                raise ValueError("Borromean cannot batch outputs")

            mask = crypto.decodeint(self.ct.rsig_gamma[idx])
            C, a, R = ring_ct.prove_range_mem(dst.amount, mask)
            rsig_data.rsig = tmisc.dump_msg(R)
            self.ct.tx_out_rsigs.append(R)

        else:
            amounts = []
            masks = []
            for i in range(batch_size):
                amounts.append(
                    self.ct.tx_data.splitted_dsts[1 + idx - batch_size +
                                                  i].amount)
                masks.append(
                    crypto.decodeint(self.ct.rsig_gamma[1 + idx - batch_size +
                                                        i]))

            bp = await ring_ct.prove_range_bp_batch(amounts, masks)
            self.ct.tx_out_rsigs.append(bp)

            rsig_data.rsig = await tmisc.dump_msg(bp)
        msg.rsig_data = rsig_data
        return msg
Beispiel #24
0
    async def blind(self):
        AKout = self._fetch_decrypt(32)
        k = self._fetch(32)
        v = self._fetch(32)

        self.ctx_amount.update(AKout)
        self.ctx_amount.update(k)
        self.ctx_amount.update(v)

        AKout = crypto.hash_to_scalar(AKout)
        k = crypto.sc_add(crypto.decodeint(k), AKout)

        AKout = crypto.hash_to_scalar(crypto.encodeint(AKout))
        v = crypto.sc_add(crypto.decodeint(v), AKout)

        self._insert(crypto.encodeint(v))
        self._insert(crypto.encodeint(k))
        return SW_OK
Beispiel #25
0
 async def get_subaddress_secret_key(self):
     sec = crypto.decodeint(self._fetch_decrypt())
     index = self._fetch(8)
     major, minor = self._idx_parse(index)
     sub_sec = monero.get_subaddress_secret_key(sec,
                                                major=major,
                                                minor=minor)
     self._insert_encrypt(crypto.encodeint(sub_sec))
     return SW_OK
Beispiel #26
0
 def find_confusion(self, A, N=10000):
     """find x, s.t.: [8*x*A]_pt == [8*x*A]_sc"""
     for i in range(1, N):
         Ac = crypto.scalarmult(A, crypto.sc_init(i * 8))
         Ab = crypto.encodepoint(Ac)
         red = crypto.encodeint(crypto.decodeint(Ab))
         if red == Ab:
             return i, Ab
     raise ValueError('Could not find a confusion parameter!')
Beispiel #27
0
 async def get_tx_key(self, salt1, salt2, tx_enc_keys, tx_prefix_hash,
                      view_key_priv):
     decr = await self._get_tx_key_intern(salt1, salt2, tx_enc_keys,
                                          tx_prefix_hash, view_key_priv)
     n_keys = len(decr) // 32
     res = []
     for i in range(n_keys):
         res.append(crypto.decodeint(decr[i * 32:(i + 1) * 32]))
     return res
Beispiel #28
0
 def _fetch_decrypt_key(self):
     buff = self._fetch()
     if buff == b"\x00" * 32:
         return self.a
     elif buff == b"\xff" * 32:
         return self.b
     else:
         return crypto.decodeint(aescbc.decrypt(self.key_enc, buff,
                                                self.iv))
Beispiel #29
0
 def test_hash_to_scalar(self):
     inp = unhexlify(
         b"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff6405"
     )
     res = crypto.hash_to_scalar(inp)
     exp = crypto.decodeint(
         binascii.unhexlify(
             b"9907925b254e12162609fc0dfd0fef2aa4d605b0d10e6507cac253dd31a3ec06"
         ))
     self.assertTrue(crypto.sc_eq(res, exp))
def pttest2(N=10000):
    a = crypto.random_scalar()
    a8 = crypto.sc_mul(a, crypto.sc_init(8))
    for i in range(1, N):
        ca = crypto.sc_mul(a8, crypto.sc_init(i))
        A8 = crypto.scalarmult_base(ca)
        A8bin = crypto.encodepoint(A8)
        red = crypto.encodeint(crypto.decodeint(A8bin))
        if red == A8bin:
            return i, red
    return None