Exemplo n.º 1
0
def prove_rct_mg_simple(message, pubs, in_sk, a, cout, kLRki, mscout, index):
    """
    Simple version for when we assume only
        post rct inputs
        here pubs is a vector of (P, C) length mixin

    :param message:
    :param pubs: vector of CtKeys, public, point values, encoded form. (dest, mask) = (P, C)
    :param in_sk: CtKey, private. (spending private key, input commitment mask (original))
    :param a: mask from the pseudo_output commitment (alpha)
    :param cout: point, decoded. Pseudo output public key.
    :param kLRki:
    :param mscout: lambda accepting c
    :param index:
    :return:
    """
    rows = 1
    cols = len(pubs)
    if cols == 0:
        raise ValueError("Empty pubs")
    if (not kLRki or not mscout) and (kLRki and mscout):
        raise ValueError("Only one of kLRki/mscout is present")

    sk = key_vector(rows + 1)
    M = key_matrix(rows + 1, cols)

    sk[0] = in_sk.dest
    sk[1] = crypto.sc_sub(in_sk.mask, a)

    for i in range(cols):
        M[i][0] = crypto.decodepoint(pubs[i].dest)
        M[i][1] = crypto.point_sub(crypto.decodepoint(pubs[i].commitment),
                                   cout)

    return gen_mlsag_ext(message, M, sk, kLRki, mscout, index, rows)
Exemplo n.º 2
0
    async def _out_proc_range_proof(self, rsig):
        if self._is_req_bulletproof():
            rsig.V = []
            batch_size = self.ct.rsig_batches[self.ct.cur_batch_idx]
            for i in range(batch_size):
                commitment = self.ct.tx_out_pk[1 + self.ct.cur_output_idx -
                                               batch_size + i].mask
                commitment = crypto.scalarmult(crypto.decodepoint(commitment),
                                               crypto.sc_inv_eight())
                rsig.V.append(crypto.encodepoint(commitment))

        self.ct.tx_out_rsigs.append(rsig)

        # Rsig verification
        try:
            if not ring_ct.ver_range(
                    C=crypto.decodepoint(self.ct.tx_out_pk[-1].mask),
                    rsig=rsig,
                    use_bulletproof=self._is_req_bulletproof(),
            ):
                logger.warning("Rsing not valid")

        except Exception as e:
            logger.error("Exception rsig: %s" % e)
            traceback.print_exc()
Exemplo n.º 3
0
 async def derive_public_key(self):
     derivation = crypto.decodepoint(self._fetch_decrypt())
     output_index = self._fetch_u32()
     pub = crypto.decodepoint(self._fetch())
     drvpub = crypto.derive_public_key(derivation, output_index, pub)
     self._insert(crypto.encodepoint(drvpub))
     return SW_OK
Exemplo n.º 4
0
async def export_key_image(creds, subaddresses, td):
    """
    Key image export
    :param creds:
    :param subaddresses:
    :param td:
    :return:
    """
    out_key = crypto.decodepoint(td.out_key)
    tx_pub_key = crypto.decodepoint(td.tx_pub_key)
    additional_tx_pub_keys = []
    if not common.is_empty(td.additional_tx_pub_keys):
        additional_tx_pub_keys = [
            crypto.decodepoint(x) for x in td.additional_tx_pub_keys
        ]

    ki, sig = ring_ct.export_key_image(
        creds,
        subaddresses,
        out_key,
        tx_pub_key,
        additional_tx_pub_keys,
        td.internal_output_index if isinstance(td, MoneroTransferDetails) else
        td.m_internal_output_index,
    )

    return ki, sig
Exemplo n.º 5
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
Exemplo n.º 6
0
 async def derive_subaddress_public_key(self):
     pub = crypto.decodepoint(self._fetch())
     derivation = crypto.decodepoint(self._fetch_decrypt())
     output_index = self._fetch_u32()
     sub_pub = monero.derive_subaddress_public_key(pub, derivation,
                                                   output_index)
     self._insert(crypto.encodepoint(sub_pub))
     return SW_OK
Exemplo n.º 7
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
Exemplo n.º 8
0
    async def get_tx_key_test(self, agent, con_data, creds, all_creds):
        salt1 = con_data.enc_salt1
        salt2 = con_data.enc_salt2
        res = await agent.get_tx_key(salt1, salt2, con_data.enc_keys,
                                     con_data.tx_prefix_hash,
                                     creds.view_key_private)

        extras = await monero.parse_extra_fields(list(con_data.tx.extra))
        tx_pub = monero.find_tx_extra_field_by_type(extras,
                                                    xmrtypes.TxExtraPubKey, 0)
        additional_pub_keys = monero.find_tx_extra_field_by_type(
            extras, xmrtypes.TxExtraAdditionalPubKeys)

        # For verification need to build database creds -> pubkeys
        all_creds_subs = []
        for idx, ccred in enumerate(all_creds):
            subs = {}
            for accnt in range(10):
                subs = monero.compute_subaddresses(ccred, accnt, range(20),
                                                   subs)
            all_creds_subs.append(
                [crypto.decodepoint(xx) for xx in subs.keys()])

        if not self.verify_tx_key(res[0], crypto.decodepoint(tx_pub.pub_key),
                                  all_creds_subs):
            raise ValueError("Tx pub mismatch")

        if additional_pub_keys and len(
                additional_pub_keys.data) != len(res) - 1:
            raise ValueError("Invalid additional keys count")

        if additional_pub_keys:
            for i, ad in enumerate(additional_pub_keys.data):
                if not self.verify_tx_key(res[i + 1], crypto.decodepoint(ad),
                                          all_creds_subs):
                    raise ValueError("Tx additional %s pub mismatch" % i)

        my_pub = crypto.scalarmult_base(creds.view_key_private)
        res_der = await agent.get_tx_deriv(salt1, salt2, con_data.enc_keys,
                                           con_data.tx_prefix_hash,
                                           creds.view_key_private,
                                           crypto.encodepoint(my_pub))
        if len(res) != len(res_der):
            raise ValueError("Derivation array mismatch")
        tmp = crypto.scalarmult(my_pub, res[0])
        if not crypto.point_eq(tmp, res_der[0]):
            raise ValueError("Derivation 0 mismatch")

        if additional_pub_keys:
            for i in range(len(additional_pub_keys.data)):
                tmp = crypto.scalarmult(my_pub, res[i + 1])
                if not crypto.point_eq(tmp, res_der[i + 1]):
                    raise ValueError("Tx derivation additional %s mismatch" %
                                     i)
Exemplo n.º 9
0
 def test_encoding(self):
     point = unhexlify(
         b"2486224797d05cae3cba4be043be2db0df381f3f19cfa113f86ab38e3d8d2bd0"
     )
     self.assertEqual(point, crypto.encodepoint(crypto.decodepoint(point)))
     self.assertTrue(
         crypto.point_eq(
             crypto.decodepoint(point),
             crypto.decodepoint(
                 crypto.encodepoint(crypto.decodepoint(point))),
         ))
Exemplo n.º 10
0
def decode_ct_keys_points(vct, copy=False):
    """
    Decodes CtKeys vector as points
    :param vct:
    :param copy:
    :return:
    """
    rvct = copy_ct_keys(vct) if copy else vct
    for i in range(len(rvct)):
        rvct[i].mask = crypto.decodepoint(rvct[i].mask)
        rvct[i].dest = crypto.decodepoint(rvct[i].dest)
    return rvct
Exemplo n.º 11
0
    async def _on_set_outputs_ack(self, t_res):
        self.ct.tx.vout.append(await tmisc.parse_msg(t_res.tx_out,
                                                     xmrtypes.TxOut()))
        self.ct.tx_out_hmacs.append(t_res.vouti_hmac)
        self.ct.tx_out_pk.append(await tmisc.parse_msg(t_res.out_pk,
                                                       xmrtypes.CtKey()))
        self.ct.tx_out_ecdh.append(await
                                   tmisc.parse_msg(t_res.ecdh_info,
                                                   xmrtypes.EcdhTuple()))

        rsig_buff = None
        if t_res.rsig_data:
            tsig_data = t_res.rsig_data

            if tsig_data.rsig and len(tsig_data.rsig) > 0:
                rsig_buff = tsig_data.rsig
            elif tsig_data.rsig_parts and len(tsig_data.rsig_parts) > 0:
                rsig_buff = b"".join(tsig_data.rsig_parts)

        if rsig_buff and not self._is_req_bulletproof():
            rsig = await tmisc.parse_msg(rsig_buff, xmrtypes.RangeSig())
        elif rsig_buff:
            rsig = await tmisc.parse_msg(rsig_buff, xmrtypes.Bulletproof())
        else:
            return

        if self._is_req_bulletproof():
            rsig.V = []
            batch_size = self.ct.rsig_batches[self.ct.cur_batch_idx]
            for i in range(batch_size):
                commitment = self.ct.tx_out_pk[1 + self.ct.cur_output_idx -
                                               batch_size + i].mask
                commitment = crypto.scalarmult(crypto.decodepoint(commitment),
                                               crypto.sc_inv_eight())
                rsig.V.append(crypto.encodepoint(commitment))

        self.ct.tx_out_rsigs.append(rsig)

        # Rsig verification
        try:
            if not ring_ct.ver_range(
                    C=crypto.decodepoint(self.ct.tx_out_pk[-1].mask),
                    rsig=rsig,
                    use_bulletproof=self._is_req_bulletproof(),
            ):
                logger.warning("Rsing not valid")

        except Exception as e:
            logger.error("Exception rsig: %s" % e)
            traceback.print_exc()

        self.ct.cur_batch_idx += 1
        self.ct.cur_output_in_batch_idx = 0
Exemplo n.º 12
0
    async def set_input(self, src_entr):
        """
        :param src_entr:
        :type src_entr: xmrtypes.TxSourceEntry
        :return:
        """
        self.inp_idx += 1
        if src_entr.real_output >= len(src_entr.outputs):
            raise ValueError(
                "real_output index %s bigger than output_keys.size()"
                % (src_entr.real_output, len(src_entr.outputs))
            )
        self.summary_inputs_money += src_entr.amount

        out_key = crypto.decodepoint(src_entr.outputs[src_entr.real_output][1].dest)
        tx_key = crypto.decodepoint(src_entr.real_out_tx_key)
        additional_keys = [
            crypto.decodepoint(x) for x in src_entr.real_out_additional_tx_keys
        ]

        secs = monero.generate_key_image_helper(
            self.trezor.creds,
            self.subaddresses,
            out_key,
            tx_key,
            additional_keys,
            src_entr.real_output_in_tx_index,
        )
        xi, ki, di = secs
        self.input_secrets.append((xi,))
        self.input_rcts.append(src_entr.rct)

        # Construct tx.vin
        vini = xmrtypes.TxinToKey(
            amount=src_entr.amount, k_image=crypto.encodepoint(ki)
        )
        vini.key_offsets = [x[0] for x in src_entr.outputs]
        vini.key_offsets = monero.absolute_output_offsets_to_relative(vini.key_offsets)
        self.tx.vin.append(vini)

        # HMAC(T_in,i || vin_i)
        kwriter = monero.get_keccak_writer()
        ar = xmrserialize.Archive(kwriter, True)
        await ar.message(src_entr, xmrtypes.TxSourceEntry)
        await ar.message(vini, xmrtypes.TxinToKey)

        hmac_key_vini = crypto.keccak_hash(
            self.key_hmac + b"txin" + xmrserialize.dump_uvarint_b(self.inp_idx)
        )
        hmac_vini = crypto.compute_hmac(hmac_key_vini, kwriter.get_digest())

        return vini, hmac_vini
Exemplo n.º 13
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
Exemplo n.º 14
0
 def test_public_spend(self):
     derivation = binascii.unhexlify(
         b"e720a09f2e3a0bbf4e4ba7ad93653bb296885510121f806acb2a5f9168fafa01"
     )
     base = binascii.unhexlify(
         b"7d996b0f2db6dbb5f2a086211f2399a4a7479b2c911af307fdc3f7f61a88cb0e"
     )
     pkey_ex = binascii.unhexlify(
         b"0846cae7405077b6b7800f0b932c10a186448370b6db318f8c9e13f781dab546"
     )
     pkey_comp = crypto.derive_public_key(crypto.decodepoint(derivation), 0,
                                          crypto.decodepoint(base))
     self.assertEqual(pkey_ex, crypto.encodepoint(pkey_comp))
Exemplo n.º 15
0
    async def mlsag_prehash_update(self):
        is_subaddress = 0
        Aout = None
        Bout = None
        C = None
        v = None
        k = None
        changed = 0

        is_subaddress = bool(self._fetch_u8())
        Aout = crypto.decodepoint(self._fetch())
        Bout = crypto.decodepoint(self._fetch())
        if self.sig_mode == TRANSACTION_CREATE_REAL:
            if crypto.point_eq(Aout, self.A) and crypto.point_eq(Bout, self.B):
                changed = 1

        AKout = self._fetch_decrypt()
        C = self._fetch()
        k = self._fetch()
        v = self._fetch()

        self.ctx_h.update(k)
        self.ctx_h.update(v)

        self.ctx_amount.update(AKout)

        v, k, AKout = self.unblind_int(v, k, AKout)
        self.ctx_amount.update(crypto.encodeint(k))
        self.ctx_amount.update(crypto.encodeint(v))

        vH = crypto.scalarmult_h(v)
        kG = crypto.scalarmult_base(k)
        k = crypto.point_add(kG, vH)

        if not crypto.point_eq(k, crypto.decodepoint(C)):
            raise ValueError(SW_SECURITY_COMMITMENT_CONTROL)

        self.ctx_commitment.update(C)
        if self.options & IN_OPTION_MORE_COMMAND == 0:
            k = self.ctx_amount.digest()
            if not common.ct_equal(k, self.KV):
                raise ValueError(SW_SECURITY_AMOUNT_CHAIN_CONTROL)

            self.C = self.ctx_commitment.digest()
            self.ctx_commitment = sha256()

        if self.sig_mode == TRANSACTION_CREATE_REAL:
            if not changed:
                await self._req_dst(Aout, Bout, v, is_subaddress)

        return SW_OK
Exemplo n.º 16
0
 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))
Exemplo n.º 17
0
 def test_scalarmult(self):
     priv = unhexlify(
         b"3482fb9735ef879fcae5ec7721b5d3646e155c4fb58d6cc11c732c9c9b76620a"
     )
     pub = unhexlify(
         b"2486224797d05cae3cba4be043be2db0df381f3f19cfa113f86ab38e3d8d2bd0"
     )
     exp = unhexlify(
         b"adcd1f5881f46f254900a03c654e71950a88a0236fa0a3a946c9b8daed6ef43d"
     )
     res = crypto.scalarmult(crypto.decodepoint(pub),
                             crypto.decodeint(priv))
     self.assertEqual(exp, crypto.encodepoint(res))
     self.assertTrue(crypto.point_eq(crypto.decodepoint(exp), res))
Exemplo n.º 18
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)
Exemplo n.º 19
0
    def check_input(self, inp, new_keys, new_subs):
        real_out_key = inp.outputs[inp.real_output][1]
        tx_key = crypto.decodepoint(inp.real_out_tx_key)
        additional_keys = [
            crypto.decodepoint(x) for x in inp.real_out_additional_tx_keys
        ]

        _ = monero.generate_key_image_helper(
            new_keys,
            new_subs,
            crypto.decodepoint(real_out_key.dest),
            tx_key,
            additional_keys,
            inp.real_output_in_tx_index,
        )
Exemplo n.º 20
0
    async def open_with_keys(self, view_key, address):
        """
        Processess view key private + address
        :param view_key:
        :param address:
        :return:
        """
        self.pub_view = crypto.scalarmult_base(view_key)

        version, pub_spend, pub_view = monero.decode_addr(address)
        self.pub_spend = crypto.decodepoint(pub_spend)

        if not crypto.point_eq(self.pub_view, crypto.decodepoint(pub_view)):
            raise ValueError(
                "Computed view public key does not match the one from address")
Exemplo n.º 21
0
def scan_output(creds, tx, i, tx_scan_info, tx_money_got_in_outs, outs,
                multisig):
    """
    Wallet2::scan_output()
    Computes spending key, key image, decodes ECDH info, amount, checks masks.
    """
    if multisig:
        tx_scan_info.in_ephemeral = 0
        tx_scan_info.ki = crypto.identity()

    else:
        out_dec = crypto.decodepoint(tx.vout[i].target.key)
        res = generate_key_image_helper_precomp(creds, out_dec,
                                                tx_scan_info.received[1], i,
                                                tx_scan_info.received[0])
        tx_scan_info.in_ephemeral, tx_scan_info.ki = res
        if not tx_scan_info.ki:
            raise ValueError("Key error generation failed")

    outs.append(i)
    if tx_scan_info.money_transfered == 0:
        res2 = ecdh_decode_rv(tx.rct_signatures, tx_scan_info.received[1], i)
        tx_scan_info.money_transfered, tx_scan_info.mask = res2
        tx_scan_info.money_transfered = crypto.sc_get64(
            tx_scan_info.money_transfered)

    tx_money_got_in_outs[
        tx_scan_info.received[0]] += tx_scan_info.money_transfered
    tx_scan_info.amount = tx_scan_info.money_transfered
    return tx_scan_info
Exemplo n.º 22
0
    async def analyze_input(self, keys, subs, inp):
        subs = subs if subs else {}
        real_out_key = inp.outputs[inp.real_output][1]
        out_key = crypto.decodepoint(real_out_key.dest)
        tx_key = crypto.decodepoint(inp.real_out_tx_key)
        additional_keys = [
            crypto.decodepoint(x) for x in inp.real_out_additional_tx_keys
        ]

        res = generate_key_image_ex(
            keys, subs, out_key, tx_key, additional_keys, inp.real_output_in_tx_index
        )

        xi, ki, recv_derivation, subaddr_recv_info = res
        sub_idx = subaddr_recv_info[0]
        return sub_idx
Exemplo n.º 23
0
 async def derive_secret_key(self):
     derivation = crypto.decodepoint(self._fetch_decrypt())
     output_index = self._fetch_u32()
     sec = self._fetch_decrypt_key()
     drvsec = crypto.derive_secret_key(derivation, output_index, sec)
     self._insert_encrypt(crypto.encodeint(drvsec))
     return SW_OK
Exemplo n.º 24
0
def decode_points(vct):
    """
    Decodes vector of points
    :param vct:
    :return:
    """
    return [crypto.decodepoint(x) for x in vct]
Exemplo n.º 25
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
Exemplo n.º 26
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)
Exemplo n.º 27
0
 def test_clsag_invalid_P(self):
     res = self.gen_clsag_sig(ring_size=11, index=5)
     msg, scalars, sc1, sI, sD, ring2, Cp = res
     with self.assertRaises(ValueError):
         ring2[5].commitment = crypto.encodepoint(
             crypto.point_mul8(crypto.decodepoint(ring2[5].dest)))
         mlsag2.verify_clsag(msg, scalars, sc1, sI, sD, ring2, Cp)
Exemplo n.º 28
0
    async def process_payment_id(self):
        """
        Payment id -> extra
        :return:
        """
        if self.tsx_data.payment_id is None or len(self.tsx_data.payment_id) == 0:
            return

        change_addr = (
            self.tsx_data.change_dts.addr if self.tsx_data.change_dts else None
        )
        view_key_pub_enc = monero.get_destination_view_key_pub(
            self.tsx_data.outputs, change_addr
        )
        if view_key_pub_enc == crypto.NULL_KEY_ENC:
            raise ValueError(
                "Destinations have to have exactly one output to support encrypted payment ids"
            )

        view_key_pub = crypto.decodepoint(view_key_pub_enc)
        payment_id_encr = monero.encrypt_payment_id(
            self.tsx_data.payment_id, view_key_pub, self.r
        )

        extra_nonce = monero.set_encrypted_payment_id_to_tx_extra_nonce(payment_id_encr)
        self.tx.extra = monero.add_extra_nonce_to_tx_extra(b"", extra_nonce)
Exemplo n.º 29
0
    async def init_transaction(self, tsx_data, tsx_ctr):
        """
        Initializes a new transaction.
        :param tsx_data:
        :param tsx_ctr:
        :return:
        """
        self.tsx_data = tsx_data
        self.gen_r()

        # Additional keys
        class_res = classify_subaddresses(
            tsx_data.outputs, tsx_data.change_dts.addr if tsx_data.change_dts else None
        )
        num_stdaddresses, num_subaddresses, single_dest_subaddress = class_res

        # if this is a single-destination transfer to a subaddress, we set the tx pubkey to R=s*D
        if num_stdaddresses == 0 and num_subaddresses == 1:
            self.r_pub = crypto.ge_scalarmult(
                self.r, crypto.decodepoint(single_dest_subaddress.m_spend_public_key)
            )

        self.need_additional_txkeys = num_subaddresses > 0 and (
            num_stdaddresses > 0 or num_subaddresses > 1
        )
        if self.need_additional_txkeys:
            for _ in range(len(tsx_data.outputs)):
                self.additional_tx_keys.append(crypto.random_scalar())

        # Extra processing, payment id
        self.tx.version = 2
        self.tx.unlock_time = tsx_data.unlock_time
        await self.process_payment_id()
        await self.compute_hmac_keys(tsx_ctr)
Exemplo n.º 30
0
def check_acc_out_precomp(tx_out, subaddresses, derivation, additional_derivations, i):
    """
    wallet2::check_acc_out_precomp
    Detects whether the tx output belongs to the subaddresses. If yes, computes the derivation.
    Returns TxScanInfo

    :param tx_out:
    :param derivation:
    :param additional_derivations:
    :param i:
    :return:
    """
    tx_scan_info = TxScanInfo()
    tx_scan_info.error = True

    if not isinstance(tx_out.target, xmrtypes.TxoutToKey):
        return tx_scan_info

    tx_scan_info.received = is_out_to_acc_precomp(
        subaddresses,
        crypto.decodepoint(tx_out.target.key),
        derivation,
        additional_derivations,
        i,
    )
    if tx_scan_info.received:
        tx_scan_info.money_transfered = tx_out.amount
    else:
        tx_scan_info.money_transfered = 0
    tx_scan_info.error = False
    return tx_scan_info