2012-06-14 39 views
6

estoy tratando de puerto el siguiente código Java a un equivalente C#:Puerto RSA código Java cifrado en C#

public static String encrypt(String value, String key) throws InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { 
    byte[] bytes = value.getBytes(Charset.forName("UTF-8")); 
    X509EncodedKeySpec x509 = new X509EncodedKeySpec(DatatypeConverter.parseBase64Binary(key)); 
    KeyFactory factory = KeyFactory.getInstance("RSA"); 
    PublicKey publicKey = factory.generatePublic(x509); 
    Cipher cipher = Cipher.getInstance("RSA"); 
    cipher.init(Cipher.ENCRYPT_MODE, publicKey); 
    bytes = cipher.doFinal(bytes); 
    return DatatypeConverter.printBase64Binary(bytes); 
} 

Hasta ahora he conseguido escribir lo siguiente en C#, utilizando la biblioteca BouncyCastle para .NET :

public static string Encrypt(string value, string key) 
    { 
     var bytes = Encoding.UTF8.GetBytes(value); 
     var publicKeyBytes = Convert.FromBase64String(key); 
     var asymmetricKeyParameter = PublicKeyFactory.CreateKey(publicKeyBytes); 
     var rsaKeyParameters = (RsaKeyParameters) asymmetricKeyParameter; 
     var cipher = CipherUtilities.GetCipher("RSA"); 
     cipher.Init(true, rsaKeyParameters); 
     var processBlock = cipher.DoFinal(bytes); 
     return Convert.ToBase64String(processBlock); 
    } 

Sin embargo, los dos métodos producen resultados diferentes aunque se invoquen con los mismos parámetros. Para propósitos de prueba, estoy usando la siguiente clave pública RSA:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLCZahTj/oz8mL6xsIfnX399Gt6bh8rDHx2ItTMjUhQrE/9kGznP5PVP19vFkQjHhcBBJ0Xi1C1wPWMKMfBsnCPwKTF/g4yga6yw26awEy4rvfjTCuFUsrShSPOz9OxwJ4t0ZIjuKxTRCDVUO7d/GZh2r7lx4zJCxACuHci0DvTQIDAQAB 

Podría por favor me ayude a aportar el código de Java con éxito o sugerir una alternativa para obtener el mismo resultado en C#?

EDIT1: la salida en Java es diferente cada vez que ejecuto el programa. No creo que se haya especificado ningún relleno, por lo que no entiendo qué hace que la salida sea aleatoria.

Edit2: Java utiliza PKCS1 por defecto, por lo que fue suficiente para especificar que en el C# inicialización de cifrado para obtener el mismo tipo de cifrado (aunque no el mismo resultado, que era irrelevante en este punto).

+0

Más que pregunta, pero a pesar de que escupieron respuestas diferentes, ¿dan las mismas entradas cuando las desencriptas? –

+0

Sí, las cadenas decodificadas con UTF8 son las mismas y aparentemente el módulo y el exponente de las dos estructuras clave (PublicKey en Java, RsaKeyParameters en C#) son idénticos. No intento descifrar los resultados ya que no los necesito y el programa no requiere la clave privada. – user1098567

+2

¿Duplicado? http://stackoverflow.com/questions/4758321/java-rsa-encryption-non-repeatable –

Respuesta

1

Como una conjetura, diría que Java agrega relleno aleatorio para crear una encriptación más fuerte.

implementaciones

más práctico de RSA hacen esto, y como el wiki pone ...

Debido a que el cifrado RSA es un algoritmo de cifrado determinista - es decir, no tiene un componente aleatorio - un atacante puede lanzar con éxito un elegido ataque de texto sin formato contra el criptosistema, mediante el cifrado de planos comunes bajo la clave pública y prueba si son iguales al texto cifrado. Un criptosistema se denomina semánticamente seguro si un atacante no puede distinguir dos cifrados entre sí, incluso si el atacante conoce (o ha elegido) los textos planos correspondientes. Como se describió anteriormente, RSA sin relleno no es semánticamente seguro.

Es probable que sus dos métodos no tengan el mismo resultado.