KMac.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs
  8. {
  9. public class KMac
  10. : IMac, IXof
  11. {
  12. private static readonly byte[] padding = new byte[100];
  13. private readonly CShakeDigest cshake;
  14. private readonly int bitLength;
  15. private readonly int outputLength;
  16. private byte[] key;
  17. private bool initialised;
  18. private bool firstOutput;
  19. public KMac(int bitLength, byte[] S)
  20. {
  21. this.cshake = new CShakeDigest(bitLength, Strings.ToAsciiByteArray("KMAC"), S);
  22. this.bitLength = bitLength;
  23. this.outputLength = bitLength * 2 / 8;
  24. }
  25. public string AlgorithmName
  26. {
  27. get { return "KMAC" + cshake.AlgorithmName.Substring(6); }
  28. }
  29. public void BlockUpdate(byte[] input, int inOff, int len)
  30. {
  31. if (!initialised)
  32. throw new InvalidOperationException("KMAC not initialized");
  33. cshake.BlockUpdate(input, inOff, len);
  34. }
  35. public int DoFinal(byte[] output, int outOff)
  36. {
  37. if (firstOutput)
  38. {
  39. if (!initialised)
  40. throw new InvalidOperationException("KMAC not initialized");
  41. byte[] encOut = XofUtilities.RightEncode(GetMacSize() * 8);
  42. cshake.BlockUpdate(encOut, 0, encOut.Length);
  43. }
  44. int rv = cshake.DoFinal(output, outOff, GetMacSize());
  45. Reset();
  46. return rv;
  47. }
  48. public int DoFinal(byte[] output, int outOff, int outLen)
  49. {
  50. if (firstOutput)
  51. {
  52. if (!initialised)
  53. throw new InvalidOperationException("KMAC not initialized");
  54. byte[] encOut = XofUtilities.RightEncode(outLen * 8);
  55. cshake.BlockUpdate(encOut, 0, encOut.Length);
  56. }
  57. int rv = cshake.DoFinal(output, outOff, outLen);
  58. Reset();
  59. return rv;
  60. }
  61. public int DoOutput(byte[] output, int outOff, int outLen)
  62. {
  63. if (firstOutput)
  64. {
  65. if (!initialised)
  66. throw new InvalidOperationException("KMAC not initialized");
  67. byte[] encOut = XofUtilities.RightEncode(0);
  68. cshake.BlockUpdate(encOut, 0, encOut.Length);
  69. firstOutput = false;
  70. }
  71. return cshake.DoOutput(output, outOff, outLen);
  72. }
  73. public int GetByteLength()
  74. {
  75. return cshake.GetByteLength();
  76. }
  77. public int GetDigestSize()
  78. {
  79. return outputLength;
  80. }
  81. public int GetMacSize()
  82. {
  83. return outputLength;
  84. }
  85. public void Init(ICipherParameters parameters)
  86. {
  87. KeyParameter kParam = (KeyParameter)parameters;
  88. this.key = Arrays.Clone(kParam.GetKey());
  89. this.initialised = true;
  90. Reset();
  91. }
  92. public void Reset()
  93. {
  94. cshake.Reset();
  95. if (key != null)
  96. {
  97. if (bitLength == 128)
  98. {
  99. bytePad(key, 168);
  100. }
  101. else
  102. {
  103. bytePad(key, 136);
  104. }
  105. }
  106. firstOutput = true;
  107. }
  108. private void bytePad(byte[] X, int w)
  109. {
  110. byte[] bytes = XofUtilities.LeftEncode(w);
  111. BlockUpdate(bytes, 0, bytes.Length);
  112. byte[] encX = encode(X);
  113. BlockUpdate(encX, 0, encX.Length);
  114. int required = w - ((bytes.Length + encX.Length) % w);
  115. if (required > 0 && required != w)
  116. {
  117. while (required > padding.Length)
  118. {
  119. BlockUpdate(padding, 0, padding.Length);
  120. required -= padding.Length;
  121. }
  122. BlockUpdate(padding, 0, required);
  123. }
  124. }
  125. private static byte[] encode(byte[] X)
  126. {
  127. return Arrays.Concatenate(XofUtilities.LeftEncode(X.Length * 8), X);
  128. }
  129. public void Update(byte input)
  130. {
  131. if (!initialised)
  132. throw new InvalidOperationException("KMAC not initialized");
  133. cshake.Update(input);
  134. }
  135. }
  136. }
  137. #pragma warning restore
  138. #endif