PageRenderTime 232ms CodeModel.GetById 46ms RepoModel.GetById 1ms app.codeStats 0ms

/afirma-crypto-cipher/src/main/java/es/gob/afirma/ciphers/jce/AOSunJCECipher.java

https://gitlab.com/edgardo001/clienteafirma
Java | 270 lines | 202 code | 33 blank | 35 comment | 26 complexity | 5ea41dad848d75b810d7413a7366a1da MD5 | raw file
  1. /* Copyright (C) 2011 [Gobierno de Espana]
  2. * This file is part of "Cliente @Firma".
  3. * "Cliente @Firma" is free software; you can redistribute it and/or modify it under the terms of:
  4. * - the GNU General Public License as published by the Free Software Foundation;
  5. * either version 2 of the License, or (at your option) any later version.
  6. * - or The European Software License; either version 1.1 or (at your option) any later version.
  7. * Date: 11/01/11
  8. * You may contact the copyright holder at: soporte.afirma5@mpt.es
  9. */
  10. package es.gob.afirma.ciphers.jce;
  11. import java.security.InvalidKeyException;
  12. import java.security.Key;
  13. import java.security.KeyException;
  14. import java.security.spec.AlgorithmParameterSpec;
  15. import javax.crypto.BadPaddingException;
  16. import javax.crypto.Cipher;
  17. import javax.crypto.KeyGenerator;
  18. import javax.crypto.SecretKeyFactory;
  19. import javax.crypto.spec.IvParameterSpec;
  20. import javax.crypto.spec.PBEKeySpec;
  21. import javax.crypto.spec.PBEParameterSpec;
  22. import javax.crypto.spec.SecretKeySpec;
  23. import es.gob.afirma.core.AOException;
  24. import es.gob.afirma.core.ciphers.AOCipher;
  25. import es.gob.afirma.core.ciphers.AOCipherConfig;
  26. import es.gob.afirma.core.ciphers.CipherConstants.AOCipherAlgorithm;
  27. import es.gob.afirma.core.ciphers.CipherConstants.AOCipherBlockMode;
  28. import es.gob.afirma.core.ciphers.CipherConstants.AOCipherPadding;
  29. /** Cifrador seg&uacute;n las capacidades del proveedor JCE (<i>Java Cryptography
  30. * Extension</i>). */
  31. public final class AOSunJCECipher implements AOCipher {
  32. /** Proveedor Java que da soporte a los algoritmos aqui descritos. */
  33. private static final String PROVIDER = "SunJCE"; //$NON-NLS-1$
  34. private static final byte[] SALT = {
  35. (byte) 0xA2, (byte) 0x35, (byte) 0xDC, (byte) 0xA4, (byte) 0x11, (byte) 0x7C, (byte) 0x99, (byte) 0x4B
  36. };
  37. private static final int ITERATION_COUNT = 9;
  38. /** Vector de inicializacion de 8 bytes. Un vector de inicializaci&oacute;n
  39. * de 8 bytes es necesario para el uso de los algoritmos DES y DESede. */
  40. private static final byte[] IV_8 = {
  41. (byte) 0xC6, (byte) 0xBA, (byte) 0xDE, (byte) 0xA4, (byte) 0x76, (byte) 0x43, (byte) 0x32, (byte) 0x6B
  42. };
  43. /** Vector de inicializacion de 16 bytes. Un vector de inicializaci&oacute;n
  44. * de 16 bytes es necesario para el uso de los algoritmos DES y DESede. */
  45. private static final byte[] IV_16 = {
  46. (byte) 0xB2, (byte) 0xBA, (byte) 0xDE, (byte) 0xA4, (byte) 0x41, (byte) 0x7F, (byte) 0x97, (byte) 0x4B,
  47. (byte) 0xAC, (byte) 0x63, (byte) 0xAC, (byte) 0xAA, (byte) 0x76, (byte) 0x73, (byte) 0x12, (byte) 0x6B
  48. };
  49. /** Configuraciones de cifrado soportadas. */
  50. private static final AOCipherConfig[] SUPPORTED_CONFIGS = new AOCipherConfig[] {
  51. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.ECB, AOCipherPadding.PKCS5PADDING),
  52. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.ECB, AOCipherPadding.ISO10126PADDING),
  53. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.CBC, AOCipherPadding.PKCS5PADDING),
  54. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.CBC, AOCipherPadding.ISO10126PADDING),
  55. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.PCBC, AOCipherPadding.PKCS5PADDING),
  56. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.PCBC, AOCipherPadding.ISO10126PADDING),
  57. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.CTR, AOCipherPadding.NOPADDING),
  58. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.CTR, AOCipherPadding.PKCS5PADDING),
  59. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.CFB, AOCipherPadding.PKCS5PADDING),
  60. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.CFB, AOCipherPadding.ISO10126PADDING),
  61. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.OFB, AOCipherPadding.PKCS5PADDING),
  62. new AOCipherConfig(AOCipherAlgorithm.AES, AOCipherBlockMode.OFB, AOCipherPadding.ISO10126PADDING),
  63. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.ECB, AOCipherPadding.PKCS5PADDING),
  64. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.ECB, AOCipherPadding.ISO10126PADDING),
  65. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.CBC, AOCipherPadding.PKCS5PADDING),
  66. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.CBC, AOCipherPadding.ISO10126PADDING),
  67. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.PCBC, AOCipherPadding.PKCS5PADDING),
  68. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.PCBC, AOCipherPadding.ISO10126PADDING),
  69. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.CTR, AOCipherPadding.NOPADDING),
  70. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.CTR, AOCipherPadding.PKCS5PADDING),
  71. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.CFB, AOCipherPadding.PKCS5PADDING),
  72. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.CFB, AOCipherPadding.ISO10126PADDING),
  73. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.OFB, AOCipherPadding.PKCS5PADDING),
  74. new AOCipherConfig(AOCipherAlgorithm.BLOWFISH, AOCipherBlockMode.OFB, AOCipherPadding.ISO10126PADDING),
  75. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.ECB, AOCipherPadding.PKCS5PADDING),
  76. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.ECB, AOCipherPadding.ISO10126PADDING),
  77. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.CBC, AOCipherPadding.PKCS5PADDING),
  78. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.CBC, AOCipherPadding.ISO10126PADDING),
  79. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.PCBC, AOCipherPadding.PKCS5PADDING),
  80. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.PCBC, AOCipherPadding.ISO10126PADDING),
  81. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.CTR, AOCipherPadding.NOPADDING),
  82. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.CTR, AOCipherPadding.PKCS5PADDING),
  83. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.CFB, AOCipherPadding.PKCS5PADDING),
  84. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.CFB, AOCipherPadding.ISO10126PADDING),
  85. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.OFB, AOCipherPadding.PKCS5PADDING),
  86. new AOCipherConfig(AOCipherAlgorithm.DES, AOCipherBlockMode.OFB, AOCipherPadding.ISO10126PADDING),
  87. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.ECB, AOCipherPadding.PKCS5PADDING),
  88. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.ECB, AOCipherPadding.ISO10126PADDING),
  89. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.CBC, AOCipherPadding.PKCS5PADDING),
  90. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.CBC, AOCipherPadding.ISO10126PADDING),
  91. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.PCBC, AOCipherPadding.PKCS5PADDING),
  92. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.PCBC, AOCipherPadding.ISO10126PADDING),
  93. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.CTR, AOCipherPadding.NOPADDING),
  94. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.CTR, AOCipherPadding.PKCS5PADDING),
  95. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.CFB, AOCipherPadding.PKCS5PADDING),
  96. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.CFB, AOCipherPadding.ISO10126PADDING),
  97. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.OFB, AOCipherPadding.PKCS5PADDING),
  98. new AOCipherConfig(AOCipherAlgorithm.TRIPLEDES, AOCipherBlockMode.OFB, AOCipherPadding.ISO10126PADDING),
  99. new AOCipherConfig(AOCipherAlgorithm.PBEWITHSHA1ANDDESEDE, AOCipherBlockMode.CBC, AOCipherPadding.PKCS5PADDING),
  100. new AOCipherConfig(AOCipherAlgorithm.PBEWITHSHA1ANDRC2_40, AOCipherBlockMode.CBC, AOCipherPadding.PKCS5PADDING),
  101. new AOCipherConfig(AOCipherAlgorithm.PBEWITHMD5ANDDES, AOCipherBlockMode.CBC, AOCipherPadding.PKCS5PADDING)
  102. };
  103. /** {@inheritDoc} */
  104. @Override
  105. public AOCipherConfig[] getSupportedConfigs() {
  106. return SUPPORTED_CONFIGS.clone();
  107. }
  108. /** {@inheritDoc} */
  109. @Override
  110. public byte[] cipher(final byte[] data, final AOCipherConfig algorithmConfig, final Key cipherKey) throws AOException, KeyException {
  111. if (data == null || algorithmConfig == null || cipherKey == null || data.length == 0) {
  112. throw new AOException("Los parametros de la funcion de cifrado no pueden ser nulos o vacios"); //$NON-NLS-1$
  113. }
  114. // Tomamos el cipher para el algoritmo indicado
  115. final Cipher cipher;
  116. try {
  117. cipher = Cipher.getInstance(algorithmConfig.toString(), PROVIDER);
  118. }
  119. catch (final Exception e) {
  120. throw new AOException("Error al obtener el cifrador: " + e, e); //$NON-NLS-1$
  121. }
  122. // Inicializamos el cipher
  123. try {
  124. cipher.init(Cipher.ENCRYPT_MODE, cipherKey, AOSunJCECipher.getParams(algorithmConfig));
  125. }
  126. catch (final InvalidKeyException e) {
  127. throw new KeyException("La clave de cifrado introducida no es valida para el algoritmo '" + //$NON-NLS-1$
  128. algorithmConfig.getAlgorithm().getName() + "'", e); //$NON-NLS-1$
  129. }
  130. catch (final Exception e) {
  131. throw new AOException("Error al inicializar el cifrador", e); //$NON-NLS-1$
  132. }
  133. // Realizamos el cifrado
  134. try {
  135. return cipher.doFinal(data);
  136. }
  137. catch (final Exception e) {
  138. throw new AOException("Error cifrando los datos", e); //$NON-NLS-1$
  139. }
  140. }
  141. /** {@inheritDoc} */
  142. @Override
  143. public byte[] decipher(final byte[] data, final AOCipherConfig algorithmConfig, final Key decipherKey) throws AOException, InvalidKeyException {
  144. if (data == null || algorithmConfig == null || decipherKey == null) {
  145. throw new AOException("Los parametros de la funcion de descifrado no pueden ser nulos"); //$NON-NLS-1$
  146. }
  147. // Tomamos el cipher para el algoritmo indicado
  148. final Cipher cipher;
  149. try {
  150. cipher = Cipher.getInstance(algorithmConfig.toString(), PROVIDER);
  151. }
  152. catch (final Exception e) {
  153. throw new AOException("Error obteniendo el descifrador", e); //$NON-NLS-1$
  154. }
  155. // Inicializamos el cipher
  156. try {
  157. cipher.init(Cipher.DECRYPT_MODE, decipherKey, AOSunJCECipher.getParams(algorithmConfig));
  158. }
  159. catch (final InvalidKeyException e) {
  160. throw new InvalidKeyException("La clave de descifrado introducida no es valida para el algoritmo '" //$NON-NLS-1$
  161. + algorithmConfig.getAlgorithm().getName() + "'", //$NON-NLS-1$
  162. e);
  163. }
  164. catch (final Exception e) {
  165. throw new AOException("Error al inicializar el descifrador", e); //$NON-NLS-1$
  166. }
  167. // Realizamos el descifrado
  168. try {
  169. return cipher.doFinal(data);
  170. }
  171. catch(final BadPaddingException e) {
  172. throw new InvalidKeyException("La clave de descifrado introducida no es correcta", e); //$NON-NLS-1$
  173. }
  174. catch (final Exception e) {
  175. throw new AOException("Error descifrando los datos", e); //$NON-NLS-1$
  176. }
  177. }
  178. /** {@inheritDoc} */
  179. @Override
  180. public Key decodeKey(final byte[] keyEncoded, final AOCipherConfig algorithmConfig, final Object[] params) throws KeyException {
  181. if (keyEncoded == null || keyEncoded.length < 1) {
  182. throw new IllegalArgumentException("La clave a descodificar no puede ser nula ni vacia"); //$NON-NLS-1$
  183. }
  184. if (algorithmConfig == null) {
  185. throw new IllegalArgumentException("La configuracion de cifrado no puede ser nula"); //$NON-NLS-1$
  186. }
  187. try {
  188. return new SecretKeySpec(keyEncoded, algorithmConfig.getAlgorithm().getName());
  189. }
  190. catch (final Exception e) {
  191. throw new KeyException("Error creando la clave secreta", e); //$NON-NLS-1$
  192. }
  193. }
  194. /** {@inheritDoc} */
  195. @Override
  196. public Key decodePassphrase(final char[] passphrase, final AOCipherConfig algorithmConfig, final Object[] params) throws AOException {
  197. if (passphrase == null || passphrase.length < 1) {
  198. throw new IllegalArgumentException("La contrasena para la generacion de la clave no puede ser nula ni vacia"); //$NON-NLS-1$
  199. }
  200. if (algorithmConfig == null) {
  201. throw new IllegalArgumentException("La configuracion de cifrado no puede ser nula"); //$NON-NLS-1$
  202. }
  203. try {
  204. return SecretKeyFactory.getInstance(
  205. algorithmConfig.getAlgorithm().getName(), PROVIDER).generateSecret(
  206. new PBEKeySpec(passphrase, SALT, ITERATION_COUNT));
  207. }
  208. catch (final Exception e) {
  209. throw new AOException("Error generando la clave secreta", e); //$NON-NLS-1$
  210. }
  211. }
  212. /** {@inheritDoc} */
  213. @Override
  214. public Key generateKey(final AOCipherConfig algorithmConfig) throws AOException {
  215. try {
  216. return KeyGenerator.getInstance(algorithmConfig.getAlgorithm().getName(), PROVIDER).generateKey();
  217. }
  218. catch (final Exception e) {
  219. throw new AOException("No se pudo generar una clave compatible para la configuracion '" + algorithmConfig + "': " + e , e); //$NON-NLS-1$ //$NON-NLS-2$
  220. }
  221. }
  222. /** Genera los par&aacute;metros necesarios para poder operar con una
  223. * configuracion concreta de cifrado. Si no es necesario ning&uacute;n
  224. * par&aacute;metro especial, devolvemos <code>null</code>.
  225. * @param algorithmConfig
  226. * Configuracion de cifrado que debemos parametrizar.
  227. * @return Par&aacute;metros para operar. */
  228. private static AlgorithmParameterSpec getParams(final AOCipherConfig algorithmConfig) {
  229. if (algorithmConfig.getAlgorithm().supportsPassword()) {
  230. return new PBEParameterSpec(SALT, ITERATION_COUNT);
  231. }
  232. if (!algorithmConfig.getBlockMode().equals(AOCipherBlockMode.ECB)) {
  233. return new IvParameterSpec(algorithmConfig.getAlgorithm().equals(AOCipherAlgorithm.AES) ? IV_16 : IV_8);
  234. }
  235. return null;
  236. }
  237. }