Exemple #1
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
Exemple #2
0
def ver_asnl(P1, P2, L1, s2, s):
    """
    Aggregate Schnorr Non-Linkable
    :param P1:
    :param P2:
    :param L1:
    :param s2:
    :param s:
    :return:
    """
    logger.info("Verifying Aggregate Schnorr Non-linkable Ring Signature")

    n = len(P1)
    LHS = crypto.scalarmult_base(crypto.sc_0())
    RHS = crypto.scalarmult_base(s)
    for j in range(0, n):
        c2 = crypto.hash_to_scalar(crypto.encodepoint(L1[j]))
        L2 = crypto.point_add(crypto.scalarmult_base(s2[j]),
                              crypto.scalarmult(P2[j], c2))
        LHS = crypto.point_add(LHS, L1[j])
        c1 = crypto.hash_to_scalar(crypto.encodepoint(L2))
        RHS = crypto.point_add(RHS, crypto.scalarmult(P1[j], c1))

    if crypto.point_eq(LHS, RHS):
        return 1
    else:
        logger.warning("Didn't verify L1: %s, L1p: %s" %
                       (crypto.encodepoint(LHS), crypto.encodepoint(RHS)))
        return 0
Exemple #3
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)
Exemple #4
0
    def test_ge25519_double_scalarmult_vartime2(self):
        for i in range(10):
            ap = crypto.random_scalar()
            bp = crypto.random_scalar()
            A = crypto.scalarmult_base(ap)
            B = crypto.scalarmult_base(bp)
            a = crypto.random_scalar()
            b = crypto.random_scalar()

            R = crypto.ge_double_scalarmult_base_vartime2(a, A, b, B)
            R_exp = crypto.point_add(crypto.scalarmult(A, a), crypto.scalarmult(B, b))
            self.assertTrue(crypto.point_eq(R, R_exp))
Exemple #5
0
    def test_pointadd(self):
        a = crypto.random_scalar()
        A = crypto.scalarmult_base(a)
        A2 = crypto.point_add(A, A)
        A3 = crypto.point_add(A2, A)
        A4 = crypto.point_add(A3, A)
        A8 = crypto.scalarmult(A4, crypto.sc_init(2))

        A8p = crypto.point_mul8(A)
        self.assertTrue(crypto.point_eq(A8p, A8))
        self.assertTrue(
            crypto.point_eq(A4, crypto.scalarmult(A, crypto.sc_init(4))))
        self.assertTrue(
            crypto.point_eq(A3, crypto.scalarmult(A, crypto.sc_init(3))))
Exemple #6
0
def gen_mlsag_rows(message, rv, pk, xx, kLRki, index, dsRows, rows, cols):
    """
    MLSAG computation - the part with secret keys
    :param message:
    :param rv:
    :param pk:
    :param xx:
    :param kLRki:
    :param index:
    :param dsRows:
    :param rows:
    :param cols:
    :return:
    """
    Ip = key_vector(dsRows)
    rv.II = key_vector(dsRows)
    alpha = key_vector(rows)
    rv.ss = key_matrix(rows, cols)

    hasher = hasher_message(message)

    for i in range(dsRows):
        hasher.update(crypto.encodepoint(pk[index][i]))
        if kLRki:
            alpha[i] = kLRki.k
            rv.II[i] = kLRki.ki
            hasher.update(crypto.encodepoint(kLRki.L))
            hasher.update(crypto.encodepoint(kLRki.R))

        else:
            Hi = crypto.hash_to_point(crypto.encodepoint(
                pk[index][i]))  # originally hashToPoint()
            alpha[i] = crypto.random_scalar()
            aGi = crypto.scalarmult_base(alpha[i])
            aHPi = crypto.scalarmult(Hi, alpha[i])
            rv.II[i] = crypto.scalarmult(Hi, xx[i])
            hasher.update(crypto.encodepoint(aGi))
            hasher.update(crypto.encodepoint(aHPi))

        Ip[i] = crypto.precomp(rv.II[i])

    for i in range(dsRows, rows):
        alpha[i] = crypto.random_scalar()
        aGi = crypto.scalarmult_base(alpha[i])
        hasher.update(crypto.encodepoint(pk[index][i]))
        hasher.update(crypto.encodepoint(aGi))

    c_old = hasher.digest()
    c_old = crypto.decodeint(c_old)
    return c_old, Ip, alpha
Exemple #7
0
def gen_mlsag(pk, xx, index):
    """
    Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)

    These are aka MG signatutes in earlier drafts of the ring ct paper
    c.f. http://eprint.iacr.org/2015/1098 section 2.
    keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i

    Gen creates a signature which proves that for some column in the keymatrix "pk"
       the signer knows a secret key for each row in that column
    Ver verifies that the MG sig was created correctly

    :param pk:
    :param xx:
    :param index:
    :return:
    """
    rows = len(xx)
    cols = len(pk)
    logger.debug("Generating MG sig of size %s x %s" % (rows, cols))
    logger.debug("index is: %s, %s" % (index, pk[index]))
    c = [None] * cols
    alpha = scalar_gen_vector(rows)
    I = key_image_vector(xx)
    L = key_matrix(rows, cols)
    R = key_matrix(rows, cols)
    s = key_matrix(rows, cols)

    m = "".join(pk[0])
    for i in range(1, cols):
        m = m + "".join(pk[i])

    L[index] = [crypto.scalarmult_base(aa) for aa in alpha]  # L = aG
    Hi = hash_key_vector(pk[index])
    R[index] = [crypto.scalarmult(Hi[ii], alpha[ii])
                for ii in range(0, rows)]  # R = aI

    oldi = index
    i = (index + 1) % cols
    c[i] = crypto.cn_fast_hash(m + "".join(L[oldi]) + "".join(R[oldi]))

    while i != index:
        s[i] = scalar_gen_vector(rows)
        L[i] = [
            crypto.add_keys2(s[i][j], c[i], pk[i][j]) for j in range(0, rows)
        ]

        Hi = hash_key_vector(pk[i])
        R[i] = [
            crypto.add_keys3(s[i][j], Hi[j], c[i], I[j])
            for j in range(0, rows)
        ]
        oldi = i
        i = (i + 1) % cols
        c[i] = crypto.cn_fast_hash(m + "".join(L[oldi]) + "".join(R[oldi]))

    s[index] = [
        crypto.sc_mulsub(c[index], xx[j], alpha[j]) for j in range(0, rows)
    ]  # alpha - c * x
    return I, c[0], s
Exemple #8
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
Exemple #9
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()
Exemple #10
0
def generate_key_image(public_key, secret_key):
    """
    Key image: secret_key * H_p(pub_key)
    """
    point = crypto.hash_to_point(public_key)
    point2 = crypto.scalarmult(point, secret_key)
    return point2
Exemple #11
0
 def verify_tx_key(self, tx_priv, tx_pub, all_creds_subs):
     if crypto.point_eq(tx_pub, crypto.scalarmult_base(tx_priv)):
         return True
     for cred_idx, subs in enumerate(all_creds_subs):
         for ckey in subs:
             if crypto.point_eq(tx_pub, crypto.scalarmult(ckey, tx_priv)):
                 return True
     return False
Exemple #12
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!')
Exemple #13
0
 def test_h_pow(self):
     hp = crypto.gen_Hpow(10)
     self.assertEqual(crypto.encodepoint(hp[0]),
                      crypto.encodepoint(crypto.xmr_H()))
     for i in range(1, 10):
         crypto.check_ed25519point(hp[i])
         self.assertEqual(
             crypto.encodepoint(hp[i]),
             crypto.encodepoint(
                 crypto.scalarmult(crypto.xmr_H(), crypto.sc_init(2**i))),
         )
Exemple #14
0
def key_image_vector(x):
    """
    Takes as input a keyvector, returns the keyimage-vector
    TODO: use crypto for generating key images
    :param x:
    :return:
    """
    return [
        crypto.scalarmult(crypto.hash_to_point(crypto.scalarmult_base(xx)), xx)
        for xx in x
    ]
Exemple #15
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
Exemple #16
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))
Exemple #17
0
def ver_schnorr_non_linkable(P1, P2, L1, s1, s2):
    """
    Verifies Schnorr signature generated by gen_schnorr_non_linkable
    :param P1:
    :param P2:
    :param L1:
    :param s1:
    :param s2:
    :return:
    """
    c2 = crypto.cn_fast_hash(crypto.encodepoint(L1))
    L2 = crypto.point_add(crypto.scalarmult_base(s2),
                          crypto.scalarmult(P2, crypto.decodeint(c2)))
    c1 = crypto.cn_fast_hash(L2)
    L1p = crypto.point_add(crypto.scalarmult_base(s1),
                           crypto.scalarmult(P1, crypto.decodeint(c1)))

    if L1 == L1p:
        return 0

    else:
        logger.warning("Didn't verify L1: %s, L1p: %s" % (L1, L1p))
        return -1
Exemple #18
0
def ecdh_decode(masked, receiver_sk=None, derivation=None):
    """
    Elliptic Curve Diffie-Helman: encodes and decodes the amount b and mask a
    where C= aG + bH
    """
    rv = xmrtypes.EcdhTuple()

    if derivation is None:
        derivation = crypto.scalarmult(masked.senderPk, receiver_sk)

    sharedSec1 = crypto.hash_to_scalar(derivation)
    sharedSec2 = crypto.hash_to_scalar(crypto.encodeint(sharedSec1))

    rv.mask = crypto.sc_sub(masked.mask, sharedSec1)
    rv.amount = crypto.sc_sub(masked.amount, sharedSec2)
    return rv
Exemple #19
0
def ecdh_encode(unmasked, receiver_pk=None, derivation=None, v2=False, dest=None):
    """
    Elliptic Curve Diffie-Helman: encodes and decodes the amount b and mask a
    where C= aG + bH
    :param unmasked:
    :param receiver_pk:
    :param derivation:
    :return:
    """
    rv = xmrtypes.EcdhTuple() if dest is None else dest
    if derivation is None:
        esk = crypto.random_scalar()
        rv.senderPk = crypto.scalarmult_base(esk)
        derivation = crypto.encodepoint(crypto.scalarmult(receiver_pk, esk))

    return ecdh_encdec(unmasked, None, derivation, v2=v2, enc=True, dest=rv)
Exemple #20
0
def generate_sub_address_keys(view_sec, spend_pub, major, minor):
    """
    Computes generic public sub-address
    :param view_sec:
    :param spend_pub:
    :param major:
    :param minor:
    :return: spend public, view public
    """
    if major == 0 and minor == 0:  # special case, Monero-defined
        return spend_pub, crypto.scalarmult_base(view_sec)

    m = get_subaddress_secret_key(view_sec, major=major, minor=minor)
    M = crypto.scalarmult_base(m)
    D = crypto.point_add(spend_pub, M)
    C = crypto.scalarmult(D, view_sec)
    return D, C
Exemple #21
0
def decode_rct(rv, sk, i):
    """
    c.f. http:#eprint.iacr.org/2015/1098 section 5.1.1
    Uses the attached ecdh info to find the amounts represented by each output commitment
    must know the destination private key to find the correct amount, else will return a random number

    :param rv:
    :param sk:
    :param i:
    :return:
    """
    decodedTuple = ecdh_decode(rv.ecdhInfo[i], sk)
    mask = decodedTuple.mask
    amount = decodedTuple.amount
    C = rv.outPk[i].mask
    H = crypto.xmr_H()
    Ctmp = crypto.point_add(crypto.scalarmult_base(mask), crypto.scalarmult(H, amount))
    if not crypto.point_eq(crypto.point_sub(C, Ctmp), crypto.identity()):
        logger.warning("warning, amount decoded incorrectly, will be unable to spend")
    return amount
Exemple #22
0
def gen_schnorr_non_linkable(x, P1, P2, index):
    """
    Generates simple Schnorr
    :param x:
    :param P1:
    :param P2:
    :param index:
    :return:
    """
    a = crypto.random_scalar()
    L1 = crypto.scalarmult_base(a)
    s2 = crypto.random_scalar()
    c2 = crypto.cn_fast_hash(crypto.encodepoint(L1))
    L2 = crypto.point_add(
        crypto.scalarmult_base(s2),
        crypto.scalarmult(P2 if index == 0 else P1, crypto.decodeint(c2)),
    )
    c1 = crypto.cn_fast_hash(crypto.encodepoint(L2))
    s1 = crypto.sc_mulsub(x, crypto.decodeint(c1), a)

    return (L1, s1, s2) if index == 0 else (L2, s2, s1)
Exemple #23
0
def ecdh_encode(unmasked, receiver_pk=None, derivation=None):
    """
    Elliptic Curve Diffie-Helman: encodes and decodes the amount b and mask a
    where C= aG + bH
    :param unmasked:
    :param receiver_pk:
    :param derivation:
    :return:
    """
    rv = xmrtypes.EcdhTuple()
    if derivation is None:
        esk = crypto.random_scalar()
        rv.senderPk = crypto.scalarmult_base(esk)
        derivation = crypto.encodepoint(crypto.scalarmult(receiver_pk, esk))

    sec1 = crypto.hash_to_scalar(derivation)
    sec2 = crypto.hash_to_scalar(crypto.encodeint(sec1))

    rv.mask = crypto.sc_add(unmasked.mask, sec1)
    rv.amount = crypto.sc_add(unmasked.amount, sec2)
    return rv
Exemple #24
0
    async def test_live_refresh(self):
        if self.should_test_only_tx() or not int(
                os.getenv("TREZOR_TEST_LIVE_REFRESH", '1')):
            self.skipTest("Live refresh skipped")

        creds = self.get_trezor_creds(0)
        await self.agent.live_refresh_start()
        for att in range(22):
            r = crypto.random_scalar()
            R = crypto.scalarmult_base(r)
            D = crypto.scalarmult(R, creds.view_key_private)
            subaddr = 0, att

            scalar_step1 = crypto.derive_secret_key(D, att,
                                                    creds.spend_key_private)

            # step 2: add Hs(SubAddr || a || index_major || index_minor)
            if subaddr == (0, 0):
                scalar_step2 = scalar_step1
            else:
                subaddr_sk = monero.get_subaddress_secret_key(
                    creds.view_key_private, major=0, minor=att)
                scalar_step2 = crypto.sc_add(scalar_step1, subaddr_sk)

            pub_ver = crypto.scalarmult_base(scalar_step2)
            ki = monero.generate_key_image(crypto.encodepoint(pub_ver),
                                           scalar_step2)

            ki2 = await self.agent.live_refresh(creds.view_key_private,
                                                crypto.encodepoint(pub_ver),
                                                crypto.encodepoint(D), att, 0,
                                                att)

            if not crypto.point_eq(ki, ki2):
                raise ValueError("Key image inconsistent")
            time.sleep(0.1)
        await self.agent.live_refresh_final()
Exemple #25
0
def generate_ring_signature(prefix_hash,
                            image,
                            pubs,
                            sec,
                            sec_idx,
                            test=False):
    """
    Generates ring signature with key image.
    void crypto_ops::generate_ring_signature()
    """
    if test:
        t = crypto.scalarmult_base(sec)
        if not crypto.point_eq(t, pubs[sec_idx]):
            raise ValueError("Invalid sec key")

        k_i = monero.generate_key_image(crypto.encodepoint(pubs[sec_idx]), sec)
        if not crypto.point_eq(k_i, image):
            raise ValueError("Key image invalid")
        for k in pubs:
            crypto.ge_frombytes_vartime_check(k)

    image_unp = crypto.ge_frombytes_vartime(image)
    image_pre = crypto.ge_dsm_precomp(image_unp)

    buff_off = len(prefix_hash)
    buff = bytearray(buff_off + 2 * 32 * len(pubs))
    memcpy(buff, 0, prefix_hash, 0, buff_off)
    mvbuff = memoryview(buff)

    sum = crypto.sc_0()
    k = crypto.sc_0()
    sig = []
    for i in range(len(pubs)):
        sig.append([crypto.sc_0(), crypto.sc_0()])  # c, r

    for i in range(len(pubs)):
        if i == sec_idx:
            k = crypto.random_scalar()
            tmp3 = crypto.scalarmult_base(k)
            crypto.encodepoint_into(mvbuff[buff_off:buff_off + 32], tmp3)
            buff_off += 32

            tmp3 = crypto.hash_to_point(crypto.encodepoint(pubs[i]))
            tmp2 = crypto.scalarmult(tmp3, k)
            crypto.encodepoint_into(mvbuff[buff_off:buff_off + 32], tmp2)
            buff_off += 32

        else:
            sig[i] = [crypto.random_scalar(), crypto.random_scalar()]
            tmp3 = crypto.ge_frombytes_vartime(pubs[i])
            tmp2 = crypto.ge_double_scalarmult_base_vartime(
                sig[i][0], tmp3, sig[i][1])
            crypto.encodepoint_into(mvbuff[buff_off:buff_off + 32], tmp2)
            buff_off += 32

            tmp3 = crypto.hash_to_point(crypto.encodepoint(tmp3))
            tmp2 = crypto.ge_double_scalarmult_precomp_vartime(
                sig[i][1], tmp3, sig[i][0], image_pre)
            crypto.encodepoint_into(mvbuff[buff_off:buff_off + 32], tmp2)
            buff_off += 32

            sum = crypto.sc_add(sum, sig[i][0])

    h = crypto.hash_to_scalar(buff)
    sig[sec_idx][0] = crypto.sc_sub(h, sum)
    sig[sec_idx][1] = crypto.sc_mulsub(sig[sec_idx][0], sec, k)
    return sig
Exemple #26
0
 def test_scalarmult(self):
     priv = bytes(
         [
             0x34,
             0x82,
             0xfb,
             0x97,
             0x35,
             0xef,
             0x87,
             0x9f,
             0xca,
             0xe5,
             0xec,
             0x77,
             0x21,
             0xb5,
             0xd3,
             0x64,
             0x6e,
             0x15,
             0x5c,
             0x4f,
             0xb5,
             0x8d,
             0x6c,
             0xc1,
             0x1c,
             0x73,
             0x2c,
             0x9c,
             0x9b,
             0x76,
             0x62,
             0x0a,
         ]
     )
     pub = bytes(
         [
             0x24,
             0x86,
             0x22,
             0x47,
             0x97,
             0xd0,
             0x5c,
             0xae,
             0x3c,
             0xba,
             0x4b,
             0xe0,
             0x43,
             0xbe,
             0x2d,
             0xb0,
             0xdf,
             0x38,
             0x1f,
             0x3f,
             0x19,
             0xcf,
             0xa1,
             0x13,
             0xf8,
             0x6a,
             0xb3,
             0x8e,
             0x3d,
             0x8d,
             0x2b,
             0xd0,
         ]
     )
     exp = bytes(
         [
             0xad,
             0xcd,
             0x1f,
             0x58,
             0x81,
             0xf4,
             0x6f,
             0x25,
             0x49,
             0x00,
             0xa0,
             0x3c,
             0x65,
             0x4e,
             0x71,
             0x95,
             0x0a,
             0x88,
             0xa0,
             0x23,
             0x6f,
             0xa0,
             0xa3,
             0xa9,
             0x46,
             0xc9,
             0xb8,
             0xda,
             0xed,
             0x6e,
             0xf4,
             0x3d,
         ]
     )
     res = crypto.scalarmult(crypto.decodepoint(pub), crypto.decodeint(priv))
     self.assertEqual(exp, crypto.encodepoint(res))
     self.assertTrue(crypto.point_eq(crypto.decodepoint(exp), res))
Exemple #27
0
 async def scal_mul_key(self):
     pub = crypto.decodepoint(self._fetch())
     sec = crypto.decodeint(self._fetch_decrypt())
     self._insert(crypto.encodepoint(crypto.scalarmult(pub, sec)))
     return SW_OK
Exemple #28
0
def generate_ring_signature(prefix_hash,
                            image,
                            pubs,
                            sec,
                            sec_idx,
                            test=False):
    """
    Generates ring signature with key image.
    void crypto_ops::generate_ring_signature()

    :param prefix_hash:
    :param image:
    :param pubs:
    :param sec:
    :param sec_idx:
    :param test:
    :return:
    """
    if test:
        t = crypto.scalarmult_base(sec)
        if not crypto.point_eq(t, pubs[sec_idx]):
            raise ValueError("Invalid sec key")

        k_i = monero.generate_key_image(crypto.encodepoint(pubs[sec_idx]), sec)
        if not crypto.point_eq(k_i, image):
            raise ValueError("Key image invalid")
        for k in pubs:
            crypto.ge_frombytes_vartime_check(k)

    image_unp = crypto.ge_frombytes_vartime(image)
    image_pre = crypto.ge_dsm_precomp(image_unp)

    buff = b"" + prefix_hash
    sum = crypto.sc_0()
    k = crypto.sc_0()
    sig = []
    for i in range(len(pubs)):
        sig.append([crypto.sc_0(), crypto.sc_0()])  # c, r

    for i in range(len(pubs)):
        if i == sec_idx:
            k = crypto.random_scalar()
            tmp3 = crypto.scalarmult_base(k)
            buff += crypto.encodepoint(tmp3)
            tmp3 = crypto.hash_to_ec(crypto.encodepoint(pubs[i]))
            tmp2 = crypto.scalarmult(tmp3, k)
            buff += crypto.encodepoint(tmp2)
        else:
            sig[i] = [crypto.random_scalar(), crypto.random_scalar()]
            tmp3 = crypto.ge_frombytes_vartime(pubs[i])
            tmp2 = crypto.ge_double_scalarmult_base_vartime(
                sig[i][0], tmp3, sig[i][1])
            buff += crypto.encodepoint(tmp2)
            tmp3 = crypto.hash_to_ec(crypto.encodepoint(tmp3))
            tmp2 = crypto.ge_double_scalarmult_precomp_vartime(
                sig[i][1], tmp3, sig[i][0], image_pre)
            buff += crypto.encodepoint(tmp2)
            sum = crypto.sc_add(sum, sig[i][0])

    h = crypto.hash_to_scalar(buff)
    sig[sec_idx][0] = crypto.sc_sub(h, sum)
    sig[sec_idx][1] = crypto.sc_mulsub(sig[sec_idx][0], sec, k)
    return sig
Exemple #29
0
    def rekey_input(self, inp, keys, subs=None, new_keys=None, new_subs=None, mixin_change=None):
        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
        ]

        logger.debug("Current out key: %s" % binascii.hexlify(real_out_key.dest))
        secs = monero.generate_key_image_helper(
            keys, subs, out_key, tx_key, additional_keys, inp.real_output_in_tx_index
        )
        xi, ki, di = secs

        need_additional = additional_keys is not None and len(additional_keys) > 0
        is_dst_sub = self.dest_sub_major != 0 and (
            self.args.minors[0] != 0 or len(self.args.minors) > 1
        )
        logger.debug(
            "Is dst sub: %s, need additional: %s" % (is_dst_sub, need_additional)
        )

        if is_dst_sub and self.add_additionals:
            need_additional = True

        if is_dst_sub:
            rand_minor = random.choice(self.args.minors)
            m = monero.get_subaddress_secret_key(
                new_keys.view_key_private, major=self.dest_sub_major, minor=rand_minor
            )
            M = crypto.scalarmult_base(m)
            d = crypto.sc_add(m, new_keys.spend_key_private)
            D = crypto.point_add(new_keys.spend_key_public, M)
            C = crypto.scalarmult(D, new_keys.view_key_private)

        if not need_additional and not is_dst_sub:
            # real_out_key.dst = Hs(R*new_a || idx)G + newB
            r = crypto.random_scalar()
            tx_key = crypto.scalarmult_base(r)
            new_deriv = crypto.generate_key_derivation(new_keys.view_key_public, r)
            new_out_pr = crypto.derive_secret_key(
                new_deriv, inp.real_output_in_tx_index, new_keys.spend_key_private
            )
            new_out = crypto.scalarmult_base(new_out_pr)
            real_out_key.dest = crypto.encodepoint(new_out)

        elif not need_additional and is_dst_sub:
            # real_out_key.dst = Hs(r*C || idx)G + newB, R=rD
            r = crypto.random_scalar()
            tx_key = crypto.scalarmult(D, r)
            new_deriv = crypto.generate_key_derivation(C, r)
            new_out_pr = crypto.derive_secret_key(
                new_deriv, inp.real_output_in_tx_index, d
            )
            new_out = crypto.scalarmult_base(new_out_pr)
            real_out_key.dest = crypto.encodepoint(new_out)

        else:
            r = crypto.random_scalar()
            tx_key = crypto.scalarmult_base(r)

            gen_additionals = min(2, inp.real_output_in_tx_index + 1)
            if additional_keys is None or len(additional_keys) < gen_additionals:
                additional_keys = [
                    crypto.scalarmult_base(crypto.random_scalar())
                    for _ in range(gen_additionals)
                ]

            ri = crypto.random_scalar()
            if is_dst_sub:
                add_tx = crypto.scalarmult(D, ri)
                new_deriv = crypto.generate_key_derivation(C, ri)
                new_out_pr = crypto.derive_secret_key(
                    new_deriv, inp.real_output_in_tx_index, d
                )
                new_out = crypto.scalarmult_base(new_out_pr)
                if not crypto.point_eq(
                    new_out,
                    crypto.derive_public_key(new_deriv, inp.real_output_in_tx_index, D),
                ):
                    raise ValueError("Invalid txout computation")

            else:
                add_tx = crypto.scalarmult_base(ri)
                new_deriv = crypto.generate_key_derivation(new_keys.view_key_public, r)
                new_out_pr = crypto.derive_secret_key(
                    new_deriv, inp.real_output_in_tx_index, new_keys.spend_key_private
                )
                new_out = crypto.scalarmult_base(new_out_pr)

            additional_keys[inp.real_output_in_tx_index] = add_tx
            real_out_key.dest = crypto.encodepoint(new_out)

        # Increasing the size of the mixin
        if mixin_change and len(inp.outputs) < mixin_change:
            for i in range(mixin_change - len(inp.outputs)):
                inp.outputs.append((0, CtKey(
                    mask=crypto.encodepoint(self.random_pub()),
                    dest=crypto.encodepoint(self.random_pub()))))
                if additional_keys:
                    additional_keys.append(self.random_pub())

        inp.real_out_tx_key = crypto.encodepoint(tx_key)
        inp.real_out_additional_tx_keys = [
            crypto.encodepoint(x) for x in additional_keys
        ]

        logger.debug("New pub: %s" % binascii.hexlify(real_out_key.dest))

        # Self-check
        self.check_input(inp, new_keys, new_subs)
        return inp
Exemple #30
0
    async def gen_input(self,
                        value=1,
                        sub_major=None,
                        sub_minor=0,
                        additionals=False):
        creds = self.src_keys
        r = self.random_scalar()
        R = crypto.scalarmult_base(r)
        additional_keys = []
        Additional = None
        sub_major = sub_major if sub_major is not None else self.account_idx
        is_sub = sub_major != 0 or sub_minor != 0

        if sub_major != self.account_idx:
            logger.warning(
                "Generating input with different major subindex, cannot be spent in the resulting "
                "transaction")

        kssec = monero.get_subaddress_secret_key(creds.view_key_private,
                                                 major=sub_major,
                                                 minor=sub_minor)
        kssub = crypto.sc_add(
            kssec,
            creds.spend_key_private) if is_sub else creds.spend_key_private
        kvsub = crypto.sc_mul(creds.view_key_private,
                              kssub) if is_sub else creds.view_key_private
        KSSUB, KVSUB = monero.generate_sub_address_keys(
            creds.view_key_private, creds.spend_key_public, sub_major,
            sub_minor)

        if not crypto.point_eq(KSSUB, crypto.scalarmult_base(kssub)):
            raise ValueError("Invariant error")

        oidx = self.prng.randint(0, 12)
        additionals_cnt = self.prng.randint(oidx + 1, 2 * oidx + 1)
        deriv = crypto.generate_key_derivation(KVSUB, r)
        kout = crypto.derive_secret_key(deriv, oidx, kssub)
        KOUT = crypto.derive_public_key(deriv, oidx, KSSUB)
        if not crypto.point_eq(KOUT, crypto.scalarmult_base(kout)):
            raise ValueError("Invariant error")

        if additionals:
            if is_sub:
                Additional = crypto.scalarmult(KSSUB, r)
            else:
                Additional = crypto.scalarmult_base(r)
        else:
            if is_sub:
                R = crypto.scalarmult(KSSUB, r)

        amnt = crypto.sc_init(value)
        msk = self.random_scalar()  # commitment mask
        C = crypto.add_keys2(msk, amnt, crypto.xmr_H())

        ring = []
        for i in range(self.ring_size - 1):
            tk = CtKey(
                dest=crypto.encodepoint(self.random_pub()),
                mask=crypto.encodepoint(self.random_pub()),
            )
            ring.append(tk)

        index = self.prng.randint(0, len(ring))
        ring.insert(
            index,
            CtKey(dest=crypto.encodepoint(KOUT), mask=crypto.encodepoint(C)))
        if additionals:
            additional_keys = [
                self.random_pub() for _ in range(additionals_cnt)
            ]
            additional_keys[oidx] = Additional

        src = TxSourceEntry()
        src.outputs = [(self.random_glob_idx(), x) for x in ring]
        src.real_output = index
        src.real_out_tx_key = crypto.encodepoint(R)
        src.real_out_additional_tx_keys = [
            crypto.encodepoint(x) for x in additional_keys
        ]
        src.real_output_in_tx_index = oidx
        src.amount = value
        src.rct = True
        src.mask = crypto.encodeint(msk)
        src.multisig_kLRki = MultisigKLRki(K=crypto.ZERO,
                                           L=crypto.ZERO,
                                           R=crypto.ZERO,
                                           ki=crypto.ZERO)

        td = TransferDetails()
        td.m_internal_output_index = oidx
        td.m_global_output_index = src.outputs[index][0]
        td.m_mask = src.mask
        td.m_amount = value
        td.m_subaddr_index = SubaddressIndex(major=sub_major, minor=sub_minor)
        td.m_rct = True
        td.m_txid = self.random_bytes(32)
        td.m_block_height = self.prng.randint(0, 0xFFFF)
        td.m_spent = False
        td.m_spent_height = 0
        td.m_key_image_known = True
        td.m_key_image_requested = False
        td.m_key_image_partial = False
        td.m_multisig_k = []
        td.m_multisig_info = []
        td.m_uses = []
        td.m_pk_index = 0
        td.m_tx = self.gen_tx_prefix(self.prng.randint(1, 10), additionals_cnt)
        td.m_tx.vout[oidx].target.key = crypto.encodepoint(KOUT)

        extras = []
        extras.append(TxExtraNonce(nonce=self.random_bytes(8)))
        extras.append(TxExtraPubKey(pub_key=src.real_out_tx_key))
        if src.real_out_additional_tx_keys:
            extras.append(
                TxExtraAdditionalPubKeys(data=src.real_out_additional_tx_keys))
        td.m_tx.extra = await self.dump_extra_fields(extras)

        tmpsubs = {}
        monero.compute_subaddresses(creds, sub_major, [sub_minor], tmpsubs)
        xi, ki, rderiv = self.check_input(src, creds, tmpsubs)
        if not crypto.sc_eq(xi, kout):
            raise ValueError("Invariant error")

        td.m_key_image = crypto.encodepoint(ki)

        self.sources.append(src)
        self.selected_transfers.append(len(self.transfers))
        self.transfers.append(td)
        self.sources_creds.append(creds)

        if not crypto.point_eq(
                crypto.decodepoint(src.outputs[src.real_output][1].dest),
                crypto.scalarmult_base(kout)):
            raise ValueError("Invariant error")

        return self