public static bool crypto_sign_verify( byte[] signature, int signatureOffset, byte[] message, int messageOffset, int messageLength, byte[] publicKey, int publicKeyOffset) { byte[] h; byte[] checkr = new byte[32]; GroupElementP3 A; GroupElementP2 R; if ((signature[signatureOffset + 63] & 224) != 0) { return(false); } if (GroupOperations.ge_frombytes_negate_vartime(out A, publicKey, publicKeyOffset) != 0) { return(false); } var hasher = new Sha512(); hasher.Update(signature, signatureOffset, 32); hasher.Update(publicKey, publicKeyOffset, 32); hasher.Update(message, messageOffset, messageLength); h = hasher.FinalizeHash(); ScalarOperations.sc_reduce(h); var sm32 = new byte[32];//todo: remove allocation Array.Copy(signature, signatureOffset + 32, sm32, 0, 32); GroupOperations.ge_double_scalarmult_vartime(out R, h, ref A, sm32); GroupOperations.ge_tobytes(checkr, 0, ref R); var result = CryptoBytes.ConstantTimeEquals(checkr, 0, signature, signatureOffset, 32); CryptoBytes.Wipe(h); CryptoBytes.Wipe(checkr); return(result); }
public static void crypto_sign( byte[] sig, int sigoffset, byte[] m, int moffset, int mlen, byte[] sk, int skoffset) { byte[] az, r, hram; GroupElementP3 R; var hasher = new Sha512(); { hasher.Update(sk, skoffset, 32); az = hasher.FinalizeHash(); ScalarOperations.sc_clamp(az, 0); hasher.Init(); hasher.Update(az, 32, 32); hasher.Update(m, moffset, mlen); r = hasher.FinalizeHash(); ScalarOperations.sc_reduce(r); GroupOperations.ge_scalarmult_base(out R, r, 0); GroupOperations.ge_p3_tobytes(sig, sigoffset, ref R); hasher.Init(); hasher.Update(sig, sigoffset, 32); hasher.Update(sk, skoffset + 32, 32); hasher.Update(m, moffset, mlen); hram = hasher.FinalizeHash(); ScalarOperations.sc_reduce(hram); var s = new byte[32]; //todo: remove allocation Array.Copy(sig, sigoffset + 32, s, 0, 32); ScalarOperations.sc_muladd(s, hram, az, r); Array.Copy(s, 0, sig, sigoffset + 32, 32); CryptoBytes.Wipe(s); } }