ISO9796d1Encoding.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using Org.BouncyCastle.Crypto;
  4. using Org.BouncyCastle.Crypto.Parameters;
  5. using Org.BouncyCastle.Math;
  6. namespace Org.BouncyCastle.Crypto.Encodings
  7. {
  8. /**
  9. * ISO 9796-1 padding. Note in the light of recent results you should
  10. * only use this with RSA (rather than the "simpler" Rabin keys) and you
  11. * should never use it with anything other than a hash (ie. even if the
  12. * message is small don't sign the message, sign it's hash) or some "random"
  13. * value. See your favorite search engine for details.
  14. */
  15. public class ISO9796d1Encoding
  16. : IAsymmetricBlockCipher
  17. {
  18. private static readonly BigInteger Sixteen = BigInteger.ValueOf(16);
  19. private static readonly BigInteger Six = BigInteger.ValueOf(6);
  20. private static readonly byte[] shadows = { 0xe, 0x3, 0x5, 0x8, 0x9, 0x4, 0x2, 0xf,
  21. 0x0, 0xd, 0xb, 0x6, 0x7, 0xa, 0xc, 0x1 };
  22. private static readonly byte[] inverse = { 0x8, 0xf, 0x6, 0x1, 0x5, 0x2, 0xb, 0xc,
  23. 0x3, 0x4, 0xd, 0xa, 0xe, 0x9, 0x0, 0x7 };
  24. private readonly IAsymmetricBlockCipher engine;
  25. private bool forEncryption;
  26. private int bitSize;
  27. private int padBits = 0;
  28. private BigInteger modulus;
  29. public ISO9796d1Encoding(
  30. IAsymmetricBlockCipher cipher)
  31. {
  32. this.engine = cipher;
  33. }
  34. public string AlgorithmName
  35. {
  36. get { return engine.AlgorithmName + "/ISO9796-1Padding"; }
  37. }
  38. public IAsymmetricBlockCipher GetUnderlyingCipher()
  39. {
  40. return engine;
  41. }
  42. public void Init(
  43. bool forEncryption,
  44. ICipherParameters parameters)
  45. {
  46. RsaKeyParameters kParam;
  47. if (parameters is ParametersWithRandom)
  48. {
  49. ParametersWithRandom rParam = (ParametersWithRandom)parameters;
  50. kParam = (RsaKeyParameters)rParam.Parameters;
  51. }
  52. else
  53. {
  54. kParam = (RsaKeyParameters)parameters;
  55. }
  56. engine.Init(forEncryption, parameters);
  57. modulus = kParam.Modulus;
  58. bitSize = modulus.BitLength;
  59. this.forEncryption = forEncryption;
  60. }
  61. /**
  62. * return the input block size. The largest message we can process
  63. * is (key_size_in_bits + 3)/16, which in our world comes to
  64. * key_size_in_bytes / 2.
  65. */
  66. public int GetInputBlockSize()
  67. {
  68. int baseBlockSize = engine.GetInputBlockSize();
  69. if (forEncryption)
  70. {
  71. return (baseBlockSize + 1) / 2;
  72. }
  73. else
  74. {
  75. return baseBlockSize;
  76. }
  77. }
  78. /**
  79. * return the maximum possible size for the output.
  80. */
  81. public int GetOutputBlockSize()
  82. {
  83. int baseBlockSize = engine.GetOutputBlockSize();
  84. if (forEncryption)
  85. {
  86. return baseBlockSize;
  87. }
  88. else
  89. {
  90. return (baseBlockSize + 1) / 2;
  91. }
  92. }
  93. /**
  94. * set the number of bits in the next message to be treated as
  95. * pad bits.
  96. */
  97. public void SetPadBits(
  98. int padBits)
  99. {
  100. if (padBits > 7)
  101. {
  102. throw new ArgumentException("padBits > 7");
  103. }
  104. this.padBits = padBits;
  105. }
  106. /**
  107. * retrieve the number of pad bits in the last decoded message.
  108. */
  109. public int GetPadBits()
  110. {
  111. return padBits;
  112. }
  113. public byte[] ProcessBlock(
  114. byte[] input,
  115. int inOff,
  116. int length)
  117. {
  118. if (forEncryption)
  119. {
  120. return EncodeBlock(input, inOff, length);
  121. }
  122. else
  123. {
  124. return DecodeBlock(input, inOff, length);
  125. }
  126. }
  127. private byte[] EncodeBlock(
  128. byte[] input,
  129. int inOff,
  130. int inLen)
  131. {
  132. byte[] block = new byte[(bitSize + 7) / 8];
  133. int r = padBits + 1;
  134. int z = inLen;
  135. int t = (bitSize + 13) / 16;
  136. for (int i = 0; i < t; i += z)
  137. {
  138. if (i > t - z)
  139. {
  140. Array.Copy(input, inOff + inLen - (t - i),
  141. block, block.Length - t, t - i);
  142. }
  143. else
  144. {
  145. Array.Copy(input, inOff, block, block.Length - (i + z), z);
  146. }
  147. }
  148. for (int i = block.Length - 2 * t; i != block.Length; i += 2)
  149. {
  150. byte val = block[block.Length - t + i / 2];
  151. block[i] = (byte)((shadows[(uint) (val & 0xff) >> 4] << 4)
  152. | shadows[val & 0x0f]);
  153. block[i + 1] = val;
  154. }
  155. block[block.Length - 2 * z] ^= (byte) r;
  156. block[block.Length - 1] = (byte)((block[block.Length - 1] << 4) | 0x06);
  157. int maxBit = (8 - (bitSize - 1) % 8);
  158. int offSet = 0;
  159. if (maxBit != 8)
  160. {
  161. block[0] &= (byte) ((ushort) 0xff >> maxBit);
  162. block[0] |= (byte) ((ushort) 0x80 >> maxBit);
  163. }
  164. else
  165. {
  166. block[0] = 0x00;
  167. block[1] |= 0x80;
  168. offSet = 1;
  169. }
  170. return engine.ProcessBlock(block, offSet, block.Length - offSet);
  171. }
  172. /**
  173. * @exception InvalidCipherTextException if the decrypted block is not a valid ISO 9796 bit string
  174. */
  175. private byte[] DecodeBlock(
  176. byte[] input,
  177. int inOff,
  178. int inLen)
  179. {
  180. byte[] block = engine.ProcessBlock(input, inOff, inLen);
  181. int r = 1;
  182. int t = (bitSize + 13) / 16;
  183. BigInteger iS = new BigInteger(1, block);
  184. BigInteger iR;
  185. if (iS.Mod(Sixteen).Equals(Six))
  186. {
  187. iR = iS;
  188. }
  189. else
  190. {
  191. iR = modulus.Subtract(iS);
  192. if (!iR.Mod(Sixteen).Equals(Six))
  193. throw new InvalidCipherTextException("resulting integer iS or (modulus - iS) is not congruent to 6 mod 16");
  194. }
  195. block = iR.ToByteArrayUnsigned();
  196. if ((block[block.Length - 1] & 0x0f) != 0x6)
  197. throw new InvalidCipherTextException("invalid forcing byte in block");
  198. block[block.Length - 1] =
  199. (byte)(((ushort)(block[block.Length - 1] & 0xff) >> 4)
  200. | ((inverse[(block[block.Length - 2] & 0xff) >> 4]) << 4));
  201. block[0] = (byte)((shadows[(uint) (block[1] & 0xff) >> 4] << 4)
  202. | shadows[block[1] & 0x0f]);
  203. bool boundaryFound = false;
  204. int boundary = 0;
  205. for (int i = block.Length - 1; i >= block.Length - 2 * t; i -= 2)
  206. {
  207. int val = ((shadows[(uint) (block[i] & 0xff) >> 4] << 4)
  208. | shadows[block[i] & 0x0f]);
  209. if (((block[i - 1] ^ val) & 0xff) != 0)
  210. {
  211. if (!boundaryFound)
  212. {
  213. boundaryFound = true;
  214. r = (block[i - 1] ^ val) & 0xff;
  215. boundary = i - 1;
  216. }
  217. else
  218. {
  219. throw new InvalidCipherTextException("invalid tsums in block");
  220. }
  221. }
  222. }
  223. block[boundary] = 0;
  224. byte[] nblock = new byte[(block.Length - boundary) / 2];
  225. for (int i = 0; i < nblock.Length; i++)
  226. {
  227. nblock[i] = block[2 * i + boundary + 1];
  228. }
  229. padBits = r - 1;
  230. return nblock;
  231. }
  232. }
  233. }
  234. #endif