2012-06-29 14 views
8

¿Qué estoy haciendo mal? Esperaba que el programa Java imprimiera "privado". Mi objetivo es tratar de escribir el método MessageEncryptor.decrypt ruby ​​en Java.Encriptar en Ruby y descifrar en Java - ¿Por qué no funciona?

cifrado Ruby (la mayoría del código fue tomada desde MessageEncryptor, pero modificado para no Mariscal), pero he extraído de modo que es más fácil ver lo que está pasando:

require 'openssl' 
require 'active_support/base64' 

@cipher = 'aes-256-cbc' 
d = OpenSSL::Cipher.new(@cipher) 
@secret = OpenSSL::PKCS5.pbkdf2_hmac_sha1("password", "some salt", 1024, d.key_len) 
cipher = OpenSSL::Cipher::Cipher.new(@cipher) 

iv = cipher.random_iv 

cipher.encrypt 
cipher.key = @secret 
cipher.iv = iv 

encrypted_data = cipher.update("private") 
encrypted_data << cipher.final 

puts [encrypted_data, iv].map {|v| ::Base64.strict_encode64(v)}.join("--") 

Qué impresa:

tzFUIVllG2FcYD7xqGPmHQ == - == UAPvdm3oN3Hog9ND9HrhEA código

Java:

package decryptruby; 

import java.security.spec.KeySpec; 
import javax.crypto.Cipher; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.PBEKeySpec; 
import javax.crypto.spec.SecretKeySpec; 
import org.apache.commons.codec.binary.Base64; 

public class DecryptRuby {  
    public static String decrypt(String encrypted, String pwd, byte[] salt) 
      throws Exception { 

     String[] parts = encrypted.split("--"); 
     if (parts.length != 2) return null; 

     byte[] encryptedData = Base64.decodeBase64(parts[0]); 
     byte[] iv = Base64.decodeBase64(parts[1]); 

     SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
     KeySpec spec = new PBEKeySpec(pwd.toCharArray(), salt, 1024, 256); 
     SecretKey tmp = factory.generateSecret(spec); 
     SecretKey aesKey = new SecretKeySpec(tmp.getEncoded(), "AES"); 


     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, aesKey, new IvParameterSpec(iv)); 

     byte[] result = cipher.doFinal(encryptedData); 
     return result.toString(); 
    } 


    public static void main(String[] args) throws Exception { 
     String encrypted = "tzFUIVllG2FcYD7xqGPmHQ==--UAPvdm3oN3Hog9ND9HrhEA=="; 

     System.out.println("Decrypted: " + decrypt(encrypted, "password", "some salt".getBytes())); 
    } 
} 

Qué impreso

descifrado: [B @ 432a0f6c

Respuesta

19

Este es el problema - o por lo menos un problema :

byte[] result = cipher.doFinal(encryptedData); 
return result.toString(); 

que está llamando toString() en una matriz de bytes. Las matrices no anulan toString(). Eso no le dará lo que desea en absoluto, como puede ver. En su lugar, tiene que escribir algo como:

return new String(result, "UTF-8"); 

... pero hay que saber qué codificación se utiliza para activar la cadena original en bytes antes del cifrado. No me queda claro, a partir del código de Ruby, qué codificación se usa, pero si puedes ser explícito al respecto (idealmente usando UTF-8) te facilitará la vida.

En resumen, sospechar este problema no tiene nada que ver con el cifrado en absoluto - que tiene mucho que ver con la conversión de texto a Bytes Ruby y luego convertir la misma secuencia de bytes vuelta a una cadena en Java.

Por supuesto, la encriptación puede estar fallando y, pero esa es una cuestión diferente.

+0

Gracias, Jon. Eso fue todo. No se puede marcar como respuesta por otros 7 minutos. – Bradford

+0

Buena captura! :-) –

Cuestiones relacionadas