2009-08-19 21 views
6

Attualmente mi sto ricevendo il seguente errore quando si utilizza Java per decifrare un Base64 codificato RSA stringa crittografata che è stato fatto in C#:errore di riempimento quando si utilizza RSA di crittografia in C# e la decrittografia in Java

javax.crypto.BadPaddingException : Non PKCS # 1 tipo di blocco 2 o zero padding

il processo di installazione tra la centrale da .NET e Java è fatto con la creazione di una chiave privata nell'archivio chiavi .NET poi dal file PEM estratto, l'uso creato keytool per creare una versione di JKS con la chiave privata. Java carica il JKS già creato e decodifica la stringa Base64 in una matrice di byte e quindi utilizza la chiave privata per decodificare.

Ecco il codice che ho in C# che crea la stringa crittografata:

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); 
} 

Ecco il codice che ho in Java che decifra la stringa immessa:

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)); 
} 

C'è qualcuno vedi un passo mancante o dove il padding o l'oggetto deve essere cambiato? Ho fatto ore di lettura su questo sito e su altri, ma non ho davvero trovato una soluzione concreta.

Il vostro aiuto è molto apprezzato.

Grazie. -Matt

+0

Dove si trova il padding specificato nel codice C#? Come sai che OAEP (che è PKCS # 1 ver. 2) non viene utilizzato durante la crittografia? – erickson

+1

Per prima cosa isolare la crittografia e la codifica in probelms separati. Vale a dire. convalidare che il byte Java decodificato [] è identico al byte C# originale []. quindi puoi chiedere se è un problema RSA o un problema Base64. Come ha detto erickson, probabilmente è la differenza nel PKCS predefinito tra C# e le librerie Java. –

+0

@erickson - il secondo parametro del metodo .NET Encrypt() seleziona il padding - true specifica OAEP e false (utilizzato nell'esempio) specifica PKCS # 1 ver 1.5. –

risposta

2

Verificare di aver scambiato correttamente la chiave.

Provare a decrittografare con una chiave errata non è distinguibile dalla decifratura dei dati riempiti male.

0

La mia ipotesi è che la versione C# stia emettendo i byte in formato little endian, e la versione Java sta importando i byte aspettandosi che siano in formato big endian. Prova a scambiare i byte in baRet da capo a capo prima di convertirli in base 64 e vedere se il tuo programma Java può decrittografarli.

Solo una supposizione.

2

Sto lavorando con un problema simile che opera tra roba .Net e iPhone in Objective - C, e credo che la risposta si trova in questo piccolo gioiello dalla documentazione RSACryptoServiceProvider:

differenza l'implementazione RSA a non gestito CAPI , la classe RSACryptoServiceProvider inverte l'ordine di una matrice crittografata di byte dopo la crittografia e prima della decrittografia. Per impostazione predefinita, i dati crittografati dalla classe RSACryptoServiceProvider non possono essere decodificati dalla funzione CAPI CryptDecrypt e i dati crittografati dal metodo CAPI CryptEncrypt non possono essere decodificati dalla classe RSACryptoServiceProvider.

Vedi qui per maggiori dettagli: http://msdn.microsoft.com/en-us/library/s575f7e2(v=VS.90).aspx

4

ho avuto exactely lo stesso problema e alla fine ho trovato la soluzione!

Ero testardo con PKCS1Padding ma non sono riuscito a farlo funzionare.

Il miglior risultato ho ottenuto utilizzando "rsa.Encrypt (Bain, false)" sul lato C# e "RSA/NONE/NoPadding" sul lato Java era questo tipo di stringa: "☻ o? + _> ?? 5? L0Q * ??? *? R ▲ ??? ♀7 ... "seguito dalla mia stringa decifrata.Quindi in un modo che è stato decodificato ma poiché non è specificato alcun padding, i dati vengono spostati. Così ho provato tutti i paddings disponibili in bouncycastle, ma avrei sempre ricevuto errori come "blocco dimensione errata" o "hash dati errati".

così ho deciso di iniziare a provare imbottiture OAEP e sono finalmente riuscito a farlo funzionare utilizzando "rsa.Encrypt (Bain, true)" sul lato C# e "RSA/NONE/OAEPWithSHA1AndMGF1Padding" sulla lato java!

Ha funzionato per me, spero che funzionerà anche per te! Se non funziona assicurati di utilizzare la chiave giusta, molto spesso il problema deriva dalla chiave.

+0

Questo mise fine a un dolore di due giorni !. Molte grazie. –

0

Ho avuto lo stesso problema quando uso Bouncy Castle 1.48 ma non era correlato alla chiave. Invece, ho scoperto che dovevo impostare le seguenti proprietà di sistema:

-Dorg.bouncycastle.pkcs1.strict=false 
Problemi correlati