/// <summary> /// Pads input bitstrings to the sponge construction to a number of bits which is a multiple of the rate. /// </summary> /// <param name="r">The rate of the sponge construction.</param> /// <param name="m">The length of the bitstring whose length to pad to a multiple of <paramref name="r"/>.</param> /// <returns>A padding suffix for a bitstring of length <paramref name="m"/> being processed in a sponge /// construction with a rate <paramref name="r"/>.</returns> /// <remarks>Keccak-p permutations use a pad10*1 (multirate) padding rule.</remarks> protected override Bitstring GetPadding(int r, int m) { int j = Bin.Mod(-m - 2, r); Bitstring pad = new Bitstring(j + 2); pad[0] = true; pad[pad.Length - 1] = true; return(pad); }
/// <summary> /// Creates a new <see cref="SpongeState"/> specifying its size and rate. /// </summary> /// <param name="size">The size of the sponge state.</param> /// <param name="rate">The rate of the sponge state, i.e. the number of bits which are impacted while absorbing /// messages.</param> /// <exception cref="ArgumentException"><paramref name="rate"/> is lower than one, or <paramref name="rate"/> is /// greater than or equal to <paramref name="size"/>'s <see cref="SpongeSize.B"/>.</exception> /// <remarks> /// <para>The capacity of the state, i.e. the number of bits which are not impacted while absorbing messages, will /// be <paramref name="size"/>.B - <paramref name="rate"/>.</para> /// </remarks> public SpongeState(SpongeSize size, int rate) { int b = size.B; if ((rate < 1) || (rate >= b)) { throw new ArgumentException($"Invalid rate {rate} for width {b}.", nameof(rate)); } _size = size; _rate = rate; _bitstring = Bitstring.Zeroes(b); }
/// <summary> /// Squeezes internal state until at least specified number of bits is produced, and returns these bits. /// </summary> /// <param name="outputLength">The number of desired output bits.</param> /// <returns>The byte array holding resulting bits.</returns> protected virtual byte[] Squeeze(int outputLength) { int rate = State.Rate; Bitstring q = new Bitstring(); while (true) { q.Append(State.Bitstring.Truncate(rate)); if (q.Length >= outputLength) { return((q.Length == outputLength) ? q.Bytes : q.Truncate(outputLength).Bytes); } Function(); } }
/// <summary> /// Creates a new <see cref="SpongeState"/> from an existing bitstring and specified rate. /// </summary> /// <param name="bitstring">The bitstring which holds the bits of the sponge state.</param> /// <param name="rate">The number of bits which are impacted while aborbing messages.</param> /// <exception cref="ArgumentNullException"><paramref name="bitstring"/> is null.</exception> /// <exception cref="ArgumentException"><paramref name="bitstring"/> is empty, or <paramref name="rate"/> is lower /// than one, or <paramref name="rate"/> is greater than or equal to <paramref> /// <name>size</name> /// </paramref> /// 's /// <see cref="SpongeSize.B"/>.</exception> /// <remarks> /// <para>The capacity of the state, i.e. the number of bits which are not impacted while absorbing messages, will /// be <see cref="bitstring"/>.Length - <paramref name="rate"/>.</para> /// </remarks> public SpongeState(Bitstring bitstring, int rate) { _bitstring = bitstring ?? throw new ArgumentNullException(nameof(bitstring)); int length = _bitstring.Length; if (length < 1) { throw new ArgumentException("Bitstring cannot be empty.", nameof(bitstring)); } _size = new SpongeSize(length); if ((rate < 1) || (rate >= _size.B)) { throw new ArgumentException($"Invalid rate {rate} for width {_size.B}.", nameof(rate)); } _rate = rate; }
/// <summary> /// /// </summary> /// <param name="bytes"></param> /// <param name="length"></param> protected virtual void Absorb(byte[] bytes, int length) { State.Clear(); Bitstring message = new Bitstring(bytes, length); int rate = State.Rate; message.Append(Suffix()); message.Append(GetPadding(rate, message.Length)); int n = message.Length / rate; Bitstring zeroes = new Bitstring(Capacity); Bitstring chunk; for (int i = 0; i < n; i++) { chunk = message.Substring(rate * i, rate); chunk.Append(zeroes); State.Bitstring.Xor(chunk); Function(); } }
private static SpongeState Iota(SpongeState state, int round) { int w = state.Size.W; int l = state.Size.L; Bitstring rc = Bitstring.Zeroes(w); RoundT roundT; int t; int rnd = 7 * round; for (int j = 0; j <= l; j++) { t = j + rnd; roundT = new RoundT(round, t); if (!_roundTConstants.ContainsKey(roundT)) { _roundTConstants.Add(roundT, RoundConstant(t)); } rc[(1 << j) - 1] = _roundTConstants[roundT]; } state.XorLane(state.GetLane(0, 0), rc); return(state); }
private static bool RoundConstant(int t) { t = Bin.Mod(t, 255); if (_roundConstants.ContainsKey(t)) { return(_roundConstants[t]); } Bitstring r = new Bitstring("10000000", 8); for (int i = 0; i < t; i++) { r.Prepend(Bitstring.Zero); r[0] ^= r[8]; r[4] ^= r[8]; r[5] ^= r[8]; r[6] ^= r[8]; r = r.Truncate(8); } bool bit = r[0]; _roundConstants.Add(t, bit); return(bit); }
/// <summary> /// Sets the bitstring holding the bits of this state to specified value. /// </summary> /// <param name="bitstring">The bitstring by which replacing this state's internal bitstring.</param> /// <remarks>Unchecked version of <see cref="Bitstring"/> setter. Internal use only.</remarks> internal void SetBitstring(Bitstring bitstring) { _bitstring = bitstring; }
/// <summary> /// Creates a new <see cref="SpongeState"/> from an existing one. /// </summary> /// <param name="state">The sponge state to copy.</param> public SpongeState(SpongeState state) { _size = state._size; _rate = state._rate; _bitstring = new Bitstring(state._bitstring); }
public override void Initialize() { _hash = new Bitstring(); }
protected override byte[] HashFinal() { _hash = new Bitstring(_permutation.Process(_hash.Bytes, _permutation.Width)); return(_hash?.Bytes ?? new byte[0]); }