java php encryption interop blowfish

¿Por qué la salida de Blowfish en Java y PHP difiere solo en 2 caracteres?



encryption interop (3)

Tu código me parece correcto.

Parece que tiene un espacio en blanco al final en la entrada de uno de estos programas, y es solo uno. Te diré por qué:

Cada uno de estos bloques de 4 char representa 3 caracteres en la cadena cifrada. La parte diferente (JA y D8 en el 7 ° bloque) en realidad provienen de un único personaje diferente.

wTHz xfxL HdMm / JMF noh0 hciS / JAD vFFg

wTHz xfxL HdMm / JMF noh0 hciS / D8D vFFg

Si lo hago bien, su dirección de correo electrónico tiene 19 caracteres. El 20º carácter en una de sus cadenas de entrada es un espacio en blanco.

Tengo un script de cifrado blowfish en PHP y JAVA, viceversa, que funcionaba bien hasta hoy cuando me encontré con un problema.

El mismo contenido se cifra de manera diferente en Java vs PHP con solo 2 caracteres, lo que es realmente extraño.

PHP

wTHzxfxLHdMm/JMFnoh0hciS/JADvFFg

Java

wTHzxfxLHdMm/JMFnoh0hciS/D8DvFFg -------------------------^^

Como ve, esas dos posiciones no coinciden. Lamentablemente, el valor es una dirección de correo electrónico real y no puedo compartirlo. Además, no pude reproducir el problema con otros pocos valores que probé. Intenté cambiar las clases de codificación de Base64 en Java, y ninguna de las dos me ayudó.

El código fuente para PHP está aquí , y para Java está aquí .

¿Qué podría hacer para resolver este problema?


Pregunta: ¿Has probado la biblioteca de descifrado de PHP asociada para descifrar el texto encriptado generado por PHP? ¿Has probado la biblioteca de descifrado JAVA asociada para descifrar el texto cifrado JAVA?

Si ambos producen salidas diferentes, entonces uno DEBE fallar el descifrado.

¿Es ese uno PHP o Java?

Sea cual sea, intentaré duplicar otra falla con una cadena que se pueda compartir públicamente ... dar esa cadena como una prueba unitaria al desarrollador o desarrolladores que crearon el código de cifrado / descifrado en el idioma que la ronda el cifrado / descifrado de viaje falla en.

Entonces ... espera a que lo arreglen.

No estoy seguro de que haya soluciones más rápidas, excepto tal vez cambiar los proveedores de bibliotecas de cifrado / descifrado ... o hacer su propia versión ...


Echemos un vistazo a su código Java:

String c = new String(Test.encrypt((new String("thevalue")).getBytes(), (new String("mykey")).getBytes())); ... System.out.println("Base64 encoded String:" + new sun.misc.BASE64Encoder().encode(c.getBytes()));

Lo que estás haciendo aquí es:

  1. Convierta la cadena de texto sin formato a bytes, utilizando la codificación predeterminada del sistema
  2. convertir la clave en bytes, utilizando la codificación predeterminada del sistema
  3. cifra los bytes
  4. Convierta los bytes cifrados a una cadena utilizando la codificación predeterminada del sistema.
  5. convertir la cadena encriptada a bytes , usando la codificación predeterminada del sistema
  6. codificar estos bytes cifrados utilizando Base64.

El problema está en el paso 4. Supone que una matriz de bytes arbitraria representa una cadena en la codificación predeterminada de su sistema, y ​​la codificación de esta cadena devuelve el mismo byte []. Esto es válido para algunas codificaciones (la serie ISO-8859 , por ejemplo), pero no para otras. En Java, cuando algún byte (o secuencia de bytes) no es representable en la codificación dada, será reemplazado por algún otro carácter, que más tarde para la reconversión será mapeado al byte 63 ( ? ASCII ? ). En realidad, la documentación incluso dice:

El comportamiento de este constructor cuando los bytes dados no son válidos en el juego de caracteres predeterminado no está especificado.

En su caso, no hay ninguna razón para hacer esto: simplemente use los bytes que su método de encrypt genera directamente para convertirlos a Base64.

byte[] encrypted = Test.encrypt("thevalue".getBytes(), "mykey".getBytes()); System.out.println("Base64 encoded String:"+ new sun.misc.BASE64Encoder().encode(encrypted));

(También tenga en cuenta que eliminé aquí las new String("...") llamadas al constructor new String("...") superfluas, aunque esto no se relaciona con su problema).

El punto a recordar: nunca convierta un byte arbitrario [], que no vino de codificar una cadena, a una cadena. La salida de un algoritmo de encriptación (y la mayoría de los otros algoritmos criptográficos, excepto el descifrado) ciertamente pertenece a la categoría de datos que no debe convertirse a una cadena .

Y nunca use la codificación predeterminada del sistema, si desea programas portátiles.