Sha512tDigest.cs 6.8 KB

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