2009-08-19 18 views
6

Actualmente estoy recibiendo el siguiente error cuando se utiliza Java para descifrar una base 64 codificado RSA cadena cifrada que se hizo en C#:error de relleno cuando se utiliza RSA cifrado en C# y descifrado en Java

javax.crypto.BadPaddingException : No PKCS # 1 cuadra de tipo 2 o de relleno cero

el proceso de configuración entre el intercambio de, el uso de .NET y Java se realiza mediante la creación de una clave privada en el almacén de claves .NET luego desde el archivo PEM extraída creado keytool para crear una versión de JKS con la clave privada. Java carga el JKS ya creado y decodifica la cadena Base64 en una matriz de bytes y luego usa la clave privada para descifrar.

Aquí está el código que tengo en C# que crea la cadena cifrada:

public string Encrypt(string value) { 
    byte[] baIn = null; 
    byte[] baRet = null; 
    string keyContainerName = "test"; 

    CspParameters cp = new CspParameters(); 
    cp.Flags = CspProviderFlags.UseMachineKeyStore; 
    cp.KeyContainerName = keyContainerName; 
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); 

    // Convert the input string to a byte array 
    baIn = UnicodeEncoding.Unicode.GetBytes(value); 

    // Encrypt 
    baRet = rsa.Encrypt(baIn, false); 

    // Convert the encrypted byte array to a base64 string 
    return Convert.ToBase64String(baRet); 
} 

Aquí está el código que tengo en Java que descifra la cadena introducida:

public void decrypt(String base64String) { 
    String keyStorePath = "C:\Key.keystore"; 
    String storepass = "1234"; 
    String keypass = "abcd"; 
    byte[] data = Base64.decode(base64String); 
    byte[] cipherData = null; 

    keystore = KeyStore.getInstance("JKS"); 
    keystore.load(new FileInputStream(keyStorePath), storepass.toCharArray()); 

    RSAPrivateKey privateRSAKey = (RSAPrivateKey) keystore.getKey(alias, keypass.toCharArray()); 

    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
    cipher.init(Cipher.DECRYPT_MODE, privateRSAKey); 
    cipherData = cipher.doFinal(data); 

    System.out.println(new String(cipherData)); 
} 

¿Hay alguien ver un paso que falta o donde el relleno o elemento necesita ser cambiado? He hecho horas de lectura en este sitio y otros, pero realmente no he encontrado una solución concreta.

Su ayuda es muy apreciada.

Gracias. -Matt

+0

¿Dónde está el relleno especificado en el código C#? ¿Cómo sabe que OAEP (que es PKCS # 1 ver.2) no se está utilizando durante el cifrado? – erickson

+1

Primero, aísle el cifrado y la codificación en probelmas por separado. Es decir. valide que el byte de Java decodificado [] es idéntico al byte de C# original []. entonces puedes preguntar si es un problema de RSA o de Base64. Como dijo Erickson, probablemente sea la diferencia en el PKCS predeterminado entre C# y las libs de Java. –

+0

@erickson - el segundo parámetro del método .NET Encrypt() selecciona el relleno - true especifica OAEP y falso (usado en el ejemplo) especifica PKCS # 1 ver 1.5. –

Respuesta

2

Compruebe que ha cambiado la llave correctamente.

Intentar descifrar con una clave incorrecta es indistinguible de descifrar datos mal acolchados.

0

Supongo que la versión C# está emitiendo los bytes en formato little endian, y la versión Java está importando los bytes esperando que estén en formato big endian. Intente intercambiar los bytes en baRet de extremo a extremo antes de convertirlos a la base 64, y vea si su programa Java puede descifrarlos.

Solo supongo.

2

estoy trabajando a través de un problema similar que opera entre la materia y .Net iPhone en Objective - C, y creo que la respuesta está en esta pequeña joya de la documentación RSACryptoServiceProvider:

A diferencia de la implementación de RSA en el CAPI no administrado , la clase RSACryptoServiceProvider invierte el orden de una matriz encriptada de bytes después del cifrado y antes del descifrado. De forma predeterminada, los datos cifrados por la clase RSACryptoServiceProvider no pueden descifrarse mediante la función CAPI CryptDecrypt y los datos cifrados mediante el método CAPI CryptEncrypt no pueden ser descifrados por la clase RSACryptoServiceProvider.

Vea aquí para más detalles: http://msdn.microsoft.com/en-us/library/s575f7e2(v=VS.90).aspx

4

tuve exactely el mismo problema y finalmente encontrar la solución!

Fui terco usando PKCS1Padding pero no pude hacerlo funcionar.

El mejor resultado que obtuve mediante "rsa.Encrypt (Bain, falsa)" en el lado C# y "RSA/NONE/NoPadding" en el lado de Java era este tipo de cadena: "☻ o? + _> ?? 5? L0Q * ??? *? R ▲ ??? ♀7 ... "seguido de mi secuencia descifrada.Entonces, de alguna manera, se descifró, pero como no se especifica relleno, los datos se cambian. Así que probé todos los paddings disponibles en bouncycastle, pero siempre obtenía errores como "bloquear el tamaño incorrecto" o "datos incorrectos".

así que decidí empezar a tratar los acolchados OAEP y finalmente lograron conseguir que funcione mediante el uso de "rsa.Encrypt (Bain, true)" en el lado C# y "RSA/NONE/OAEPWithSHA1AndMGF1Padding" en el lado java!

Me funcionó, ¡espero que te funcione también! Si no funciona, asegúrese de estar utilizando la tecla correcta, muy a menudo el problema proviene de la clave.

+0

Esto puso fin a un dolor de dos días !. Muchas gracias. –

0

Tuve el mismo problema al utilizar Bouncy Castle 1.48 pero no estaba relacionado con la clave. En cambio, descubrí que tenía que establecer la siguiente propiedad del sistema:

-Dorg.bouncycastle.pkcs1.strict=false