CSHAKEDigest.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. /// Customizable SHAKE function.
  9. /// </summary>
  10. public class CShakeDigest
  11. : ShakeDigest
  12. {
  13. private static readonly byte[] padding = new byte[100];
  14. private static byte[] EncodeString(byte[] str)
  15. {
  16. if (Arrays.IsNullOrEmpty(str))
  17. {
  18. return XofUtilities.LeftEncode(0L);
  19. }
  20. return Arrays.Concatenate(XofUtilities.LeftEncode(str.Length * 8L), str);
  21. }
  22. private readonly byte[] diff;
  23. /// <summary>
  24. /// Base constructor
  25. /// </summary>
  26. /// <param name="bitLength">bit length of the underlying SHAKE function, 128 or 256.</param>
  27. /// <param name="N">the function name string, note this is reserved for use by NIST. Avoid using it if not required.</param>
  28. /// <param name="S">the customization string - available for local use.</param>
  29. public CShakeDigest(int bitLength, byte[] N, byte[] S)
  30. : base(bitLength)
  31. {
  32. if ((N == null || N.Length == 0) && (S == null || S.Length == 0))
  33. {
  34. diff = null;
  35. }
  36. else
  37. {
  38. diff = Arrays.ConcatenateAll(XofUtilities.LeftEncode(rate / 8), EncodeString(N), EncodeString(S));
  39. DiffPadAndAbsorb();
  40. }
  41. }
  42. public CShakeDigest(CShakeDigest source)
  43. : base(source)
  44. {
  45. this.diff = Arrays.Clone(source.diff);
  46. }
  47. // bytepad in SP 800-185
  48. private void DiffPadAndAbsorb()
  49. {
  50. int blockSize = rate / 8;
  51. Absorb(diff, 0, diff.Length);
  52. int delta = diff.Length % blockSize;
  53. // only add padding if needed
  54. if (delta != 0)
  55. {
  56. int required = blockSize - delta;
  57. while (required > padding.Length)
  58. {
  59. Absorb(padding, 0, padding.Length);
  60. required -= padding.Length;
  61. }
  62. Absorb(padding, 0, required);
  63. }
  64. }
  65. public override string AlgorithmName
  66. {
  67. get { return "CSHAKE" + fixedOutputLength; }
  68. }
  69. public override int DoOutput(byte[] output, int outOff, int outLen)
  70. {
  71. if (diff == null)
  72. {
  73. return base.DoOutput(output, outOff, outLen);
  74. }
  75. if (!squeezing)
  76. {
  77. AbsorbBits(0x00, 2);
  78. }
  79. Squeeze(output, outOff, ((long)outLen) << 3);
  80. return outLen;
  81. }
  82. public override void Reset()
  83. {
  84. base.Reset();
  85. if (diff != null)
  86. {
  87. DiffPadAndAbsorb();
  88. }
  89. }
  90. }
  91. }
  92. #pragma warning restore
  93. #endif