CSHAKEDigest.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  5. namespace Best.HTTP.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 Output(byte[] output, int outOff, int outLen)
  70. {
  71. if (diff == null)
  72. {
  73. return base.Output(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. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  83. public override int Output(Span<byte> output)
  84. {
  85. if (diff == null)
  86. {
  87. return base.Output(output);
  88. }
  89. if (!squeezing)
  90. {
  91. AbsorbBits(0x00, 2);
  92. }
  93. Squeeze(output);
  94. return output.Length;
  95. }
  96. #endif
  97. public override void Reset()
  98. {
  99. base.Reset();
  100. if (diff != null)
  101. {
  102. DiffPadAndAbsorb();
  103. }
  104. }
  105. }
  106. }
  107. #pragma warning restore
  108. #endif