private static void ProcessInternal(byte[] ciphertext, int ciphertextOffset, byte[] message, int messageOffset, int messageLength, byte[] key, int keyOffset, byte[] nonce, int nonceOffset) { Array16 <UInt32> internalKey; PrepareInternalKey(out internalKey, key, keyOffset, nonce, nonceOffset); Array16 <UInt32> temp; byte[] tempBytes = new byte[64];//todo: remove allocation int blockOffset = 0; while (blockOffset < messageLength) { //internalKey.x8++; SalsaCore.Salsa(out temp, ref internalKey, 20); ByteIntegerConverter.Array16StoreLittleEndian32(tempBytes, 0, ref temp); int count = Math.Min(64, messageLength - blockOffset); for (int i = 0; i < count; i++) { ciphertext[ciphertextOffset + blockOffset + i] = (byte)(message[messageOffset + blockOffset + i] ^ tempBytes[i]); } blockOffset += 64; internalKey.x8++; } CryptoBytes.Wipe(tempBytes); // DON'T LEAK! }
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 static byte[] ExpandedPrivateKeyFromSeed(byte[] privateKeySeed) { byte[] privateKey; byte[] publicKey; KeyPairFromSeed(out publicKey, out privateKey, privateKeySeed); CryptoBytes.Wipe(publicKey); return(privateKey); }
public static byte[] ExpandedPrivateKeyFromSeed(ReadOnlySpan <byte> privateKeySeed) { Span <byte> publicKey = stackalloc byte[PublicKeySizeInBytes]; var privateKey = new byte[ExpandedPrivateKeySizeInBytes]; KeyPairFromSeed(publicKey, privateKey, privateKeySeed); CryptoBytes.Wipe(publicKey); return(privateKey); }
/// <summary> /// Calculate public key from private key seed /// </summary> /// <param name="privateKeySeed">Private key seed value</param> /// <returns></returns> public static byte[] PublicKeyFromSeed(byte[] privateKeySeed) { Contract.Requires <ArgumentNullException>(privateKeySeed != null); Contract.Requires <ArgumentException>(privateKeySeed.Length == PrivateKeySeedSize); byte[] privateKey; byte[] publicKey; KeyPairFromSeed(out publicKey, out privateKey, privateKeySeed); CryptoBytes.Wipe(privateKey); return(publicKey); }
public void Finish(Span <byte> output) { if (output.Length != 64) { throw new ArgumentException("output.Count must be 64"); } Update(_padding); Array16 <ulong> block; ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer); CryptoBytes.Wipe(_buffer, 0, _buffer.Length); int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); if (bytesInBuffer > BlockSize - 16) { Sha512Internal.Core(out _state, in _state, in block); block = default; } block = new Array16 <ulong>( block.x0, block.x1, block.x2, block.x3, block.x4, block.x5, block.x6, block.x7, block.x8, block.x9, block.x10, block.x11, block.x12, block.x13, block.x14, (_totalBytes - 1) * 8); Sha512Internal.Core(out _state, in _state, in block); BinaryPrimitives.WriteUInt64BigEndian(output.Slice(0), _state.x0); BinaryPrimitives.WriteUInt64BigEndian(output.Slice(8), _state.x1); BinaryPrimitives.WriteUInt64BigEndian(output.Slice(16), _state.x2); BinaryPrimitives.WriteUInt64BigEndian(output.Slice(24), _state.x3); BinaryPrimitives.WriteUInt64BigEndian(output.Slice(32), _state.x4); BinaryPrimitives.WriteUInt64BigEndian(output.Slice(40), _state.x5); BinaryPrimitives.WriteUInt64BigEndian(output.Slice(48), _state.x6); BinaryPrimitives.WriteUInt64BigEndian(output.Slice(56), _state.x7); _state = default; }
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); }
public 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 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 void Update(ReadOnlySpan <byte> data) { Array16 <ulong> block; int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); _totalBytes += (uint)data.Length; var bufferSpan = _buffer.AsSpan(); if (_totalBytes >= ulong.MaxValue / 8) { throw new InvalidOperationException("Too much data"); } // Fill existing buffer if (bytesInBuffer != 0) { var toCopy = Math.Min(BlockSize - bytesInBuffer, data.Length); data.Slice(0, toCopy).CopyTo(bufferSpan.Slice(bytesInBuffer)); data = data.Slice(toCopy); bytesInBuffer += toCopy; if (bytesInBuffer == BlockSize) { ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer); Sha512Internal.Core(out _state, in _state, in block); CryptoBytes.Wipe(_buffer, 0, _buffer.Length); bytesInBuffer = 0; } } // Hash complete blocks without copying while (data.Length >= BlockSize) { ByteIntegerConverter.Array16LoadBigEndian64(out block, data); Sha512Internal.Core(out _state, in _state, in block); data = data.Slice(BlockSize); } // Copy remainder into buffer if (data.Length > 0) { data.CopyTo(bufferSpan.Slice(bytesInBuffer)); } }
public static void KeyExchange(ArraySegment \ \ sharedKey, ArraySegment \ \ publicKey, ArraySegment \ \ 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); 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); }
public static byte[] PublicKeyFromSeed(byte[] privateKeySeed) { KeyPairFromSeed(out var publicKey, out var privateKey, privateKeySeed); CryptoBytes.Wipe(privateKey); return(publicKey); }