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 void Finish(ArraySegment <byte> output) { if (output.Array == null) { throw new ArgumentNullException(nameof(output)); } if (output.Count != 64) { throw new ArgumentException("output.Count must be 64"); } Update(Padding, 0, Padding.Length); ByteIntegerConverter.Array16LoadBigEndian64(out Array16 <ulong> block, _buffer, 0); CryptoBytes.InternalWipe(_buffer, 0, _buffer.Length); int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); if (bytesInBuffer > BlockSize - 16) { Sha512Internal.Core(out _state, ref _state, ref block); block = default(Array16 <ulong>); } block.x15 = (_totalBytes - 1) * 8; Sha512Internal.Core(out _state, ref _state, ref block); ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 0, _state.x0); ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 8, _state.x1); ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 16, _state.x2); ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 24, _state.x3); ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 32, _state.x4); ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 40, _state.x5); ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 48, _state.x6); ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 56, _state.x7); _state = default(Array8 <ulong>); }
public void Update(byte[] data, int offset, int count) { if (data == null) { throw new ArgumentNullException(nameof(data)); } if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count)); } if (data.Length - offset < count) { throw new ArgumentException("Requires offset + count <= data.Length"); } Array16 <ulong> block; int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); _totalBytes += (uint)count; if (_totalBytes >= ulong.MaxValue / 8) { throw new InvalidOperationException("Too much data"); } // Fill existing buffer if (bytesInBuffer != 0) { int toCopy = Math.Min(BlockSize - bytesInBuffer, count); Buffer.BlockCopy(data, offset, _buffer, bytesInBuffer, toCopy); offset += toCopy; count -= toCopy; bytesInBuffer += toCopy; if (bytesInBuffer == BlockSize) { ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer, 0); Sha512Internal.Core(out _state, ref _state, ref block); CryptoBytes.InternalWipe(_buffer, 0, _buffer.Length); bytesInBuffer = 0; } } // Hash complete blocks without copying while (count >= BlockSize) { ByteIntegerConverter.Array16LoadBigEndian64(out block, data, offset); Sha512Internal.Core(out _state, ref _state, ref block); offset += BlockSize; count -= BlockSize; } // Copy remainder into buffer if (count > 0) { Buffer.BlockCopy(data, offset, _buffer, bytesInBuffer, count); } }
public static byte[] ExpandedPrivateKeyFromSeed(byte[] privateKeySeed) { KeyPairFromSeed(out byte[] publicKey, out byte[] privateKey, privateKeySeed); CryptoBytes.Wipe(publicKey); return(privateKey); }