public static void GetPublicKey(Span <byte> publicKey, ReadOnlySpan <byte> privateKey) { if (publicKey.Length != PublicKeySizeInBytes) { throw new ArgumentException("privateKey.Count must be 32"); } if (privateKey.Length != PrivateKeySizeInBytes) { throw new ArgumentException("privateKey.Count must be 32"); } // hack: abusing publicKey as temporary storage // todo: remove hack for (int i = 0; i < 32; i++) { publicKey[i] = privateKey[i]; } ScalarOperations.sc_clamp(publicKey); GroupElementP3 A; GroupOperations.ge_scalarmult_base(out A, publicKey); EdwardsToMontgomeryX(out var publicKeyFE, ref A.Y, ref A.Z); FieldOperations.fe_tobytes(publicKey, in publicKeyFE); }
public static void GetPublicKey(ArraySegment <byte> publicKey, ArraySegment <byte> privateKey) { if (publicKey.Array == null) { throw new ArgumentNullException("publicKey.Array"); } if (privateKey.Array == null) { throw new ArgumentNullException("privateKey.Array"); } if (publicKey.Count != PublicKeySizeInBytes) { throw new ArgumentException("privateKey.Count must be 32"); } if (privateKey.Count != PrivateKeySizeInBytes) { throw new ArgumentException("privateKey.Count must be 32"); } // hack: abusing publicKey as temporary storage // todo: remove hack for (int i = 0; i < 32; i++) { publicKey.Array[publicKey.Offset + i] = privateKey.Array[privateKey.Offset + i]; } ScalarOperations.sc_clamp(publicKey.Array, publicKey.Offset); GroupElementP3 A; GroupOperations.ge_scalarmult_base(out A, publicKey.Array, publicKey.Offset); FieldElement publicKeyFE; EdwardsToMontgomeryX(out publicKeyFE, ref A.Y, ref A.Z); FieldOperations.fe_tobytes(publicKey.Array, publicKey.Offset, ref publicKeyFE); }
public static void CryptoSign( byte[] sig, int sigoffset, byte[] m, int moffset, int mlen, byte[] sk, int skoffset) { var hasher = new Sha512(); { hasher.Update(sk, skoffset, 32); var az = hasher.Finalize(); ScalarOperations.Clamp(az, 0); hasher.Init(); hasher.Update(az, 32, 32); hasher.Update(m, moffset, mlen); var r = hasher.Finalize(); ScalarOperations.Reduce(r); GroupElementP3 R; GroupOperations.ScalarMultBase(out R, r, 0); GroupOperations.P3ToBytes(sig, sigoffset, ref R); hasher.Init(); hasher.Update(sig, sigoffset, 32); hasher.Update(sk, skoffset + 32, 32); hasher.Update(m, moffset, mlen); var hram = hasher.Finalize(); ScalarOperations.Reduce(hram); var s = new byte[32]; Array.Copy(sig, sigoffset + 32, s, 0, 32); ScalarOperations.MulAdd(s, hram, az, r); Array.Copy(s, 0, sig, sigoffset + 32, 32); CryptoBytes.Wipe(s); } }
public static void KeyExchange(Span <byte> sharedKey, ReadOnlySpan <byte> publicKey, ReadOnlySpan <byte> privateKey) { if (sharedKey.Length != 32) { throw new ArgumentException("sharedKey.Count != 32"); } if (publicKey.Length != 32) { throw new ArgumentException("publicKey.Count != 32"); } if (privateKey.Length != 64) { throw new ArgumentException("privateKey.Count != 64"); } FieldOperations.fe_frombytes(out var edwardsY, publicKey); FieldOperations.fe_1(out var edwardsZ); MontgomeryCurve25519.EdwardsToMontgomeryX(out var montgomeryX, ref edwardsY, ref edwardsZ); Span <byte> h = stackalloc byte[64]; Sha512.Hash(privateKey.Slice(0, 32), h); ScalarOperations.sc_clamp(h); MontgomeryOperations.scalarmult(out var sharedMontgomeryX, h, in montgomeryX); CryptoBytes.Wipe(h); FieldOperations.fe_tobytes(sharedKey, in sharedMontgomeryX); }
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); }
private static GroupElementP3 Hash2Point(byte[] hashed) { byte[] hashValue = HashFactory.Crypto.SHA3.CreateKeccak256().ComputeBytes(hashed).GetBytes(); //byte[] hashValue = HashFactory.Crypto.SHA3.CreateKeccak512().ComputeBytes(hashed).GetBytes(); ScalarOperations.sc_reduce32(hashValue); GroupOperations.ge_fromfe_frombytes_vartime(out GroupElementP2 p2, hashValue, 0); GroupOperations.ge_mul8(out GroupElementP1P1 p1p1, ref p2); GroupOperations.ge_p1p1_to_p3(out GroupElementP3 p3, ref p1p1); return(p3); }
public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey, bool naclCompat = false) { if (sharedKey.Array == null) { throw new ArgumentNullException("sharedKey.Array"); } if (publicKey.Array == null) { throw new ArgumentNullException("publicKey.Array"); } if (privateKey.Array == null) { throw new ArgumentNullException("privateKey"); } if (sharedKey.Count != SharedKeySizeInBytes) { throw new ArgumentException("sharedKey.Count != 32"); } if (publicKey.Count != PublicKeySizeInBytes) { throw new ArgumentException("publicKey.Count != 32"); } if (privateKey.Count != ExpandedPrivateKeySizeInBytes) { throw new ArgumentException("privateKey.Count != 64"); } FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX; FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset); FieldOperations.fe_1(out edwardsZ); Curve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ); IHash hasher = AuthenticatorFactory.CreateHashPrimitive(HashFunction.Sha512); hasher.BlockUpdate(privateKey.Array, privateKey.Offset, 32); byte[] h = new byte[64]; hasher.DoFinal(h, 0); ScalarOperations.sc_clamp(h, 0); MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX); h.SecureWipe(); FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX); if (naclCompat) { Curve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset); } }
public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey) { if (sharedKey.Array == null) { throw new ArgumentNullException("sharedKey.Array"); } if (publicKey.Array == null) { throw new ArgumentNullException("publicKey.Array"); } if (privateKey.Array == null) { throw new ArgumentNullException("privateKey"); } if (sharedKey.Count != 32) { throw new ArgumentException("sharedKey.Count != 32"); } if (publicKey.Count != 32) { throw new ArgumentException("publicKey.Count != 32"); } if (privateKey.Count != 64) { throw new ArgumentException("privateKey.Count != 64"); } FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX; FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset); FieldOperations.fe_1(out edwardsZ); MontgomeryCurve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ); var blake2bConfig = new Blake2BConfig { OutputSizeInBytes = 64 }; var hasher = Blake2B.Create(blake2bConfig); hasher.Update(privateKey.Array, privateKey.Offset, 32); byte[] h = hasher.Finish(); //byte[] h = Sha512.Hash(privateKey.Array, privateKey.Offset, 32);//ToDo: Remove alloc ScalarOperations.sc_clamp(h, 0); MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX); CryptoBytes.Wipe(h); FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX); MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset); }
internal static void crypto_sign2( byte[] sig, byte[] m, byte[] sk, int keylen) { byte[] privHash = new byte[64]; byte[] seededHash = new byte[64]; byte[] result = new byte[64]; GroupElementP3 R = new GroupElementP3(); var hasher = new KeccakDigest(512); { var reversedPrivateKey = new byte[keylen]; Array.Copy(sk, 0, reversedPrivateKey, 0, keylen); Array.Reverse(reversedPrivateKey); hasher.BlockUpdate(reversedPrivateKey, 0, keylen); hasher.DoFinal(privHash, 0); ScalarOperations.sc_clamp(privHash, 0); hasher.Reset(); hasher.BlockUpdate(privHash, 32, 32); hasher.BlockUpdate(m, 0, m.Length); hasher.DoFinal(seededHash, 0); ScalarOperations.sc_reduce(seededHash); GroupOperations.ge_scalarmult_base(out R, seededHash, 0); GroupOperations.ge_p3_tobytes(sig, 0, ref R); hasher.Reset(); hasher.BlockUpdate(sig, 0, 32); hasher.BlockUpdate(sk, keylen, 32); hasher.BlockUpdate(m, 0, m.Length); hasher.DoFinal(result, 0); ScalarOperations.sc_reduce(result); var s = new byte[32]; //todo: remove allocation Array.Copy(sig, 32, s, 0, 32); ScalarOperations.sc_muladd(s, result, privHash, seededHash); Array.Copy(s, 0, sig, 32, 32); CryptoBytes.Wipe(s); } }
public static void key_derive(byte[] shared, byte[] salt, byte[] secretKey, byte[] pubkey) { var longKeyHash = new byte[64]; var shortKeyHash = new byte[32]; Array.Reverse(secretKey); // compute Sha3(512) hash of secret key (as in prepareForScalarMultiply) var digestSha3 = new KeccakDigest(512); digestSha3.BlockUpdate(secretKey, 0, 32); digestSha3.DoFinal(longKeyHash, 0); longKeyHash[0] &= 248; longKeyHash[31] &= 127; longKeyHash[31] |= 64; Array.Copy(longKeyHash, 0, shortKeyHash, 0, 32); ScalarOperations.sc_clamp(shortKeyHash, 0); var p = new[] { new long[16], new long[16], new long[16], new long[16] }; var q = new[] { new long[16], new long[16], new long[16], new long[16] }; TweetNaCl.TweetNaCl.Unpackneg(q, pubkey); // returning -1 invalid signature TweetNaCl.TweetNaCl.Scalarmult(p, q, shortKeyHash, 0); TweetNaCl.TweetNaCl.Pack(shared, p); // for some reason the most significant bit of the last byte needs to be flipped. // doesnt seem to be any corrosponding action in nano/nem.core, so this may be an issue in one of the above 3 functions. i have no idea. shared[31] ^= (1 << 7); // salt for (var i = 0; i < salt.Length; i++) { shared[i] ^= salt[i]; } // hash salted shared key var digestSha3Two = new KeccakDigest(256); digestSha3Two.BlockUpdate(shared, 0, 32); digestSha3Two.DoFinal(shared, 0); }
/// <summary> /// Calculates a new public key by processing an existing one with this license bock. /// The key is calculated as following: <code>new_pub_key = pub_key * hash + parent</code>. /// Where <code>pub_key</code> and <code>parent</code> are public keys, and <code>hash</code> a private key. /// </summary> /// <param name="parent">The preceeding key (from the previous block or root key).</param> /// <returns>The new public key after processing it with this block.</returns> public byte[] DeriveKey(ReadOnlySpan<byte> parent) { ScalarOperations.sc_clamp(Hash); GroupOperations.ge_frombytes_negate_vartime(out var pubkey, Key); GroupOperations.ge_frombytes_negate_vartime(out var parkey, parent); GroupOperations.ge_scalarmult_vartime(out GroupElementP1P1 res, Hash, pubkey); GroupOperations.ge_p3_to_cached(out var pargrp, parkey); GroupOperations.ge_p1p1_to_p3(out var r, res); GroupOperations.ge_add(out var a, r, pargrp); GroupOperations.ge_p1p1_to_p3(out var r2, a); var final = new byte[32]; GroupOperations.ge_p3_tobytes(final, r2); final[31] ^= 0x80; return final; }
public static void crypto_sign_keypair(byte[] pk, int pkoffset, byte[] sk, int skoffset, byte[] seed, int seedoffset) { GroupElementP3 A; int i; Array.Copy(seed, seedoffset, sk, skoffset, 32); byte[] h = SHA512.Hash(sk, skoffset, 32);//ToDo: Remove alloc ScalarOperations.sc_clamp(h, 0); GroupOperations.ge_scalarmult_base(out A, h, 0); GroupOperations.ge_p3_tobytes(pk, pkoffset, ref A); for (i = 0; i < 32; ++i) { sk[skoffset + 32 + i] = pk[pkoffset + i]; } CryptoExtensions.Wipe(h); }
public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey) { if (sharedKey.Array == null) { throw new ArgumentNullException(nameof(sharedKey)); } if (publicKey.Array == null) { throw new ArgumentNullException(nameof(sharedKey)); } if (privateKey.Array == null) { throw new ArgumentNullException("privateKey"); } if (sharedKey.Count != 32) { throw new ArgumentException("sharedKey.Count != 32"); } if (publicKey.Count != 32) { throw new ArgumentException("publicKey.Count != 32"); } if (privateKey.Count != 64) { throw new ArgumentException("privateKey.Count != 64"); } FieldOperations.fe_frombytes(out FieldElement edwardsY, publicKey.Array, publicKey.Offset); FieldOperations.fe_1(out FieldElement edwardsZ); MontgomeryCurve25519.EdwardsToMontgomeryX(out FieldElement montgomeryX, ref edwardsY, ref edwardsZ); byte[] h = Sha512.Hash(privateKey.Array, privateKey.Offset, 32); ScalarOperations.ScClamp(h, 0); MontgomeryOperations.ScalarMult(out FieldElement sharedMontgomeryX, h, 0, ref montgomeryX); CryptoBytes.Wipe(h); FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX); MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset); }
public static void CryptoSignKeyPair(byte[] pk, int pkoffset, byte[] sk, int skoffset, byte[] seed, int seedoffset) { int i; Array.Copy(seed, seedoffset, sk, skoffset, 32); var h = Sha512.Hash(sk, skoffset, 32); ScalarOperations.Clamp(h, 0); GroupOperations.ScalarMultBase(out var A, h, 0); GroupOperations.P3ToBytes(pk, pkoffset, ref A); for (i = 0; i < 32; ++i) { sk[skoffset + 32 + i] = pk[pkoffset + i]; } CryptoBytes.Wipe(h); }
public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey) { if (sharedKey.Array == null) { throw new ArgumentNullException("sharedKey.Array"); } if (publicKey.Array == null) { throw new ArgumentNullException("publicKey.Array"); } if (privateKey.Array == null) { throw new ArgumentNullException("privateKey"); } if (sharedKey.Count != 32) { throw new ArgumentException("sharedKey.Count != 32"); } if (publicKey.Count != 32) { throw new ArgumentException("publicKey.Count != 32"); } if (privateKey.Count != 64) { throw new ArgumentException("privateKey.Count != 64"); } FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX; FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset); FieldOperations.fe_1(out edwardsZ); MontgomeryCurve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ); var hasher = Blake2Fast.Blake2b.CreateIncrementalHasher(64); hasher.Update(new ArraySegment <byte>(privateKey.Array, privateKey.Offset, 32)); byte[] h = hasher.Finish(); ScalarOperations.sc_clamp(h, 0); MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX); CryptoBytes.Wipe(h); FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX); MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset); }
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); }
//Needs more testing public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey) { Throw.If(sharedKey.Array == null, "sharedKey.Array"); Throw.If(publicKey.Array == null, "publicKey.Array"); Throw.If(privateKey.Array == null, "privateKey"); Throw.If(sharedKey.Count != 32, "sharedKey.Count != 32"); Throw.If(publicKey.Count != 32, "publicKey.Count != 32"); Throw.If(privateKey.Count != 64, "privateKey.Count != 64"); FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX; FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset); FieldOperations.fe_1(out edwardsZ); EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ); byte[] h = SHA512.Hash(privateKey.Array, privateKey.Offset, 32);//ToDo: Remove alloc ScalarOperations.sc_clamp(h, 0); MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX); CryptoExtensions.Wipe(h); FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX); KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset); }
public static bool crypto_sign_verify( byte[] sig, int sigoffset, byte[] m, int moffset, int mlen, byte[] pk, int pkoffset) { byte[] h; byte[] checkr = new byte[32]; GroupElementP3 A; GroupElementP2 R; if ((sig[sigoffset + 63] & 224) != 0) { return(false); } if (GroupOperations.ge_frombytes_negate_vartime(out A, pk, pkoffset) != 0) { return(false); } var hasher = new Sha512(); hasher.Update(sig, sigoffset, 32); hasher.Update(pk, pkoffset, 32); hasher.Update(m, moffset, mlen); h = hasher.Finalize(); ScalarOperations.sc_reduce(h); var sm32 = new byte[32]; Array.Copy(sig, sigoffset + 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, sig, sigoffset, 32); CryptoBytes.Wipe(h); CryptoBytes.Wipe(checkr); return(result); }
public static bool CryptoSignVerify( byte[] sig, int sigoffset, byte[] m, int moffset, int mlen, byte[] pk, int pkoffset) { var checker = new byte[32]; GroupElementP3 A; GroupElementP2 R; if ((sig[sigoffset + 63] & 224) != 0) { return(false); } if (GroupOperations.FromBytes(out A, pk, pkoffset) != 0) { return(false); } var hasher = new Sha512(); hasher.Update(sig, sigoffset, 32); hasher.Update(pk, pkoffset, 32); hasher.Update(m, moffset, mlen); var h = hasher.Finalize(); ScalarOperations.Reduce(h); var sm32 = new byte[32]; Array.Copy(sig, sigoffset + 32, sm32, 0, 32); GroupOperations.DoubleScalarMult(out R, h, ref A, sm32); GroupOperations.ToBytes(checker, 0, ref R); var result = CryptoBytes.ConstantTimeEquals(checker, 0, sig, sigoffset, 32); CryptoBytes.Wipe(h); CryptoBytes.Wipe(checker); return(result); }
public static void GenerateSignature( byte[] sig, int sigoffset, byte[] m, int moffset, int mlen, byte[] sk, int skoffset) { byte[] az; byte[] r; byte[] hram; GroupElementP3 R; var hasher = new SHA512(); { hasher.Update(sk, skoffset, 32); az = hasher.Finish(); ScalarOperations.sc_clamp(az, 0); hasher.Init(); hasher.Update(az, 32, 32); hasher.Update(m, moffset, mlen); r = hasher.Finish(); 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.Finish(); 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); CryptoExtensions.Wipe(s); } }
private static byte[] GetRandomSeed(bool reduced = false) { byte[] seed = new byte[32]; if (!reduced) { RNGCryptoServiceProvider.Create().GetNonZeroBytes(seed); } else { byte[] limit = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 }; bool isZero = false, less32 = false; do { RNGCryptoServiceProvider.Create().GetNonZeroBytes(seed); isZero = ScalarOperations.sc_isnonzero(seed) == 0; less32 = Less32(seed, limit); } while (isZero && !less32); ScalarOperations.sc_reduce32(seed); } return(seed); }
internal static void scalarmult( out FieldElement q, byte[] n, int noffset, ref FieldElement p) { byte[] e = new byte[32]; //ToDo: remove allocation UInt32 i; FieldElement x1; FieldElement x2; FieldElement z2; FieldElement x3; FieldElement z3; FieldElement tmp0; FieldElement tmp1; int pos; UInt32 swap; UInt32 b; for (i = 0; i < 32; ++i) { e[i] = n[noffset + i]; } ScalarOperations.sc_clamp(e, 0); x1 = p; FieldOperations.fe_1(out x2); FieldOperations.fe_0(out z2); x3 = x1; FieldOperations.fe_1(out z3); swap = 0; for (pos = 254; pos >= 0; --pos) { b = (uint)(e[pos / 8] >> (pos & 7)); b &= 1; swap ^= b; FieldOperations.fe_cswap(ref x2, ref x3, swap); FieldOperations.fe_cswap(ref z2, ref z3, swap); swap = b; /* qhasm: fe X2 */ /* qhasm: fe Z2 */ /* qhasm: fe X3 */ /* qhasm: fe Z3 */ /* qhasm: fe X4 */ /* qhasm: fe Z4 */ /* qhasm: fe X5 */ /* qhasm: fe Z5 */ /* qhasm: fe A */ /* qhasm: fe B */ /* qhasm: fe C */ /* qhasm: fe D */ /* qhasm: fe E */ /* qhasm: fe AA */ /* qhasm: fe BB */ /* qhasm: fe DA */ /* qhasm: fe CB */ /* qhasm: fe t0 */ /* qhasm: fe t1 */ /* qhasm: fe t2 */ /* qhasm: fe t3 */ /* qhasm: fe t4 */ /* qhasm: enter ladder */ /* qhasm: D = X3-Z3 */ /* asm 1: fe_sub(>D=fe#5,<X3=fe#3,<Z3=fe#4); */ /* asm 2: fe_sub(>D=tmp0,<X3=x3,<Z3=z3); */ FieldOperations.fe_sub(out tmp0, ref x3, ref z3); /* qhasm: B = X2-Z2 */ /* asm 1: fe_sub(>B=fe#6,<X2=fe#1,<Z2=fe#2); */ /* asm 2: fe_sub(>B=tmp1,<X2=x2,<Z2=z2); */ FieldOperations.fe_sub(out tmp1, ref x2, ref z2); /* qhasm: A = X2+Z2 */ /* asm 1: fe_add(>A=fe#1,<X2=fe#1,<Z2=fe#2); */ /* asm 2: fe_add(>A=x2,<X2=x2,<Z2=z2); */ FieldOperations.fe_add(out x2, ref x2, ref z2); /* qhasm: C = X3+Z3 */ /* asm 1: fe_add(>C=fe#2,<X3=fe#3,<Z3=fe#4); */ /* asm 2: fe_add(>C=z2,<X3=x3,<Z3=z3); */ FieldOperations.fe_add(out z2, ref x3, ref z3); /* qhasm: DA = D*A */ /* asm 1: fe_mul(>DA=fe#4,<D=fe#5,<A=fe#1); */ /* asm 2: fe_mul(>DA=z3,<D=tmp0,<A=x2); */ FieldOperations.fe_mul(out z3, ref tmp0, ref x2); /* qhasm: CB = C*B */ /* asm 1: fe_mul(>CB=fe#2,<C=fe#2,<B=fe#6); */ /* asm 2: fe_mul(>CB=z2,<C=z2,<B=tmp1); */ FieldOperations.fe_mul(out z2, ref z2, ref tmp1); /* qhasm: BB = B^2 */ /* asm 1: fe_sq(>BB=fe#5,<B=fe#6); */ /* asm 2: fe_sq(>BB=tmp0,<B=tmp1); */ FieldOperations.fe_sq(out tmp0, ref tmp1); /* qhasm: AA = A^2 */ /* asm 1: fe_sq(>AA=fe#6,<A=fe#1); */ /* asm 2: fe_sq(>AA=tmp1,<A=x2); */ FieldOperations.fe_sq(out tmp1, ref x2); /* qhasm: t0 = DA+CB */ /* asm 1: fe_add(>t0=fe#3,<DA=fe#4,<CB=fe#2); */ /* asm 2: fe_add(>t0=x3,<DA=z3,<CB=z2); */ FieldOperations.fe_add(out x3, ref z3, ref z2); /* qhasm: assign x3 to t0 */ /* qhasm: t1 = DA-CB */ /* asm 1: fe_sub(>t1=fe#2,<DA=fe#4,<CB=fe#2); */ /* asm 2: fe_sub(>t1=z2,<DA=z3,<CB=z2); */ FieldOperations.fe_sub(out z2, ref z3, ref z2); /* qhasm: X4 = AA*BB */ /* asm 1: fe_mul(>X4=fe#1,<AA=fe#6,<BB=fe#5); */ /* asm 2: fe_mul(>X4=x2,<AA=tmp1,<BB=tmp0); */ FieldOperations.fe_mul(out x2, ref tmp1, ref tmp0); /* qhasm: E = AA-BB */ /* asm 1: fe_sub(>E=fe#6,<AA=fe#6,<BB=fe#5); */ /* asm 2: fe_sub(>E=tmp1,<AA=tmp1,<BB=tmp0); */ FieldOperations.fe_sub(out tmp1, ref tmp1, ref tmp0); /* qhasm: t2 = t1^2 */ /* asm 1: fe_sq(>t2=fe#2,<t1=fe#2); */ /* asm 2: fe_sq(>t2=z2,<t1=z2); */ FieldOperations.fe_sq(out z2, ref z2); /* qhasm: t3 = a24*E */ /* asm 1: fe_mul121666(>t3=fe#4,<E=fe#6); */ /* asm 2: fe_mul121666(>t3=z3,<E=tmp1); */ FieldOperations.fe_mul121666(out z3, ref tmp1); /* qhasm: X5 = t0^2 */ /* asm 1: fe_sq(>X5=fe#3,<t0=fe#3); */ /* asm 2: fe_sq(>X5=x3,<t0=x3); */ FieldOperations.fe_sq(out x3, ref x3); /* qhasm: t4 = BB+t3 */ /* asm 1: fe_add(>t4=fe#5,<BB=fe#5,<t3=fe#4); */ /* asm 2: fe_add(>t4=tmp0,<BB=tmp0,<t3=z3); */ FieldOperations.fe_add(out tmp0, ref tmp0, ref z3); /* qhasm: Z5 = X1*t2 */ /* asm 1: fe_mul(>Z5=fe#4,x1,<t2=fe#2); */ /* asm 2: fe_mul(>Z5=z3,x1,<t2=z2); */ FieldOperations.fe_mul(out z3, ref x1, ref z2); /* qhasm: Z4 = E*t4 */ /* asm 1: fe_mul(>Z4=fe#2,<E=fe#6,<t4=fe#5); */ /* asm 2: fe_mul(>Z4=z2,<E=tmp1,<t4=tmp0); */ FieldOperations.fe_mul(out z2, ref tmp1, ref tmp0); /* qhasm: return */ } FieldOperations.fe_cswap(ref x2, ref x3, swap); FieldOperations.fe_cswap(ref z2, ref z3, swap); FieldOperations.fe_invert(out z2, ref z2); FieldOperations.fe_mul(out x2, ref x2, ref z2); q = x2; CryptoExtensions.Wipe(e); }
private static void ScalarMult( out FieldElement q, byte[] n, int noffset, ref FieldElement p) { var e = new byte[32]; //ToDo: remove allocation FieldElement tmp1; for (var i = 0; i < 32; ++i) { e[i] = n[noffset + i]; } ScalarOperations.Clamp(e, 0); var x1 = p; FieldOperations.FieldOperations_1(out var x2); FieldOperations.FieldOperations_0(out var z2); var x3 = x1; FieldOperations.FieldOperations_1(out var z3); uint swap = 0; for (var pos = 254; pos >= 0; --pos) { var b = (uint)(e[pos / 8] >> (pos & 7)); b &= 1; swap ^= b; FieldOperations.ControlledSwap(ref x2, ref x3, swap); FieldOperations.ControlledSwap(ref z2, ref z3, swap); swap = b; /* qhasm: enter ladder */ /* qhasm: D = X3-Z3 */ /* asm 1: Subtract(>D=fe#5,<X3=fe#3,<Z3=fe#4); */ /* asm 2: Subtract(>D=tmp0,<X3=x3,<Z3=z3); */ FieldOperations.Subtract(out var tmp0, ref x3, ref z3); /* qhasm: B = X2-Z2 */ /* asm 1: Subtract(>B=fe#6,<X2=fe#1,<Z2=fe#2); */ /* asm 2: Subtract(>B=tmp1,<X2=x2,<Z2=z2); */ FieldOperations.Subtract(out tmp1, ref x2, ref z2); /* qhasm: A = X2+Z2 */ /* asm 1: Add(>A=fe#1,<X2=fe#1,<Z2=fe#2); */ /* asm 2: Add(>A=x2,<X2=x2,<Z2=z2); */ FieldOperations.Add(out x2, ref x2, ref z2); /* qhasm: C = X3+Z3 */ /* asm 1: Add(>C=fe#2,<X3=fe#3,<Z3=fe#4); */ /* asm 2: Add(>C=z2,<X3=x3,<Z3=z3); */ FieldOperations.Add(out z2, ref x3, ref z3); /* qhasm: DA = D*A */ /* asm 1: Multiplication(>DA=fe#4,<D=fe#5,<A=fe#1); */ /* asm 2: Multiplication(>DA=z3,<D=tmp0,<A=x2); */ FieldOperations.Multiplication(out z3, ref tmp0, ref x2); /* qhasm: CB = C*B */ /* asm 1: Multiplication(>CB=fe#2,<C=fe#2,<B=fe#6); */ /* asm 2: Multiplication(>CB=z2,<C=z2,<B=tmp1); */ FieldOperations.Multiplication(out z2, ref z2, ref tmp1); /* qhasm: BB = B^2 */ /* asm 1: Square(>BB=fe#5,<B=fe#6); */ /* asm 2: Square(>BB=tmp0,<B=tmp1); */ FieldOperations.Square(out tmp0, ref tmp1); /* qhasm: AA = A^2 */ /* asm 1: Square(>AA=fe#6,<A=fe#1); */ /* asm 2: Square(>AA=tmp1,<A=x2); */ FieldOperations.Square(out tmp1, ref x2); /* qhasm: t0 = DA+CB */ /* asm 1: Add(>t0=fe#3,<DA=fe#4,<CB=fe#2); */ /* asm 2: Add(>t0=x3,<DA=z3,<CB=z2); */ FieldOperations.Add(out x3, ref z3, ref z2); /* qhasm: assign x3 to t0 */ /* qhasm: t1 = DA-CB */ /* asm 1: Subtract(>t1=fe#2,<DA=fe#4,<CB=fe#2); */ /* asm 2: Subtract(>t1=z2,<DA=z3,<CB=z2); */ FieldOperations.Subtract(out z2, ref z3, ref z2); /* qhasm: X4 = AA*BB */ /* asm 1: Multiplication(>X4=fe#1,<AA=fe#6,<BB=fe#5); */ /* asm 2: Multiplication(>X4=x2,<AA=tmp1,<BB=tmp0); */ FieldOperations.Multiplication(out x2, ref tmp1, ref tmp0); /* qhasm: E = AA-BB */ /* asm 1: Subtract(>E=fe#6,<AA=fe#6,<BB=fe#5); */ /* asm 2: Subtract(>E=tmp1,<AA=tmp1,<BB=tmp0); */ FieldOperations.Subtract(out tmp1, ref tmp1, ref tmp0); /* qhasm: t2 = t1^2 */ /* asm 1: Square(>t2=fe#2,<t1=fe#2); */ /* asm 2: Square(>t2=z2,<t1=z2); */ FieldOperations.Square(out z2, ref z2); /* qhasm: t3 = a24*E */ /* asm 1: Multiplication121666(>t3=fe#4,<E=fe#6); */ /* asm 2: Multiplication121666(>t3=z3,<E=tmp1); */ FieldOperations.Multiplication121666(out z3, ref tmp1); /* qhasm: X5 = t0^2 */ /* asm 1: Square(>X5=fe#3,<t0=fe#3); */ /* asm 2: Square(>X5=x3,<t0=x3); */ FieldOperations.Square(out x3, ref x3); /* qhasm: t4 = BB+t3 */ /* asm 1: Add(>t4=fe#5,<BB=fe#5,<t3=fe#4); */ /* asm 2: Add(>t4=tmp0,<BB=tmp0,<t3=z3); */ FieldOperations.Add(out tmp0, ref tmp0, ref z3); /* qhasm: Z5 = X1*t2 */ /* asm 1: Multiplication(>Z5=fe#4,x1,<t2=fe#2); */ /* asm 2: Multiplication(>Z5=z3,x1,<t2=z2); */ FieldOperations.Multiplication(out z3, ref x1, ref z2); /* qhasm: Z4 = E*t4 */ /* asm 1: Multiplication(>Z4=fe#2,<E=fe#6,<t4=fe#5); */ /* asm 2: Multiplication(>Z4=z2,<E=tmp1,<t4=tmp0); */ FieldOperations.Multiplication(out z2, ref tmp1, ref tmp0); /* qhasm: return */ } FieldOperations.ControlledSwap(ref x2, ref x3, swap); FieldOperations.ControlledSwap(ref z2, ref z3, swap); FieldOperations.Invert(out z2, ref z2); FieldOperations.Multiplication(out x2, ref x2, ref z2); q = x2; CryptoBytes.Wipe(e); }
public byte[] CreateResponse(string password, ReadOnlySpan <byte> authenticationData) { // Java reference: https://github.com/MariaDB/mariadb-connector-j/blob/master/src/main/java/org/mariadb/jdbc/internal/com/send/authentication/Ed25519PasswordPlugin.java // C reference: https://github.com/MariaDB/server/blob/592fe954ef82be1bc08b29a8e54f7729eb1e1343/plugin/auth_ed25519/ref10/sign.c#L7 /*** Java * byte[] bytePwd; * if (passwordCharacterEncoding != null && !passwordCharacterEncoding.isEmpty()) { * bytePwd = password.getBytes(passwordCharacterEncoding); * } else { * bytePwd = password.getBytes(); * } */ byte[] passwordBytes = Encoding.UTF8.GetBytes(password); /*** Java * MessageDigest hash = MessageDigest.getInstance("SHA-512"); * * byte[] az = hash.digest(bytePwd); * az[0] &= 248; * az[31] &= 63; * az[31] |= 64; */ /*** C * unsigned char az[64]; * * crypto_hash_sha512(az,pw,pwlen); * az[0] &= 248; * az[31] &= 63; * az[31] |= 64; */ using (var sha512 = SHA512.Create()) { byte[] az = sha512.ComputeHash(passwordBytes); ScalarOperations.sc_clamp(az, 0); /*** Java * int mlen = seed.length; * final byte[] sm = new byte[64 + mlen]; * * System.arraycopy(seed, 0, sm, 64, mlen); * System.arraycopy(az, 32, sm, 32, 32); * * byte[] buff = Arrays.copyOfRange(sm, 32, 96); * hash.reset(); * byte[] nonce = hash.digest(buff); */ /*** C * unsigned char nonce[64]; * unsigned char hram[64]; * * memmove(sm + 64,m,mlen); * memmove(sm + 32,az + 32,32); * crypto_hash_sha512(nonce,sm + 32,mlen + 32); */ byte[] sm = new byte[64 + authenticationData.Length]; authenticationData.CopyTo(sm.AsSpan().Slice(64)); Buffer.BlockCopy(az, 32, sm, 32, 32); byte[] nonce = sha512.ComputeHash(sm, 32, authenticationData.Length + 32); /*** Java * ScalarOps scalar = new ScalarOps(); * * EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("Ed25519"); * GroupElement elementAvalue = spec.getB().scalarMultiply(az); * byte[] elementAarray = elementAvalue.toByteArray(); * System.arraycopy(elementAarray, 0, sm, 32, elementAarray.length); */ /*** C * ge_p3 A; * * ge_scalarmult_base(&A,az); * ge_p3_tobytes(sm + 32,&A); */ GroupOperations.ge_scalarmult_base(out var A, az, 0); GroupOperations.ge_p3_tobytes(sm, 32, ref A); /*** Java * nonce = scalar.reduce(nonce); * GroupElement elementRvalue = spec.getB().scalarMultiply(nonce); * byte[] elementRarray = elementRvalue.toByteArray(); * System.arraycopy(elementRarray, 0, sm, 0, elementRarray.length); */ /*** C * ge_p3 R; * * sc_reduce(nonce); * ge_scalarmult_base(&R,nonce); * ge_p3_tobytes(sm,&R); */ ScalarOperations.sc_reduce(nonce); GroupOperations.ge_scalarmult_base(out var R, nonce, 0); GroupOperations.ge_p3_tobytes(sm, 0, ref R); /*** Java * hash.reset(); * byte[] hram = hash.digest(sm); * hram = scalar.reduce(hram); * byte[] tt = scalar.multiplyAndAdd(hram, az, nonce); * System.arraycopy(tt, 0, sm, 32, tt.length); * * return Arrays.copyOfRange(sm, 0, 64); */ /*** C * unsigned char hram[64]; * * crypto_hash_sha512(hram,sm,mlen + 64); * sc_reduce(hram); * sc_muladd(sm + 32,hram,az,nonce); * * return 0; */ var hram = sha512.ComputeHash(sm); ScalarOperations.sc_reduce(hram); var temp = new byte[32]; ScalarOperations.sc_muladd(temp, hram, az, nonce); Buffer.BlockCopy(temp, 0, sm, 32, temp.Length); var result = new byte[64]; Buffer.BlockCopy(sm, 0, result, 0, result.Length); return(result); } }