FastSicBlockCipher.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Modes;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Math;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  9. namespace Best.HTTP.Shared.TLS.Crypto.Impl
  10. {
  11. /**
  12. * Implements the Segmented Integer Counter (SIC) mode on top of a simple
  13. * block cipher.
  14. */
  15. public class FastSicBlockCipher
  16. : IBlockCipherMode
  17. {
  18. private readonly IBlockCipher cipher;
  19. private readonly int blockSize;
  20. private readonly byte[] counter;
  21. private readonly byte[] counterOut;
  22. private byte[] IV;
  23. /**
  24. * Basic constructor.
  25. *
  26. * @param c the block cipher to be used.
  27. */
  28. public FastSicBlockCipher(IBlockCipher cipher)
  29. {
  30. this.cipher = cipher;
  31. this.blockSize = cipher.GetBlockSize();
  32. this.counter = new byte[blockSize];
  33. this.counterOut = new byte[blockSize];
  34. this.IV = new byte[blockSize];
  35. }
  36. /**
  37. * return the underlying block cipher that we are wrapping.
  38. *
  39. * @return the underlying block cipher that we are wrapping.
  40. */
  41. public IBlockCipher UnderlyingCipher => cipher;
  42. public virtual void Init(
  43. bool forEncryption, //ignored by this CTR mode
  44. ICipherParameters parameters)
  45. {
  46. ParametersWithIV ivParam = parameters as ParametersWithIV;
  47. if (ivParam == null)
  48. throw new ArgumentException("CTR/SIC mode requires ParametersWithIV", "parameters");
  49. this.IV = Arrays.Clone(ivParam.GetIV());
  50. if (blockSize < IV.Length)
  51. throw new ArgumentException("CTR/SIC mode requires IV no greater than: " + blockSize + " bytes.");
  52. int maxCounterSize = System.Math.Min(8, blockSize / 2);
  53. if (blockSize - IV.Length > maxCounterSize)
  54. throw new ArgumentException("CTR/SIC mode requires IV of at least: " + (blockSize - maxCounterSize) + " bytes.");
  55. // if null it's an IV changed only.
  56. if (ivParam.Parameters != null)
  57. {
  58. cipher.Init(true, ivParam.Parameters);
  59. }
  60. Reset();
  61. }
  62. public virtual string AlgorithmName
  63. {
  64. get { return cipher.AlgorithmName + "/SIC"; }
  65. }
  66. public virtual bool IsPartialBlockOkay
  67. {
  68. get { return true; }
  69. }
  70. public virtual int GetBlockSize()
  71. {
  72. return cipher.GetBlockSize();
  73. }
  74. public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
  75. {
  76. cipher.ProcessBlock(counter, 0, counterOut, 0);
  77. //
  78. // XOR the counterOut with the plaintext producing the cipher text
  79. //
  80. for (int i = 0; i < counterOut.Length; i++)
  81. {
  82. output[outOff + i] = (byte)(counterOut[i] ^ input[inOff + i]);
  83. }
  84. // Increment the counter
  85. int j = counter.Length;
  86. while (--j >= 0 && ++counter[j] == 0)
  87. {
  88. }
  89. return counter.Length;
  90. }
  91. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  92. public virtual int ProcessBlock(ReadOnlySpan<byte> input, Span<byte> output)
  93. {
  94. cipher.ProcessBlock(counter, 0, counterOut, 0);
  95. //
  96. // XOR the counterOut with the plaintext producing the cipher text
  97. //
  98. for (int i = 0; i < counterOut.Length; i++)
  99. {
  100. output[i] = (byte)(counterOut[i] ^ input[i]);
  101. }
  102. // Increment the counter
  103. int j = counter.Length;
  104. while (--j >= 0 && ++counter[j] == 0)
  105. {
  106. }
  107. return counter.Length;
  108. }
  109. #endif
  110. public virtual void Reset()
  111. {
  112. Arrays.Fill(counter, (byte)0);
  113. Array.Copy(IV, 0, counter, 0, IV.Length);
  114. }
  115. }
  116. }
  117. #pragma warning restore
  118. #endif