"Errores" en Java. Variancia de resultados.

Saludos a todos!

Bueno, tengo una variancia de texto a la hora de obtener el texto de un JTextPane.

La situacion es la siguiente,
tengo en mi codigo, la instruccion siguiente:
String cipheredText = new DES().DESDecipher(txtTextPane.getText(),txtLlave.getText());
donde los parametros del metodo DESDecipher son claro, de tipo String.

En fin, a la hora de invocar a esta instruccion se genera una variancia del valor de la variable cipheredText al resultado correcto.
txtTextPane tiene algunos simbolos raros que por lo que he visto Java no reconoce, por ejemplo
un System.out.println((char)129); //Prueben ustedes mismo
genera como resultado un simbolo ? y aqui entonces tambien me pregunto, porque hace eso
y no es solo ese simbolo, sino un rango entre los numeros 128 y 159 que generan simbolos asi porque supongo Java no los reconoce. Espero puedan ayudarme a resolver esto. De verdad lo agradeceria.

Bueno, siguiendo con la variable cipheredText
El resultado sale correcto si hago lo siguiente
String cipheredText = new DES().DESDecipher("ü♀Øø",txtLlave.getText());
"ü♀Øø" es lo mismo que contiene el JTextPane, y entonces ahi me pregunto el porque se generan resultados diferentes si al fin y al cabo resultan ser el mismo contenido.

De verdad agradeceria sus comentarios y ayuda.

Hasta pronto!

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

binario

DES (y cualquier otro algoritmo decente de encripción por bloques) maneja datos binarios. Puede encriptar texto pero también podría encriptar cualquier otra cosa. El resultado de encriptar datos con DES no es texto, son datos binarios, que por supuesto no siempre (o más bien casi nunca) son imprimibles. Esos símbolos raros son caracteres no estándar, como bien deberías saber, las letras y números y otros símbolos "normales" de texto están en el rango del 32 al 126 tanto en ASCII como en Unicode. Los caracteres 128 a 159 se representan de distintas formas en distintos encodings, que puede ser ISO-8859-1, UTF-8 o alguna otra cosa según la configuración de la JVM donde estás corriendo esto.

Normalmente para evitar todos esos problemas, se usa codificación a hexadecimal o a base 64 de los datos encriptados, cuando es necesario mostrarlos o transmitirlos como texto. De ese modo, se usan puros caracteres estándar de 7 bits, que pueden ser manejados como texto por cualquier sistema nuevo y viejo; cuando necesitas decriptar los datos (como es tu caso), tomas ese texto, lo decodificas de base64 o hexadecimal, obtienes datos ya en binario (un arreglo de bytes) y eso es lo que decriptas. El resultado puede ser texto, si lo que encriptaste originalmente era texto, o pueden ser datos binarios (por ejemplo una imagen o audio).

Cuando trabajes con encripción debes recordar que no estás manejando texto, sino bits y bytes. Esa clase de DES que tienes, debería recibir arreglos de bytes en vez de Strings, a menos que por ejemplo estés utilizando PKCS#5 para generar una llave binaria a partir de un password en texto y entonces la llave la puedes pasar como simple texto (porque si tu llave la usas a partir de un texto escrito sin hacer ninguna transformación, tu encripción será bastante débil ya que estás usando un espacio de llaves muy reducido y estás forzando a los usuarios a tener passwords de 8 caracteres porque DES necesita llaves de 64 bits).

Given the choice of dancing pigs and security, users will choose dancing pigs, every single time. - Steve Riley

Imagen de ezamudio

JCE

Como comentario adicional, Java ya incluye desde la versión 1.4 las Java Cryptography Extensions, que son toda una serie de clases para poder encriptar/decriptar datos, sin necesidad de recurrir a librerías externas. En tu caso simplemente instanciarías una subclase de Cipher, usando el método Cipher.getInstance() y le tienes que dar una cadena describiendo el algoritmo, el modo de encripción (Cipher Block Chaining o Electronic Code Book, Cipher Feedback, etc). Luego la inicializas para encriptar o decriptar, con una llave y muy probablemente un vector de inicialización (en caso que uses CFB o CBC que es lo más recomendable) y le vas pasando bloques de datos (puede ser uno por uno o todos de golpe), como arreglos de bytes. Para decriptar simplemente inicializas con Cipher.INIT_DECRYPT en vez de INIT_ENCRYPT y el resto del proceso es igual (porque es encripción simétrica).
Lo mejor de todo es que luego puedes cambiar de algoritmo simplemente modificando el Cipher.getInstance() para usar AES en vez de DES, por ejemplo (bueno y en ese caso tendrías que manejar llaves y bloques de 128 bits en vez de 64 bits, pero es algo mínimo y parametrizable).

Given the choice of dancing pigs and security, users will choose dancing pigs, every single time. - Steve Riley