#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) using System; using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Digests { /** * FIPS 180-4 implementation of SHA-512/t */ public class Sha512tDigest : LongDigest { private const ulong A5 = 0xa5a5a5a5a5a5a5a5UL; private readonly int digestLength; private ulong H1t, H2t, H3t, H4t, H5t, H6t, H7t, H8t; /** * Standard constructor */ public Sha512tDigest(int bitLength) { if (bitLength >= 512) throw new ArgumentException("cannot be >= 512", "bitLength"); if (bitLength % 8 != 0) throw new ArgumentException("needs to be a multiple of 8", "bitLength"); if (bitLength == 384) throw new ArgumentException("cannot be 384 use SHA384 instead", "bitLength"); this.digestLength = bitLength / 8; tIvGenerate(digestLength * 8); Reset(); } /** * Copy constructor. This will copy the state of the provided * message digest. */ public Sha512tDigest(Sha512tDigest t) : base(t) { this.digestLength = t.digestLength; Reset(t); } public override string AlgorithmName { get { return "SHA-512/" + (digestLength * 8); } } public override int GetDigestSize() { return digestLength; } public override int DoFinal(byte[] output, int outOff) { Finish(); UInt64_To_BE(H1, output, outOff, digestLength); UInt64_To_BE(H2, output, outOff + 8, digestLength - 8); UInt64_To_BE(H3, output, outOff + 16, digestLength - 16); UInt64_To_BE(H4, output, outOff + 24, digestLength - 24); UInt64_To_BE(H5, output, outOff + 32, digestLength - 32); UInt64_To_BE(H6, output, outOff + 40, digestLength - 40); UInt64_To_BE(H7, output, outOff + 48, digestLength - 48); UInt64_To_BE(H8, output, outOff + 56, digestLength - 56); Reset(); return digestLength; } /** * reset the chaining variables */ public override void Reset() { base.Reset(); /* * initial hash values use the iv generation algorithm for t. */ H1 = H1t; H2 = H2t; H3 = H3t; H4 = H4t; H5 = H5t; H6 = H6t; H7 = H7t; H8 = H8t; } private void tIvGenerate(int bitLength) { H1 = 0x6a09e667f3bcc908UL ^ A5; H2 = 0xbb67ae8584caa73bUL ^ A5; H3 = 0x3c6ef372fe94f82bUL ^ A5; H4 = 0xa54ff53a5f1d36f1UL ^ A5; H5 = 0x510e527fade682d1UL ^ A5; H6 = 0x9b05688c2b3e6c1fUL ^ A5; H7 = 0x1f83d9abfb41bd6bUL ^ A5; H8 = 0x5be0cd19137e2179UL ^ A5; Update(0x53); Update(0x48); Update(0x41); Update(0x2D); Update(0x35); Update(0x31); Update(0x32); Update(0x2F); if (bitLength > 100) { Update((byte)(bitLength / 100 + 0x30)); bitLength = bitLength % 100; Update((byte)(bitLength / 10 + 0x30)); bitLength = bitLength % 10; Update((byte)(bitLength + 0x30)); } else if (bitLength > 10) { Update((byte)(bitLength / 10 + 0x30)); bitLength = bitLength % 10; Update((byte)(bitLength + 0x30)); } else { Update((byte)(bitLength + 0x30)); } Finish(); H1t = H1; H2t = H2; H3t = H3; H4t = H4; H5t = H5; H6t = H6; H7t = H7; H8t = H8; } private static void UInt64_To_BE(ulong n, byte[] bs, int off, int max) { if (max > 0) { UInt32_To_BE((uint)(n >> 32), bs, off, max); if (max > 4) { UInt32_To_BE((uint)n, bs, off + 4, max - 4); } } } private static void UInt32_To_BE(uint n, byte[] bs, int off, int max) { int num = System.Math.Min(4, max); while (--num >= 0) { int shift = 8 * (3 - num); bs[off + num] = (byte)(n >> shift); } } public override IMemoable Copy() { return new Sha512tDigest(this); } public override void Reset(IMemoable other) { Sha512tDigest t = (Sha512tDigest)other; if (this.digestLength != t.digestLength) { throw new MemoableResetException("digestLength inappropriate in other"); } base.CopyIn(t); this.H1t = t.H1t; this.H2t = t.H2t; this.H3t = t.H3t; this.H4t = t.H4t; this.H5t = t.H5t; this.H6t = t.H6t; this.H7t = t.H7t; this.H8t = t.H8t; } } } #endif