RFC3394WrapEngine.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  6. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines
  7. {
  8. /// <remarks>
  9. /// An implementation of the AES Key Wrapper from the NIST Key Wrap
  10. /// Specification as described in RFC 3394.
  11. /// <p/>
  12. /// For further details see: <a href="http://www.ietf.org/rfc/rfc3394.txt">http://www.ietf.org/rfc/rfc3394.txt</a>
  13. /// and <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
  14. /// </remarks>
  15. public class Rfc3394WrapEngine
  16. : IWrapper
  17. {
  18. private readonly IBlockCipher engine;
  19. private KeyParameter param;
  20. private bool forWrapping;
  21. private byte[] iv =
  22. {
  23. 0xa6, 0xa6, 0xa6, 0xa6,
  24. 0xa6, 0xa6, 0xa6, 0xa6
  25. };
  26. public Rfc3394WrapEngine(
  27. IBlockCipher engine)
  28. {
  29. this.engine = engine;
  30. }
  31. public virtual void Init(
  32. bool forWrapping,
  33. ICipherParameters parameters)
  34. {
  35. this.forWrapping = forWrapping;
  36. if (parameters is ParametersWithRandom)
  37. {
  38. parameters = ((ParametersWithRandom) parameters).Parameters;
  39. }
  40. if (parameters is KeyParameter)
  41. {
  42. this.param = (KeyParameter) parameters;
  43. }
  44. else if (parameters is ParametersWithIV)
  45. {
  46. ParametersWithIV pIV = (ParametersWithIV) parameters;
  47. byte[] iv = pIV.GetIV();
  48. if (iv.Length != 8)
  49. throw new ArgumentException("IV length not equal to 8", "parameters");
  50. this.iv = iv;
  51. this.param = (KeyParameter) pIV.Parameters;
  52. }
  53. else
  54. {
  55. // TODO Throw an exception for bad parameters?
  56. }
  57. }
  58. public virtual string AlgorithmName
  59. {
  60. get { return engine.AlgorithmName; }
  61. }
  62. public virtual byte[] Wrap(
  63. byte[] input,
  64. int inOff,
  65. int inLen)
  66. {
  67. if (!forWrapping)
  68. {
  69. throw new InvalidOperationException("not set for wrapping");
  70. }
  71. int n = inLen / 8;
  72. if ((n * 8) != inLen)
  73. {
  74. throw new DataLengthException("wrap data must be a multiple of 8 bytes");
  75. }
  76. byte[] block = new byte[inLen + iv.Length];
  77. byte[] buf = new byte[8 + iv.Length];
  78. Array.Copy(iv, 0, block, 0, iv.Length);
  79. Array.Copy(input, inOff, block, iv.Length, inLen);
  80. engine.Init(true, param);
  81. for (int j = 0; j != 6; j++)
  82. {
  83. for (int i = 1; i <= n; i++)
  84. {
  85. Array.Copy(block, 0, buf, 0, iv.Length);
  86. Array.Copy(block, 8 * i, buf, iv.Length, 8);
  87. engine.ProcessBlock(buf, 0, buf, 0);
  88. int t = n * j + i;
  89. for (int k = 1; t != 0; k++)
  90. {
  91. byte v = (byte)t;
  92. buf[iv.Length - k] ^= v;
  93. t = (int) ((uint)t >> 8);
  94. }
  95. Array.Copy(buf, 0, block, 0, 8);
  96. Array.Copy(buf, 8, block, 8 * i, 8);
  97. }
  98. }
  99. return block;
  100. }
  101. public virtual byte[] Unwrap(
  102. byte[] input,
  103. int inOff,
  104. int inLen)
  105. {
  106. if (forWrapping)
  107. {
  108. throw new InvalidOperationException("not set for unwrapping");
  109. }
  110. int n = inLen / 8;
  111. if ((n * 8) != inLen)
  112. {
  113. throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
  114. }
  115. byte[] block = new byte[inLen - iv.Length];
  116. byte[] a = new byte[iv.Length];
  117. byte[] buf = new byte[8 + iv.Length];
  118. Array.Copy(input, inOff, a, 0, iv.Length);
  119. Array.Copy(input, inOff + iv.Length, block, 0, inLen - iv.Length);
  120. engine.Init(false, param);
  121. n = n - 1;
  122. for (int j = 5; j >= 0; j--)
  123. {
  124. for (int i = n; i >= 1; i--)
  125. {
  126. Array.Copy(a, 0, buf, 0, iv.Length);
  127. Array.Copy(block, 8 * (i - 1), buf, iv.Length, 8);
  128. int t = n * j + i;
  129. for (int k = 1; t != 0; k++)
  130. {
  131. byte v = (byte)t;
  132. buf[iv.Length - k] ^= v;
  133. t = (int) ((uint)t >> 8);
  134. }
  135. engine.ProcessBlock(buf, 0, buf, 0);
  136. Array.Copy(buf, 0, a, 0, 8);
  137. Array.Copy(buf, 8, block, 8 * (i - 1), 8);
  138. }
  139. }
  140. if (!Arrays.ConstantTimeAreEqual(a, iv))
  141. throw new InvalidCipherTextException("checksum failed");
  142. return block;
  143. }
  144. }
  145. }
  146. #pragma warning restore
  147. #endif