예제 #1
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.sc_reduce32(crypto.decodeint(kck.digest()))

    return crypto.sc_eq(ee_computed, ee)
예제 #2
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_ec(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.sc_reduce32(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
예제 #3
0
def generate_keys(recovery_key):
    """
    Wallet gen.
    :param recovery_key:
    :return:
    """
    sec = crypto.sc_reduce32(recovery_key)
    pub = crypto.scalarmult_base(sec)
    return sec, pub
예제 #4
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_ec(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.sc_reduce32(crypto.decodeint(c_old))
    return c_old, Ip, alpha
예제 #5
0
def ver_mlsag_ext(message, pk, rv, dsRows):
    """
    Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
    c.f. http://eprint.iacr.org/2015/1098 section 2.
    keyImageV just does I[i] = xx[i] * Hash(xx[i] * G) for each i

    :param message:
    :param pk: matrix of EC points, point form.
    :param rv:
    :param dsRows:
    :return:
    """
    rows, cols = ver_mlsag_assert(pk, rv, dsRows)
    c_old = rv.cc

    Ip = key_vector(dsRows)
    for i in range(dsRows):
        Ip[i] = crypto.precomp(rv.II[i])

    i = 0
    while i < cols:
        c = 0
        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_ec(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.sc_reduce32(crypto.decodeint(hasher.digest()))
        c_old = c
        i += 1

    c = crypto.sc_sub(c_old, rv.cc)
    return not crypto.sc_isnonzero(c)
예제 #6
0
def gen_borromean(x, P1, P2, indices):
    """
    Generates Borromean signature for range proofs.
    :return:
    """
    n = len(P1)
    alpha = key_zero_vector(n)
    s1 = key_zero_vector(n)
    kck = crypto.get_keccak()  # ee computation

    for ii in range(n):
        alpha[ii] = crypto.random_scalar()
        L = crypto.scalarmult_base(alpha[ii])

        if indices[ii] == 0:
            s1[ii] = crypto.random_scalar()
            c = crypto.hash_to_scalar(crypto.encodepoint(L))
            L = crypto.add_keys2(s1[ii], c, P2[ii])
            kck.update(crypto.encodepoint(L))

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

    ee = crypto.sc_reduce32(crypto.decodeint(kck.digest()))
    del kck

    s0 = key_zero_vector(n)

    for jj in range(n):
        if not indices[jj]:
            s0[jj] = crypto.sc_mulsub(x[jj], ee, alpha[jj])
        else:
            s0[jj] = crypto.random_scalar()
            LL = crypto.add_keys2(s0[jj], ee, P1[jj])
            cc = crypto.hash_to_scalar(crypto.encodepoint(LL))
            s1[jj] = crypto.sc_mulsub(x[jj], cc, alpha[jj])

    return s0, s1, ee
예제 #7
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.
    """
    n = ATOMS
    bb = d2b(amount, n)  # gives binary form of bb in "digits" binary digits
    ai = [None] * len(bb)
    Ci = [None] * len(bb)
    a = crypto.sc_0()

    C = crypto.identity()
    alpha = mlsag2.key_zero_vector(n)
    s1 = mlsag2.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 == ATOMS - 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:
            Ci[ii] = crypto.scalarmult_base(ai[ii])
        else:
            Ci[ii] = crypto.point_add(crypto.scalarmult_base(ai[ii]), c_H)
        C = crypto.point_add(C, Ci[ii])

        if bb[ii] == 0:
            s1[ii] = crypto.random_scalar()
            c = crypto.hash_to_scalar(crypto.encodepoint(L))
            L = crypto.add_keys2(s1[ii], c, crypto.point_sub(Ci[ii], c_H))
            kck.update(crypto.encodepoint(L))

        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()))
    del kck

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

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

        else:
            s0[jj] = crypto.random_scalar()
            LL = crypto.add_keys2(s0[jj], ee, Ci[jj])
            cc = crypto.hash_to_scalar(crypto.encodepoint(LL))
            s1[jj] = crypto.sc_mulsub(ai[jj], cc, alpha[jj])
        c_H = crypto.point_double(c_H)

    A = xmrtypes.BoroSig()
    A.s0, A.s1, A.ee = s0, s1, ee

    R = xmrtypes.RangeSig()
    R.asig = A
    R.Ci = Ci

    return C, a, R