Sha512tDigest.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using Org.BouncyCastle.Crypto.Utilities;
  4. using Org.BouncyCastle.Utilities;
  5. namespace Org.BouncyCastle.Crypto.Digests
  6. {
  7. /**
  8. * FIPS 180-4 implementation of SHA-512/t
  9. */
  10. public class Sha512tDigest
  11. : LongDigest
  12. {
  13. private const ulong A5 = 0xa5a5a5a5a5a5a5a5UL;
  14. private readonly int digestLength;
  15. private ulong H1t, H2t, H3t, H4t, H5t, H6t, H7t, H8t;
  16. /**
  17. * Standard constructor
  18. */
  19. public Sha512tDigest(int bitLength)
  20. {
  21. if (bitLength >= 512)
  22. throw new ArgumentException("cannot be >= 512", "bitLength");
  23. if (bitLength % 8 != 0)
  24. throw new ArgumentException("needs to be a multiple of 8", "bitLength");
  25. if (bitLength == 384)
  26. throw new ArgumentException("cannot be 384 use SHA384 instead", "bitLength");
  27. this.digestLength = bitLength / 8;
  28. tIvGenerate(digestLength * 8);
  29. Reset();
  30. }
  31. /**
  32. * Copy constructor. This will copy the state of the provided
  33. * message digest.
  34. */
  35. public Sha512tDigest(Sha512tDigest t)
  36. : base(t)
  37. {
  38. this.digestLength = t.digestLength;
  39. Reset(t);
  40. }
  41. public override string AlgorithmName
  42. {
  43. get { return "SHA-512/" + (digestLength * 8); }
  44. }
  45. public override int GetDigestSize()
  46. {
  47. return digestLength;
  48. }
  49. public override int DoFinal(byte[] output, int outOff)
  50. {
  51. Finish();
  52. UInt64_To_BE(H1, output, outOff, digestLength);
  53. UInt64_To_BE(H2, output, outOff + 8, digestLength - 8);
  54. UInt64_To_BE(H3, output, outOff + 16, digestLength - 16);
  55. UInt64_To_BE(H4, output, outOff + 24, digestLength - 24);
  56. UInt64_To_BE(H5, output, outOff + 32, digestLength - 32);
  57. UInt64_To_BE(H6, output, outOff + 40, digestLength - 40);
  58. UInt64_To_BE(H7, output, outOff + 48, digestLength - 48);
  59. UInt64_To_BE(H8, output, outOff + 56, digestLength - 56);
  60. Reset();
  61. return digestLength;
  62. }
  63. /**
  64. * reset the chaining variables
  65. */
  66. public override void Reset()
  67. {
  68. base.Reset();
  69. /*
  70. * initial hash values use the iv generation algorithm for t.
  71. */
  72. H1 = H1t;
  73. H2 = H2t;
  74. H3 = H3t;
  75. H4 = H4t;
  76. H5 = H5t;
  77. H6 = H6t;
  78. H7 = H7t;
  79. H8 = H8t;
  80. }
  81. private void tIvGenerate(int bitLength)
  82. {
  83. H1 = 0x6a09e667f3bcc908UL ^ A5;
  84. H2 = 0xbb67ae8584caa73bUL ^ A5;
  85. H3 = 0x3c6ef372fe94f82bUL ^ A5;
  86. H4 = 0xa54ff53a5f1d36f1UL ^ A5;
  87. H5 = 0x510e527fade682d1UL ^ A5;
  88. H6 = 0x9b05688c2b3e6c1fUL ^ A5;
  89. H7 = 0x1f83d9abfb41bd6bUL ^ A5;
  90. H8 = 0x5be0cd19137e2179UL ^ A5;
  91. Update(0x53);
  92. Update(0x48);
  93. Update(0x41);
  94. Update(0x2D);
  95. Update(0x35);
  96. Update(0x31);
  97. Update(0x32);
  98. Update(0x2F);
  99. if (bitLength > 100)
  100. {
  101. Update((byte)(bitLength / 100 + 0x30));
  102. bitLength = bitLength % 100;
  103. Update((byte)(bitLength / 10 + 0x30));
  104. bitLength = bitLength % 10;
  105. Update((byte)(bitLength + 0x30));
  106. }
  107. else if (bitLength > 10)
  108. {
  109. Update((byte)(bitLength / 10 + 0x30));
  110. bitLength = bitLength % 10;
  111. Update((byte)(bitLength + 0x30));
  112. }
  113. else
  114. {
  115. Update((byte)(bitLength + 0x30));
  116. }
  117. Finish();
  118. H1t = H1;
  119. H2t = H2;
  120. H3t = H3;
  121. H4t = H4;
  122. H5t = H5;
  123. H6t = H6;
  124. H7t = H7;
  125. H8t = H8;
  126. }
  127. private static void UInt64_To_BE(ulong n, byte[] bs, int off, int max)
  128. {
  129. if (max > 0)
  130. {
  131. UInt32_To_BE((uint)(n >> 32), bs, off, max);
  132. if (max > 4)
  133. {
  134. UInt32_To_BE((uint)n, bs, off + 4, max - 4);
  135. }
  136. }
  137. }
  138. private static void UInt32_To_BE(uint n, byte[] bs, int off, int max)
  139. {
  140. int num = System.Math.Min(4, max);
  141. while (--num >= 0)
  142. {
  143. int shift = 8 * (3 - num);
  144. bs[off + num] = (byte)(n >> shift);
  145. }
  146. }
  147. public override IMemoable Copy()
  148. {
  149. return new Sha512tDigest(this);
  150. }
  151. public override void Reset(IMemoable other)
  152. {
  153. Sha512tDigest t = (Sha512tDigest)other;
  154. if (this.digestLength != t.digestLength)
  155. {
  156. throw new MemoableResetException("digestLength inappropriate in other");
  157. }
  158. base.CopyIn(t);
  159. this.H1t = t.H1t;
  160. this.H2t = t.H2t;
  161. this.H3t = t.H3t;
  162. this.H4t = t.H4t;
  163. this.H5t = t.H5t;
  164. this.H6t = t.H6t;
  165. this.H7t = t.H7t;
  166. this.H8t = t.H8t;
  167. }
  168. }
  169. }
  170. #endif