123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- using System;
- using Org.BouncyCastle.Crypto.Parameters;
- using Org.BouncyCastle.Crypto.Utilities;
- namespace Org.BouncyCastle.Crypto.Macs
- {
- /// <summary>
- /// Implementation of SipHash as specified in "SipHash: a fast short-input PRF", by Jean-Philippe
- /// Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf).
- /// </summary>
- /// <remarks>
- /// "SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d are the number of
- /// compression rounds and the number of finalization rounds. A compression round is identical to a
- /// finalization round and this round function is called SipRound. Given a 128-bit key k and a
- /// (possibly empty) byte string m, SipHash-c-d returns a 64-bit value..."
- /// </remarks>
- public class SipHash
- : IMac
- {
- protected readonly int c, d;
- protected long k0, k1;
- protected long v0, v1, v2, v3;
- protected long m = 0;
- protected int wordPos = 0;
- protected int wordCount = 0;
- /// <summary>SipHash-2-4</summary>
- public SipHash()
- : this(2, 4)
- {
- }
- /// <summary>SipHash-c-d</summary>
- /// <param name="c">the number of compression rounds</param>
- /// <param name="d">the number of finalization rounds</param>
- public SipHash(int c, int d)
- {
- this.c = c;
- this.d = d;
- }
- public virtual string AlgorithmName
- {
- get { return "SipHash-" + c + "-" + d; }
- }
- public virtual int GetMacSize()
- {
- return 8;
- }
- public virtual void Init(ICipherParameters parameters)
- {
- KeyParameter keyParameter = parameters as KeyParameter;
- if (keyParameter == null)
- throw new ArgumentException("must be an instance of KeyParameter", "parameters");
- byte[] key = keyParameter.GetKey();
- if (key.Length != 16)
- throw new ArgumentException("must be a 128-bit key", "parameters");
- this.k0 = (long)Pack.LE_To_UInt64(key, 0);
- this.k1 = (long)Pack.LE_To_UInt64(key, 8);
- Reset();
- }
- public virtual void Update(byte input)
- {
- m = (long)(((ulong)m >> 8) | ((ulong)input << 56));
- if (++wordPos == 8)
- {
- ProcessMessageWord();
- wordPos = 0;
- }
- }
- public virtual void BlockUpdate(byte[] input, int offset, int length)
- {
- int i = 0, fullWords = length & ~7;
- if (wordPos == 0)
- {
- for (; i < fullWords; i += 8)
- {
- m = (long)Pack.LE_To_UInt64(input, offset + i);
- ProcessMessageWord();
- }
- for (; i < length; ++i)
- {
- m = (long)(((ulong)m >> 8) | ((ulong)input[offset + i] << 56));
- }
- wordPos = length - fullWords;
- }
- else
- {
- int bits = wordPos << 3;
- for (; i < fullWords; i += 8)
- {
- ulong n = Pack.LE_To_UInt64(input, offset + i);
- m = (long)((n << bits) | ((ulong)m >> -bits));
- ProcessMessageWord();
- m = (long)n;
- }
- for (; i < length; ++i)
- {
- m = (long)(((ulong)m >> 8) | ((ulong)input[offset + i] << 56));
- if (++wordPos == 8)
- {
- ProcessMessageWord();
- wordPos = 0;
- }
- }
- }
- }
- public virtual long DoFinal()
- {
- // NOTE: 2 distinct shifts to avoid "64-bit shift" when wordPos == 0
- m = (long)((ulong)m >> ((7 - wordPos) << 3));
- m = (long)((ulong)m >> 8);
- m = (long)((ulong)m | ((ulong)((wordCount << 3) + wordPos) << 56));
- ProcessMessageWord();
- v2 ^= 0xffL;
- ApplySipRounds(d);
- long result = v0 ^ v1 ^ v2 ^ v3;
- Reset();
- return result;
- }
- public virtual int DoFinal(byte[] output, int outOff)
- {
- long result = DoFinal();
- Pack.UInt64_To_LE((ulong)result, output, outOff);
- return 8;
- }
- public virtual void Reset()
- {
- v0 = k0 ^ 0x736f6d6570736575L;
- v1 = k1 ^ 0x646f72616e646f6dL;
- v2 = k0 ^ 0x6c7967656e657261L;
- v3 = k1 ^ 0x7465646279746573L;
- m = 0;
- wordPos = 0;
- wordCount = 0;
- }
- protected virtual void ProcessMessageWord()
- {
- ++wordCount;
- v3 ^= m;
- ApplySipRounds(c);
- v0 ^= m;
- }
- protected virtual void ApplySipRounds(int n)
- {
- long r0 = v0, r1 = v1, r2 = v2, r3 = v3;
- for (int r = 0; r < n; ++r)
- {
- r0 += r1;
- r2 += r3;
- r1 = RotateLeft(r1, 13);
- r3 = RotateLeft(r3, 16);
- r1 ^= r0;
- r3 ^= r2;
- r0 = RotateLeft(r0, 32);
- r2 += r1;
- r0 += r3;
- r1 = RotateLeft(r1, 17);
- r3 = RotateLeft(r3, 21);
- r1 ^= r2;
- r3 ^= r0;
- r2 = RotateLeft(r2, 32);
- }
- v0 = r0; v1 = r1; v2 = r2; v3 = r3;
- }
- protected static long RotateLeft(long x, int n)
- {
- ulong ux = (ulong)x;
- ux = (ux << n) | (ux >> -n);
- return (long)ux;
- }
- }
- }
- #endif
|