public RingSignature[] Sign(byte[] msg, byte[] keyImage, IKey[] publicKeys, byte[] secretKey, int index) { RingSignature[] signatures = new RingSignature[publicKeys.Length]; byte[][] pubs = publicKeys.Select(pk => pk.Value.ToArray()).ToArray(); GroupOperations.ge_frombytes(out GroupElementP3 keyImageP3, keyImage, 0); GroupElementCached[] image_pre = new GroupElementCached[8]; GroupOperations.ge_dsm_precomp(image_pre, ref keyImageP3); byte[] sum = new byte[32], k = null, h = null; IHash hasher = HashFactory.Crypto.SHA3.CreateKeccak256(); hasher.TransformBytes(msg); for (int i = 0; i < publicKeys.Length; i++) { signatures[i] = new RingSignature(); if (i == index) { k = GetRandomSeed(true); GroupOperations.ge_scalarmult_base(out GroupElementP3 tmp3, k, 0); byte[] tmp3bytes = new byte[32]; GroupOperations.ge_p3_tobytes(tmp3bytes, 0, ref tmp3); hasher.TransformBytes(tmp3bytes); tmp3 = Hash2Point(pubs[i]); GroupOperations.ge_scalarmult(out GroupElementP2 tmp2, k, ref tmp3); byte[] tmp2bytes = new byte[32]; GroupOperations.ge_tobytes(tmp2bytes, 0, ref tmp2); hasher.TransformBytes(tmp2bytes); } else { signatures[i].C = GetRandomSeed(true); signatures[i].R = GetRandomSeed(true); GroupOperations.ge_frombytes(out GroupElementP3 tmp3, pubs[i], 0); GroupOperations.ge_double_scalarmult_vartime(out GroupElementP2 tmp2, signatures[i].C, ref tmp3, signatures[i].R); byte[] tmp2bytes = new byte[32]; GroupOperations.ge_tobytes(tmp2bytes, 0, ref tmp2); hasher.TransformBytes(tmp2bytes); tmp3 = Hash2Point(pubs[i]); GroupOperations.ge_double_scalarmult_precomp_vartime(out tmp2, signatures[i].R, tmp3, signatures[i].C, image_pre); tmp2bytes = new byte[32]; GroupOperations.ge_tobytes(tmp2bytes, 0, ref tmp2); hasher.TransformBytes(tmp2bytes); ScalarOperations.sc_add(sum, sum, signatures[i].C); } } h = hasher.TransformFinal().GetBytes(); ScalarOperations.sc_sub(signatures[index].C, h, sum); ScalarOperations.sc_reduce32(signatures[index].C); ScalarOperations.sc_mulsub(signatures[index].R, signatures[index].C, secretKey, k); ScalarOperations.sc_reduce32(signatures[index].R); return(signatures); }
public bool Verify(byte[] msg, byte[] keyImage, IKey[] publicKeys, RingSignature[] signatures) { byte[][] pubs = publicKeys.Select(pk => pk.Value.ToArray()).ToArray(); GroupOperations.ge_frombytes(out GroupElementP3 image_unp, keyImage, 0); GroupElementCached[] image_pre = new GroupElementCached[8]; GroupOperations.ge_dsm_precomp(image_pre, ref image_unp); byte[] sum = new byte[32]; IHash hasher = HashFactory.Crypto.SHA3.CreateKeccak256(); hasher.TransformBytes(msg); for (int i = 0; i < pubs.Length; i++) { if (ScalarOperations.sc_check(signatures[i].C) != 0 || ScalarOperations.sc_check(signatures[i].R) != 0) { return(false); } GroupOperations.ge_frombytes(out GroupElementP3 tmp3, pubs[i], 0); GroupOperations.ge_double_scalarmult_vartime(out GroupElementP2 tmp2, signatures[i].C, ref tmp3, signatures[i].R); byte[] tmp2bytes = new byte[32]; GroupOperations.ge_tobytes(tmp2bytes, 0, ref tmp2); hasher.TransformBytes(tmp2bytes); tmp3 = Hash2Point(pubs[i]); GroupOperations.ge_double_scalarmult_precomp_vartime(out tmp2, signatures[i].R, tmp3, signatures[i].C, image_pre); tmp2bytes = new byte[32]; GroupOperations.ge_tobytes(tmp2bytes, 0, ref tmp2); hasher.TransformBytes(tmp2bytes); ScalarOperations.sc_add(sum, sum, signatures[i].C); } byte[] h = hasher.TransformFinal().GetBytes(); ScalarOperations.sc_reduce32(h); ScalarOperations.sc_sub(h, h, sum); int res = ScalarOperations.sc_isnonzero(h); return(res == 0); }