public static void crypto_sign2(Span <byte> sig, ReadOnlySpan <byte> m, ReadOnlySpan <byte> sk) { var hasher = new Sha512(); { hasher.Update(sk.Slice(0, 32)); Span <byte> az = stackalloc byte[64]; hasher.Finish(az); ScalarOperations.sc_clamp(az); hasher.Init(); hasher.Update(az.Slice(32, 32)); hasher.Update(m); Span <byte> r = stackalloc byte[64]; hasher.Finish(r); ScalarOperations.sc_reduce(r); GroupOperations.ge_scalarmult_base(out var R, r); GroupOperations.ge_p3_tobytes(sig, in R); hasher.Init(); hasher.Update(sig.Slice(0, 32)); hasher.Update(sk.Slice(32, 32)); hasher.Update(m); Span <byte> hram = stackalloc byte[64]; hasher.Finish(hram); ScalarOperations.sc_reduce(hram); ScalarOperations.sc_muladd(sig.Slice(32, 32), hram, az, r); } }
public static bool crypto_sign_verify(ReadOnlySpan <byte> sig, ReadOnlySpan <byte> m, ReadOnlySpan <byte> pk) { if ((sig[63] & 224) != 0) { return(false); } if (GroupOperations.ge_frombytes_negate_vartime(out var A, pk) != 0) { return(false); } var hasher = new Sha512(); hasher.Update(sig.Slice(0, 32)); hasher.Update(pk.Slice(0, 32)); hasher.Update(m); Span <byte> h = stackalloc byte[64]; hasher.Finish(h); ScalarOperations.sc_reduce(h); GroupOperations.ge_double_scalarmult_vartime(out var R, h, in A, sig.Slice(32, 32)); Span <byte> checkr = stackalloc byte[32]; GroupOperations.ge_tobytes(checkr, in R); var result = CryptoBytes.ConstantTimeEquals(checkr, sig, 32); CryptoBytes.Wipe(h); CryptoBytes.Wipe(checkr); return(result); }
public static void crypto_sign_keypair(Span <byte> pk, Span <byte> sk, ReadOnlySpan <byte> seed) { Sha512.Hash(seed, sk); ScalarOperations.sc_clamp(sk); GroupOperations.ge_scalarmult_base(out var A, sk.Slice(0, 32)); GroupOperations.ge_p3_tobytes(pk, in A); seed.CopyTo(sk); pk.CopyTo(sk.Slice(32, 32)); }