TupleHash.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  5. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests
  6. {
  7. /// <summary>
  8. /// TupleHash - a hash designed to simply hash a tuple of input strings, any or all of which may be empty strings,
  9. /// in an unambiguous way with an optional XOF mode.
  10. /// <para>
  11. /// From NIST Special Publication 800-185 - SHA-3 Derived Functions:cSHAKE, KMAC, TupleHash and ParallelHash
  12. /// </para>
  13. /// </summary>
  14. public class TupleHash
  15. : IXof, IDigest
  16. {
  17. private static readonly byte[] N_TUPLE_HASH = Strings.ToByteArray("TupleHash");
  18. private readonly CShakeDigest cshake;
  19. private readonly int bitLength;
  20. private readonly int outputLength;
  21. private bool firstOutput;
  22. /**
  23. * Base constructor.
  24. *
  25. * @param bitLength bit length of the underlying SHAKE function, 128 or 256.
  26. * @param S the customization string - available for local use.
  27. */
  28. public TupleHash(int bitLength, byte[] S)
  29. : this(bitLength, S, bitLength * 2)
  30. {
  31. }
  32. public TupleHash(int bitLength, byte[] S, int outputSize)
  33. {
  34. this.cshake = new CShakeDigest(bitLength, N_TUPLE_HASH, S);
  35. this.bitLength = bitLength;
  36. this.outputLength = (outputSize + 7) / 8;
  37. Reset();
  38. }
  39. public TupleHash(TupleHash original)
  40. {
  41. this.cshake = new CShakeDigest(original.cshake);
  42. this.bitLength = cshake.fixedOutputLength;
  43. this.outputLength = bitLength * 2 / 8;
  44. this.firstOutput = original.firstOutput;
  45. }
  46. public virtual string AlgorithmName
  47. {
  48. get { return "TupleHash" + cshake.AlgorithmName.Substring(6); }
  49. }
  50. public virtual int GetByteLength()
  51. {
  52. return cshake.GetByteLength();
  53. }
  54. public virtual int GetDigestSize()
  55. {
  56. return outputLength;
  57. }
  58. public virtual void Update(byte b)
  59. {
  60. byte[] bytes = XofUtilities.Encode(b);
  61. cshake.BlockUpdate(bytes, 0, bytes.Length);
  62. }
  63. public virtual void BlockUpdate(byte[] inBuf, int inOff, int len)
  64. {
  65. byte[] bytes = XofUtilities.Encode(inBuf, inOff, len);
  66. cshake.BlockUpdate(bytes, 0, bytes.Length);
  67. }
  68. private void wrapUp(int outputSize)
  69. {
  70. byte[] encOut = XofUtilities.RightEncode(outputSize * 8);
  71. cshake.BlockUpdate(encOut, 0, encOut.Length);
  72. firstOutput = false;
  73. }
  74. public virtual int DoFinal(byte[] outBuf, int outOff)
  75. {
  76. if (firstOutput)
  77. {
  78. wrapUp(GetDigestSize());
  79. }
  80. int rv = cshake.DoFinal(outBuf, outOff, GetDigestSize());
  81. Reset();
  82. return rv;
  83. }
  84. public virtual int DoFinal(byte[] outBuf, int outOff, int outLen)
  85. {
  86. if (firstOutput)
  87. {
  88. wrapUp(GetDigestSize());
  89. }
  90. int rv = cshake.DoFinal(outBuf, outOff, outLen);
  91. Reset();
  92. return rv;
  93. }
  94. public virtual int DoOutput(byte[] outBuf, int outOff, int outLen)
  95. {
  96. if (firstOutput)
  97. {
  98. wrapUp(0);
  99. }
  100. return cshake.DoOutput(outBuf, outOff, outLen);
  101. }
  102. public virtual void Reset()
  103. {
  104. cshake.Reset();
  105. firstOutput = true;
  106. }
  107. }
  108. }
  109. #pragma warning restore
  110. #endif