def ver_mlsag(pk, I, c0, s): """ Verify MLSAG :param pk: :param I: :param c0: :param s: :return: """ rows = len(pk[0]) cols = len(pk) logger.debug("verifying MG sig of dimensions %s x %s" % (rows, cols)) c = [None] * (cols + 1) c[0] = c0 L = key_matrix(rows, cols) R = key_matrix(rows, cols) m = "".join(pk[0]) for i in range(1, cols): m = m + "".join(pk[i]) i = 0 while i < cols: 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 c[i] = crypto.cn_fast_hash(m + "".join(L[oldi]) + "".join(R[oldi])) return c0 == c[cols]
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
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
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_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 += 1 c = crypto.sc_sub(c_old, rv.cc) return not crypto.sc_isnonzero(c)