PageRenderTime 25ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/java/com/caucho/quercus/lib/mcrypt/Mcrypt.java

https://github.com/moriyoshi/quercus-gae
Java | 343 lines | 221 code | 48 blank | 74 comment | 64 complexity | a99bfa42c64e354d6260f157a8e28980 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
  3. *
  4. * This file is part of Resin(R) Open Source
  5. *
  6. * Each copy or derived work must preserve the copyright notice and this
  7. * notice unmodified.
  8. *
  9. * Resin Open Source is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * Resin Open Source is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
  17. * of NON-INFRINGEMENT. See the GNU General Public License for more
  18. * details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with Resin Open Source; if not, write to the
  22. *
  23. * Free Software Foundation, Inc.
  24. * 59 Temple Place, Suite 330
  25. * Boston, MA 02111-1307 USA
  26. *
  27. * @author Scott Ferguson
  28. */
  29. package com.caucho.quercus.lib.mcrypt;
  30. import com.caucho.quercus.QuercusRuntimeException;
  31. import com.caucho.quercus.env.ArrayValue;
  32. import com.caucho.quercus.env.ArrayValueImpl;
  33. import com.caucho.quercus.env.Env;
  34. import com.caucho.quercus.env.Value;
  35. import com.caucho.util.L10N;
  36. import javax.crypto.Cipher;
  37. import javax.crypto.spec.IvParameterSpec;
  38. import javax.crypto.spec.SecretKeySpec;
  39. import java.security.Key;
  40. /**
  41. * Encryption class
  42. */
  43. public class Mcrypt {
  44. private static final L10N L = new L10N(Mcrypt.class);
  45. private final String _algorithm;
  46. private final String _mode;
  47. private final Cipher _cipher;
  48. private Key _key;
  49. private IvParameterSpec _iv;
  50. Mcrypt(Env env, String algorithm, String mode)
  51. throws Exception
  52. {
  53. _algorithm = algorithm;
  54. _mode = mode.toUpperCase();
  55. String transformation = getTransformation(algorithm, mode);
  56. if (transformation == null)
  57. throw new QuercusRuntimeException(L.l("'{0}' is an unknown algorithm",
  58. algorithm));
  59. _cipher = Cipher.getInstance(transformation);
  60. }
  61. /**
  62. * Uninitialize data.
  63. */
  64. public boolean deinit()
  65. {
  66. return false;
  67. }
  68. /**
  69. * Encrypts data.
  70. */
  71. public byte []decrypt(byte []data)
  72. {
  73. try {
  74. _cipher.init(Cipher.DECRYPT_MODE, _key, _iv);
  75. _cipher.getBlockSize();
  76. return _cipher.doFinal(data);
  77. } catch (Exception e) {
  78. throw new RuntimeException(e);
  79. }
  80. }
  81. /**
  82. * Encrypts data.
  83. */
  84. public byte []encrypt(byte []data)
  85. {
  86. try {
  87. _cipher.init(Cipher.ENCRYPT_MODE, _key, _iv);
  88. if (isPadded())
  89. data = pad(data);
  90. return _cipher.doFinal(data);
  91. } catch (Exception e) {
  92. throw new RuntimeException(e);
  93. }
  94. }
  95. /**
  96. * Returns the block size.
  97. */
  98. public int get_block_size()
  99. {
  100. return _cipher.getBlockSize();
  101. }
  102. /**
  103. * Returns the initialization vector size.
  104. */
  105. public String get_algorithms_name()
  106. {
  107. return _algorithm;
  108. }
  109. /**
  110. * Returns the initialization vector size.
  111. */
  112. public int get_iv_size()
  113. {
  114. if (_mode.equals("OFB"))
  115. return _cipher.getBlockSize();
  116. else if (_mode.equals("CFB"))
  117. return _cipher.getBlockSize();
  118. else if (_mode.equals("CBC"))
  119. return _cipher.getBlockSize();
  120. else if (_mode.equals("ECB"))
  121. return _cipher.getBlockSize();
  122. else
  123. return 0;
  124. }
  125. /**
  126. * Returns the supported key sizes
  127. */
  128. public Value get_supported_key_sizes()
  129. {
  130. ArrayValue value = new ArrayValueImpl();
  131. if (McryptModule.MCRYPT_RIJNDAEL_128.equals(_algorithm)) {
  132. value.put(128 / 8);
  133. }
  134. else if (McryptModule.MCRYPT_RIJNDAEL_192.equals(_algorithm)) {
  135. value.put(128 / 8);
  136. value.put(192 / 8);
  137. }
  138. else if (McryptModule.MCRYPT_RIJNDAEL_256.equals(_algorithm)) {
  139. value.put(128 / 8);
  140. value.put(192 / 8);
  141. value.put(256 / 8);
  142. }
  143. else if (McryptModule.MCRYPT_3DES.equals(_algorithm)) {
  144. value.put(24);
  145. }
  146. else if (McryptModule.MCRYPT_DES.equals(_algorithm)) {
  147. value.put(8);
  148. }
  149. return value;
  150. }
  151. /**
  152. * Returns the key size in bytes.
  153. */
  154. public int get_key_size()
  155. {
  156. if (McryptModule.MCRYPT_RIJNDAEL_128.equals(_algorithm))
  157. return 128 / 8;
  158. else if (McryptModule.MCRYPT_RIJNDAEL_192.equals(_algorithm))
  159. return 192 / 8;
  160. else if (McryptModule.MCRYPT_RIJNDAEL_256.equals(_algorithm))
  161. return 256 / 8;
  162. else if (McryptModule.MCRYPT_3DES.equals(_algorithm))
  163. return 24;
  164. else if (McryptModule.MCRYPT_BLOWFISH.equals(_algorithm))
  165. return 56;
  166. else
  167. return get_block_size();
  168. }
  169. private boolean isPadKey()
  170. {
  171. if (McryptModule.MCRYPT_BLOWFISH.equals(_algorithm))
  172. return false;
  173. else
  174. return true;
  175. }
  176. /**
  177. * Returns the initialization vector size.
  178. */
  179. public String get_modes_name()
  180. {
  181. return _mode;
  182. }
  183. /**
  184. * Initialize the crypt.
  185. */
  186. public int init(byte []keyBytesArg, byte []iv)
  187. {
  188. byte []keyBytes;
  189. if (isPadKey()) {
  190. keyBytes = new byte[get_key_size()];
  191. int length = Math.min(keyBytesArg.length, keyBytes.length);
  192. System.arraycopy(keyBytesArg, 0, keyBytes, 0, length);
  193. }
  194. else
  195. keyBytes = keyBytesArg;
  196. _key = new SecretKeySpec(keyBytes, getAlgorithm(_algorithm));
  197. if (iv == null)
  198. _iv = null;
  199. else if (_mode.equals("CBC") || _mode.equals("CFB") || _mode.equals("OFB"))
  200. _iv = new IvParameterSpec(iv);
  201. else
  202. _iv = null;
  203. return 0;
  204. }
  205. /**
  206. * Returns true for block algorithms
  207. */
  208. public boolean is_block_algorithm()
  209. {
  210. if (_algorithm.equals(McryptModule.MCRYPT_BLOWFISH))
  211. return false;
  212. else
  213. return true;
  214. }
  215. /**
  216. * Returns true for block algorithms
  217. */
  218. public boolean is_block_algorithm_mode()
  219. {
  220. return _mode.equals("CBC") || _mode.equals("CFB") || _mode.equals("OFB");
  221. }
  222. /**
  223. * Returns true for block algorithms
  224. */
  225. public boolean is_block_mode()
  226. {
  227. return _mode.equals("CBC") || _mode.equals("ECB");
  228. }
  229. private byte []pad(byte []data)
  230. {
  231. int blockSize = get_block_size();
  232. int len = data.length;
  233. int offset = len % blockSize;
  234. if (offset == 0)
  235. return data;
  236. else {
  237. byte []pad = new byte[len + blockSize - offset];
  238. System.arraycopy(data, 0, pad, 0, data.length);
  239. return pad;
  240. }
  241. }
  242. private boolean isPadded()
  243. {
  244. return (McryptModule.MCRYPT_DES.equals(_algorithm)
  245. || McryptModule.MCRYPT_3DES.equals(_algorithm)
  246. || McryptModule.MCRYPT_RIJNDAEL_128.equals(_algorithm)
  247. || McryptModule.MCRYPT_RIJNDAEL_192.equals(_algorithm)
  248. || McryptModule.MCRYPT_RIJNDAEL_256.equals(_algorithm));
  249. }
  250. /**
  251. * Closes the mcrypt.
  252. */
  253. public void close()
  254. {
  255. }
  256. private static String getTransformation(String algorithm, String mode)
  257. throws Exception
  258. {
  259. mode = mode.toUpperCase();
  260. if (McryptModule.MCRYPT_RIJNDAEL_128.equals(algorithm))
  261. return "AES/" + mode + "/NoPadding";
  262. else if (McryptModule.MCRYPT_RIJNDAEL_192.equals(algorithm))
  263. return "AES/" + mode + "192/NoPadding";
  264. else if (McryptModule.MCRYPT_RIJNDAEL_256.equals(algorithm))
  265. return "AES/" + mode + "256/NoPadding";
  266. else if (McryptModule.MCRYPT_DES.equals(algorithm))
  267. return "DES/" + mode + "/NoPadding";
  268. else if (McryptModule.MCRYPT_3DES.equals(algorithm))
  269. return "DESede/" + mode + "/NoPadding";
  270. else if (McryptModule.MCRYPT_BLOWFISH.equals(algorithm)) {
  271. // php/1q0t, #2561
  272. return "Blowfish/" + mode + "/PKCS5Padding";
  273. }
  274. else if (McryptModule.MCRYPT_ARCFOUR.equals(algorithm)
  275. || McryptModule.MCRYPT_RC4.equals(algorithm))
  276. return "ARCFOUR/" + mode + "/NoPadding";
  277. else
  278. return algorithm + '/' + mode + "/NoPadding";
  279. }
  280. private static String getAlgorithm(String algorithm)
  281. {
  282. if (McryptModule.MCRYPT_RIJNDAEL_128.equals(algorithm) ||
  283. McryptModule.MCRYPT_RIJNDAEL_192.equals(algorithm) ||
  284. McryptModule.MCRYPT_RIJNDAEL_256.equals(algorithm))
  285. return "AES";
  286. else if (McryptModule.MCRYPT_3DES.equals(algorithm))
  287. return "DESede";
  288. else
  289. return algorithm;
  290. }
  291. public String toString()
  292. {
  293. return "Mcrypt[" + _algorithm + ", " + _mode + "]";
  294. }
  295. }