¿Qué pasa con el siguiente ejemplo?
El problema es que la primera parte de la cadena descifrada no tiene sentido. Sin embargo, el resto está bien, me sale ...
Result: `£eB6O�geS��i are you? Have a nice day.
@Test
public void testEncrypt() {
try {
String s = "Hello there. How are you? Have a nice day.";
// Generate key
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
SecretKey aesKey = kgen.generateKey();
// Encrypt cipher
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);
// Encrypt
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);
cipherOutputStream.write(s.getBytes());
cipherOutputStream.flush();
cipherOutputStream.close();
byte[] encryptedBytes = outputStream.toByteArray();
// Decrypt cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);
// Decrypt
outputStream = new ByteArrayOutputStream();
ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);
CipherInputStream cipherInputStream = new CipherInputStream(inStream, decryptCipher);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buf)) >= 0) {
outputStream.write(buf, 0, bytesRead);
}
System.out.println("Result: " + new String(outputStream.toByteArray()));
}
catch (Exception ex) {
ex.printStackTrace();
}
}
java
encryption
aes
TedTrippin
fuente
fuente
Respuestas:
Muchas personas, incluyéndome a mí, enfrentan muchos problemas al hacer que esto funcione debido a que faltan información como, olvidar convertir a Base64, vectores de inicialización, juego de caracteres, etc. Así que pensé en hacer un código completamente funcional.
Espero que esto sea útil para todos: Para compilar, necesita un jar adicional de Apache Commons Codec, que está disponible aquí: http://commons.apache.org/proper/commons-codec/download_codec.cgi
fuente
System.out.println("encrypted string:" + DatatypeConverter.printBase64Binary(encrypted));
byte[] original = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted));
SecureRandom
Aquí una solución sin
Apache Commons Codec
'sBase64
:Ejemplo de uso:
Huellas dactilares:
fuente
encrypt(String)
y noencrypt(byte[] )
?. El cifrado (también el descifrado) es un proceso basado en bytes (de todos modos, AES lo es). El cifrado toma bytes como entrada y genera bytes, al igual que el descifrado (ejemplo: elCipher
objeto lo hace). Ahora, un caso de uso particular puede ser tener bytes encriptados provenientes de una Cadena, o ser enviados como una Cadena (adjunto MIME base64 para un Correo ...), pero ese es un problema de codificación de bytes, para los cuales existen cientos de soluciones, totalmente ajenas a AES / cifrado.Strings
ya que eso es básicamente con lo que trabajo el 95% del tiempo y terminas convirtiendo de todos modos.Me parece que no está tratando correctamente con su vector de inicialización (IV). Ha pasado mucho tiempo desde la última vez que leí sobre AES, IV y encadenamiento de bloques, pero su línea
no parece estar bien. En el caso de AES, puede pensar en el vector de inicialización como el "estado inicial" de una instancia de cifrado, y este estado es un poco de información que no puede obtener de su clave, sino del cálculo real del cifrado de cifrado. (Se podría argumentar que si el IV pudiera extraerse de la clave, entonces no sería útil, ya que la clave ya se le dio a la instancia de cifrado durante su fase de inicio).
Por lo tanto, debe obtener el IV como un byte [] de la instancia de cifrado al final de su cifrado
y usted debe inicializar su
Cipher
enDECRYPT_MODE
este byte []:Entonces, su descifrado debería estar bien. Espero que esto ayude.
fuente
El IV que está utilizando para el descifrado es incorrecto. Reemplazar este código
Con este código
Y eso debería resolver tu problema.
A continuación se incluye un ejemplo de una clase AES simple en Java. No recomiendo usar esta clase en entornos de producción, ya que es posible que no tenga en cuenta todas las necesidades específicas de su aplicación.
Tenga en cuenta que AES no tiene nada que ver con la codificación, por lo que elegí manejarlo por separado y sin la necesidad de bibliotecas de terceros.
fuente
"/NoPadding"
. CTR es un modo que convierte AES en un cifrado de flujo, y un cifrado de flujo opera en bytes en lugar de bloques.En esta respuesta, elijo abordar el tema principal del "Ejemplo simple de cifrado / descifrado AES de Java" y no la pregunta de depuración específica porque creo que esto beneficiará a la mayoría de los lectores.
Este es un resumen simple de mi publicación de blog sobre el cifrado AES en Java por lo que recomiendo leerlo antes de implementar cualquier cosa. Sin embargo, seguiré brindando un ejemplo simple para usar y dar algunos consejos sobre qué tener en cuenta.
En este ejemplo, elegiré utilizar cifrado autenticado con el modo Galois / Counter o el modo GCM . La razón es que, en la mayoría de los casos, desea integridad y autenticidad en combinación con confidencialidad (lea más en el blog ).
Tutorial de cifrado / descifrado AES-GCM
Estos son los pasos necesarios para cifrar / descifrar con AES-GCM con Java Cryptography Architecture (JCA) . No mezclar con otros ejemplos , ya que las diferencias sutiles pueden hacer que su código sea completamente inseguro.
1. Crear clave
Como depende de su caso de uso, asumiré el caso más simple: una clave secreta aleatoria.
Importante:
SecureRandom
2. Cree el vector de inicialización
Se utiliza un vector de inicialización (IV) para que la misma clave secreta cree diferentes textos cifrados .
Importante:
SecureRandom
3. Cifrar con IV y Key
Importante:
CipherInputStream
al cifrar grandes cantidades de datoscipher.updateAAD(associatedData);
Más aquí.3. Serializar en un solo mensaje
Solo agregue IV y texto cifrado. Como se indicó anteriormente, el IV no tiene por qué ser secreto.
Opcionalmente, codifique con Base64 si necesita una representación de cadena. Utilice la implementación incorporada de Android o Java 8 (no use Apache Commons Codec, es una implementación terrible). La codificación se utiliza para "convertir" matrices de bytes en una representación de cadena para que sea ASCII seguro, por ejemplo:
4. Preparar el descifrado: deserializar
Si ha codificado el mensaje, primero decodifíquelo en una matriz de bytes:
Importante:
5. Descifrar
Inicialice el cifrado y establezca los mismos parámetros que con el cifrado:
Importante:
cipher.updateAAD(associatedData);
si los agregó durante el cifrado.Se puede encontrar un fragmento de código funcional en esta esencia.
Tenga en cuenta que las implementaciones más recientes de Android (SDK 21+) y Java (7+) deben tener AES-GCM. Es posible que las versiones anteriores no lo tengan. Sigo eligiendo este modo, ya que es más fácil de implementar además de ser más eficiente en comparación con un modo similar de Encrypt-then-Mac (por ejemplo, con AES-CBC + HMAC ). Consulte este artículo sobre cómo implementar AES-CBC con HMAC .
fuente
this is true for CBC mode but not for GCM
¿Te refieres a la parte completa, o solo que no necesita ser impredecible?Versión ejecutable del editor en línea: -
fuente
A menudo es una buena idea confiar en la solución estándar proporcionada por la biblioteca:
Esto imprime "Texto para codificar".
La solución se basa en la Guía de referencia de la arquitectura de criptografía de Java y la respuesta https://stackoverflow.com/a/20591539/146745 .
fuente
Esta es una mejora con respecto a la respuesta aceptada.
Cambios:
(1) Usar IV aleatorio y anteponerlo al texto cifrado
(2) Usar SHA-256 para generar una clave a partir de una frase de contraseña
(3) Sin dependencia de Apache Commons
fuente
Otra solución usando java.util.Base64 con Spring Boot
Clase de cifrador
EncryptorController (clase)
application.properties
Ejemplo
http: // localhost: 8082 / cipher / encrypt / jmendoza
2h41HH8Shzc4BRU3hVDOXA ==
http: // localhost: 8082 / cipher / decrypt / 2h41HH8Shzc4BRU3hVDOXA ==
jmendoza
fuente
Versión optimizada de la respuesta aceptada.
sin bibliotecas de terceros
incluye IV en el mensaje cifrado (puede ser público)
la contraseña puede tener cualquier longitud
Código:
Uso:
Salida de ejemplo:
fuente
e.printStackTrace()
en el llamado código optimizado.