public static bool CheckRingSignatures(byte[] PrefixHash, byte[] KeyImage, byte[][] PublicKeys, byte[][] Signatures) { // Convert signature list to signature buffer array HashBuffer[] SignaturesBuffer = new HashBuffer[Signatures.Length]; for (int i = 0; i < SignaturesBuffer.Length; i++) { SignaturesBuffer[i] = new HashBuffer(Signatures[i]); } // Create some ED25519 points ge_p3 Image_Unp = new ge_p3(); ge_dsmp Image_Pre = new ge_dsmp(); // Declare a few more variables byte[] Sum = new byte[32]; byte[] Hash = new byte[32]; // Create a signature buffer array HashBuffer[] Buffer = new HashBuffer[PublicKeys.Length]; // Verify key image if (ge_frombytes_vartime(Image_Unp, KeyImage) != 0) { return(false); } // Precomp ge_dsm_precomp(ref Image_Pre, Image_Unp); // Another check if (ge_check_subgroup_precomp_vartime(Image_Pre) != 0) { return(false); } // Loop through all given signatures for (int i = 0; i < PublicKeys.Length; i++) { // Assign a new signature buffer Buffer[i] = new HashBuffer(); // Create temporary points ge_p2 tmp2 = new ge_p2(); ge_p3 tmp3 = new ge_p3(); // Verify information if (sc_check(SignaturesBuffer[i].A) != 0 || sc_check(SignaturesBuffer[i].B) != 0) { return(false); } if (ge_frombytes_vartime(tmp3, PublicKeys[i]) != 0) { return(false); } // Signature Part A ge_double_scalarmult_base_vartime(tmp2, SignaturesBuffer[i].A, tmp3, SignaturesBuffer[i].B); ge_tobytes(ref Buffer[i].A, tmp2); // Convert public key to elliptic curve point HashToEllipticCurve(tmp3, PublicKeys[i]); // Signature Part B ge_double_scalarmult_precomp_vartime(tmp2, SignaturesBuffer[i].B, tmp3, SignaturesBuffer[i].A, Image_Pre); ge_tobytes(ref Buffer[i].B, tmp2); // Add to sum sc_add(ref Sum, Sum, SignaturesBuffer[i].A); } // Combine buffer and convert to a scalar byte[] SigHash = PrefixHash; for (int i = 0; i < Buffer.Length; i++) { SigHash = SigHash.AppendBytes(Buffer[i].Output); } HashToScalar(ref Hash, SigHash); // Perform final math sc_sub(ref Hash, Hash, Sum); // Return result of final check return(sc_isnonzero(Hash) == 0); }
public static byte[][] GenerateRingSignatures(byte[] PrefixHash, byte[] KeyImage, byte[][] PublicKeys, byte[] TransactionSecretKey, ulong RealOutput) { // Create some ED25519 points ge_p3 Image_Unp = new ge_p3(); ge_dsmp Image_Pre = new ge_dsmp(); // Declare a few more variables byte[] Sum = new byte[32]; byte[] Scalar = new byte[32]; byte[] Hash = new byte[32]; // Create a signature buffer array and output array HashBuffer[] Buffer = new HashBuffer[PublicKeys.Length]; HashBuffer[] Signatures = new HashBuffer[PublicKeys.Length]; // Verify key image if (ge_frombytes_vartime(Image_Unp, KeyImage) != 0) { return(null); } // Precomp ge_dsm_precomp(ref Image_Pre, Image_Unp); // Loop through all given keys for (ulong i = 0; i < (ulong)PublicKeys.Length; i++) { // Assign a new signature buffers Buffer[i] = new HashBuffer(); Signatures[i] = new HashBuffer(); // Create temporary points ge_p2 tmp2 = new ge_p2(); ge_p3 tmp3 = new ge_p3(); // This is the real output index if (i == RealOutput) { // Generate a random scalar random_scalar(ref Scalar); //random_scalar(k); ge_scalarmult_base(tmp3, Scalar); //ge_scalarmult_base(tmp3, k); // Signature Part A ge_p3_tobytes(ref Buffer[i].A, tmp3); //ge_p3_tobytes(reinterpret_cast < unsigned char *> (&buf->ab[i].a), &tmp3); // Turn public key at this index into an elliptic curve, then multiply HashToEllipticCurve(tmp3, PublicKeys[i]); //hash_to_ec(publicKeys[i], tmp3); ge_scalarmult(tmp2, Scalar, tmp3); //ge_scalarmult(&tmp2, reinterpret_cast < unsigned char *> (&k), &tmp3); // Signature Part B ge_tobytes(ref Buffer[i].B, tmp2); // ge_tobytes(reinterpret_cast < unsigned char *> (&buf->ab[i].b), &tmp2); } // This is a generated signature index else { // Create a random scalar for both signature parts random_scalar(ref Signatures[i].A); random_scalar(ref Signatures[i].B); // Get bytes from this public key (also verifies it) if (ge_frombytes_vartime(tmp3, PublicKeys[i]) != 0) { return(null); } // Signature Part A ge_double_scalarmult_base_vartime(tmp2, Signatures[i].A, tmp3, Signatures[i].B); ge_tobytes(ref Buffer[i].A, tmp2); // Convert public key to elliptic curve point HashToEllipticCurve(tmp3, PublicKeys[i]); // Signature Part B ge_double_scalarmult_precomp_vartime(tmp2, Signatures[i].B, tmp3, Signatures[i].A, Image_Pre); ge_tobytes(ref Buffer[i].B, tmp2); // Add to sum sc_add(ref Sum, Sum, Signatures[i].A); } } // Combine buffer and convert to a scalar byte[] SigHash = PrefixHash; for (int i = 0; i < Buffer.Length; i++) { SigHash = SigHash.AppendBytes(Buffer[i].Output); } HashToScalar(ref Hash, SigHash); // Perform final math sc_sub(ref Signatures[RealOutput].A, Hash, Sum); sc_mulsub(ref Signatures[RealOutput].B, Signatures[RealOutput].A, TransactionSecretKey, Scalar); // Create an output array and return it byte[][] Output = new byte[Signatures.Length][]; for (int i = 0; i < Signatures.Length; i++) { Output[i] = Signatures[i].Output; } return(Output); }