Пример #1
0
 def test_clsag_invalid_Cp(self):
     res = self.gen_clsag_sig(ring_size=11, index=5)
     msg, scalars, sc1, sI, sD, ring2, Cp = res
     with self.assertRaises(ValueError):
         Cp = crypto.point_add(Cp,
                               crypto.scalarmult_base(crypto.sc_init(1)))
         self.verify_clsag(msg, scalars, sc1, sI, sD, ring2, Cp)
Пример #2
0
def generate_sub_address_keys(view_sec, spend_pub, major, minor):
    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
Пример #3
0
def _check_out_commitment(state: State, amount, mask, C):
    utils.ensure(
        crypto.point_eq(
            C,
            crypto.point_add(crypto.scalarmult_base(mask),
                             crypto.scalarmult_h(amount)),
        ),
        "OutC fail",
    )
Пример #4
0
def get_subaddress_spend_public_key(view_private, spend_public, major, minor):
    """
    Generates subaddress spend public key D_{major, minor}
    """
    if major == 0 and minor == 0:
        return spend_public

    m = get_subaddress_secret_key(view_private, major=major, minor=minor)
    M = crypto.scalarmult_base(m)
    D = crypto.point_add(spend_public, M)
    return D
Пример #5
0
def generate_mlsag_full(message, pubs, in_sk, out_sk_mask, out_pk_commitments,
                        kLRki, index, txn_fee_key):
    cols = len(pubs)
    if cols == 0:
        raise ValueError("Empty pubs")
    rows = len(pubs[0])
    if rows == 0:
        raise ValueError("Empty pub row")
    for i in range(cols):
        if len(pubs[i]) != rows:
            raise ValueError("pub is not rectangular")

    if len(in_sk) != rows:
        raise ValueError("Bad inSk size")
    if len(out_sk_mask) != len(out_pk_commitments):
        raise ValueError("Bad outsk/putpk size")

    sk = _key_vector(rows + 1)
    M = _key_matrix(rows + 1, cols)
    for i in range(rows + 1):
        sk[i] = crypto.sc_0()

    for i in range(cols):
        M[i][rows] = crypto.identity()
        for j in range(rows):
            M[i][j] = crypto.decodepoint(pubs[i][j].dest)
            M[i][rows] = crypto.point_add(
                M[i][rows], crypto.decodepoint(pubs[i][j].commitment))

    sk[rows] = crypto.sc_0()
    for j in range(rows):
        sk[j] = in_sk[j].dest
        sk[rows] = crypto.sc_add(sk[rows],
                                 in_sk[j].mask)  # add masks in last row

    for i in range(cols):
        for j in range(len(out_pk_commitments)):
            M[i][rows] = crypto.point_sub(
                M[i][rows], crypto.decodepoint(
                    out_pk_commitments[j]))  # subtract output Ci's in last row

        # Subtract txn fee output in last row
        M[i][rows] = crypto.point_sub(M[i][rows], txn_fee_key)

    for j in range(len(out_pk_commitments)):
        sk[rows] = crypto.sc_sub(
            sk[rows], out_sk_mask[j])  # subtract output masks in last row

    return generate_mlsag(message, M, sk, kLRki, index, rows)
Пример #6
0
def prove_range_mem(amount, last_mask=None):
    """
    Memory optimized range proof.

    Gives C, and mask such that \sumCi = C
    c.f. http:#eprint.iacr.org/2015/1098 section 5.1

    Ci is a commitment to either 0 or 2^i, i=0,...,63
    thus this proves that "amount" is in [0, 2^ATOMS]
    mask is a such that C = aG + bH, and b = amount
    :param amount:
    :param last_mask: ai[ATOMS-1] will be computed as \sum_{i=0}^{ATOMS-2} a_i - last_mask
    :param use_asnl: use ASNL, used before Borromean
    :return: sumCi, mask, RangeSig.
        sumCi is Pedersen commitment on the amount value. sumCi = aG + amount*H
        mask is "a" from the Pedersent commitment above.
    """
    res = bytearray(32 * (64 + 64 + 64 + 1))
    mv = memoryview(res)
    gc.collect()

    def as0(mv, x, i):
        crypto.encodeint_into(x, mv[32 * i:])

    def as1(mv, x, i):
        crypto.encodeint_into(x, mv[32 * 64 + 32 * i:])

    def aci(mv, x, i):
        crypto.encodepoint_into(x, mv[32 * 64 * 2 + 32 + 32 * i:])

    n = 64
    bb = d2b(amount, n)  # gives binary form of bb in "digits" binary digits
    ai = key_zero_vector(n)
    a = crypto.sc_0()

    C = crypto.identity()
    alpha = key_zero_vector(n)
    c_H = crypto.gen_H()
    kck = crypto.get_keccak()  # ee computation

    # First pass, generates: ai, alpha, Ci, ee, s1
    for ii in range(n):
        ai[ii] = crypto.random_scalar()
        if last_mask is not None and ii == 64 - 1:
            ai[ii] = crypto.sc_sub(last_mask, a)

        a = crypto.sc_add(
            a, ai[ii]
        )  # creating the total mask since you have to pass this to receiver...

        alpha[ii] = crypto.random_scalar()
        L = crypto.scalarmult_base(alpha[ii])

        if bb[ii] == 0:
            Ctmp = crypto.scalarmult_base(ai[ii])
        else:
            Ctmp = crypto.point_add(crypto.scalarmult_base(ai[ii]), c_H)
        C = crypto.point_add(C, Ctmp)
        aci(mv, Ctmp, ii)

        if bb[ii] == 0:
            si = crypto.random_scalar()
            c = crypto.hash_to_scalar(crypto.encodepoint(L))
            L = crypto.add_keys2(si, c, crypto.point_sub(Ctmp, c_H))
            kck.update(crypto.encodepoint(L))
            as1(mv, si, ii)

        else:
            kck.update(crypto.encodepoint(L))

        c_H = crypto.point_double(c_H)

    # Compute ee, memory cleanup
    ee = crypto.sc_reduce32(crypto.decodeint(kck.digest()))
    crypto.encodeint_into(ee, mv[64 * 32 * 2:])
    del kck
    gc.collect()

    # Second phase computes: s0, s1
    c_H = crypto.gen_H()

    for jj in range(n):
        if not bb[jj]:
            s0 = crypto.sc_mulsub(ai[jj], ee, alpha[jj])

        else:
            s0 = crypto.random_scalar()
            Ctmp = crypto.decodepoint(
                mv[32 * 64 * 2 + 32 + 32 * jj:32 * 64 * 2 + 32 + 32 * jj + 32])
            LL = crypto.add_keys2(s0, ee, Ctmp)
            cc = crypto.hash_to_scalar(crypto.encodepoint(LL))
            si = crypto.sc_mulsub(ai[jj], cc, alpha[jj])
            as1(mv, si, jj)
        as0(mv, s0, jj)

        c_H = crypto.point_double(c_H)

    gc.collect()
    return C, a, res