DSTU7564Mac.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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.Digests;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
  7. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs
  8. {
  9. /// <summary>
  10. /// Implementation of DSTU7564 mac mode
  11. /// </summary>
  12. public class Dstu7564Mac
  13. : IMac
  14. {
  15. private Dstu7564Digest engine;
  16. private int macSize;
  17. private ulong inputLength;
  18. byte[] paddedKey;
  19. byte[] invertedKey;
  20. public string AlgorithmName
  21. {
  22. get { return "DSTU7564Mac"; }
  23. }
  24. public Dstu7564Mac(int macSizeBits)
  25. {
  26. engine = new Dstu7564Digest(macSizeBits);
  27. macSize = macSizeBits / 8;
  28. }
  29. public void Init(ICipherParameters parameters)
  30. {
  31. if (parameters is KeyParameter)
  32. {
  33. byte[] key = ((KeyParameter)parameters).GetKey();
  34. invertedKey = new byte[key.Length];
  35. paddedKey = PadKey(key);
  36. for (int byteIndex = 0; byteIndex < invertedKey.Length; byteIndex++)
  37. {
  38. invertedKey[byteIndex] = (byte)(key[byteIndex] ^ (byte)0xFF);
  39. }
  40. }
  41. else
  42. {
  43. throw new ArgumentException("Bad parameter passed");
  44. }
  45. engine.BlockUpdate(paddedKey, 0, paddedKey.Length);
  46. }
  47. public int GetMacSize()
  48. {
  49. return macSize;
  50. }
  51. public void BlockUpdate(byte[] input, int inOff, int len)
  52. {
  53. Check.DataLength(input, inOff, len, "input buffer too short");
  54. if (paddedKey == null)
  55. throw new InvalidOperationException(AlgorithmName + " not initialised");
  56. engine.BlockUpdate(input, inOff, len);
  57. inputLength += (ulong)len;
  58. }
  59. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  60. public void BlockUpdate(ReadOnlySpan<byte> input)
  61. {
  62. if (paddedKey == null)
  63. throw new InvalidOperationException(AlgorithmName + " not initialised");
  64. engine.BlockUpdate(input);
  65. inputLength += (ulong)input.Length;
  66. }
  67. #endif
  68. public void Update(byte input)
  69. {
  70. engine.Update(input);
  71. inputLength++;
  72. }
  73. public int DoFinal(byte[] output, int outOff)
  74. {
  75. if (paddedKey == null)
  76. throw new InvalidOperationException(AlgorithmName + " not initialised");
  77. Check.OutputLength(output, outOff, macSize, "output buffer too short");
  78. Pad();
  79. engine.BlockUpdate(invertedKey, 0, invertedKey.Length);
  80. inputLength = 0;
  81. return engine.DoFinal(output, outOff);
  82. }
  83. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  84. public int DoFinal(Span<byte> output)
  85. {
  86. if (paddedKey == null)
  87. throw new InvalidOperationException(AlgorithmName + " not initialised");
  88. Check.OutputLength(output, macSize, "output buffer too short");
  89. Pad();
  90. engine.BlockUpdate(invertedKey);
  91. inputLength = 0;
  92. return engine.DoFinal(output);
  93. }
  94. #endif
  95. public void Reset()
  96. {
  97. inputLength = 0;
  98. engine.Reset();
  99. if (paddedKey != null)
  100. {
  101. engine.BlockUpdate(paddedKey, 0, paddedKey.Length);
  102. }
  103. }
  104. private void Pad()
  105. {
  106. int extra = engine.GetByteLength() - (int)(inputLength % (ulong)engine.GetByteLength());
  107. if (extra < 13) // terminator byte + 96 bits of length
  108. {
  109. extra += engine.GetByteLength();
  110. }
  111. byte[] padded = new byte[extra];
  112. padded[0] = (byte)0x80; // Defined in standard;
  113. // Defined in standard;
  114. Pack.UInt64_To_LE(inputLength * 8, padded, padded.Length - 12);
  115. engine.BlockUpdate(padded, 0, padded.Length);
  116. }
  117. private byte[] PadKey(byte[] input)
  118. {
  119. int paddedLen = ((input.Length + engine.GetByteLength() - 1) / engine.GetByteLength()) * engine.GetByteLength();
  120. int extra = engine.GetByteLength() - (int)(input.Length % engine.GetByteLength());
  121. if (extra < 13) // terminator byte + 96 bits of length
  122. {
  123. paddedLen += engine.GetByteLength();
  124. }
  125. byte[] padded = new byte[paddedLen];
  126. Array.Copy(input, 0, padded, 0, input.Length);
  127. padded[input.Length] = (byte)0x80; // Defined in standard;
  128. Pack.UInt32_To_LE((uint)(input.Length * 8), padded, padded.Length - 12); // Defined in standard;
  129. return padded;
  130. }
  131. }
  132. }
  133. #pragma warning restore
  134. #endif