/// <summary> /// Updates internal state with data from the provided array. /// </summary> /// <param name="data">Array of bytes</param> /// <param name="index">Offset of byte sequence</param> /// <param name="length">Sequence length</param> public void Update(byte[] data, int index, int length) { Array16 <ulong> block; int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); _totalBytes += (uint)length; if (_totalBytes >= ulong.MaxValue / 8) { throw new InvalidOperationException("Too much data"); } // Fill existing buffer if (bytesInBuffer != 0) { var toCopy = Math.Min(BlockSize - bytesInBuffer, length); Buffer.BlockCopy(data, index, _buffer, bytesInBuffer, toCopy); index += toCopy; length -= 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 (length >= BlockSize) { ByteIntegerConverter.Array16LoadBigEndian64(out block, data, index); Sha512Internal.Core(out _state, ref _state, ref block); index += BlockSize; length -= BlockSize; } // Copy remainder into buffer if (length > 0) { Buffer.BlockCopy(data, index, _buffer, bytesInBuffer, length); } }
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); }