2013-08-06 13 views
10

Mi è stato fornito questo codice C# scritto dal team del servizio Web che espone alcuni servizi Web che sto pianificando di consumare. La mia password deve essere crittografata con questo codice in modo che il servizio Web sappia come decodificarlo alla fine.Traduzione di C# RSACryptoServiceProvider nel codice JAVA

using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) 
{ 
    rsa.FromXmlString(publicKey); 
    byte[] plainBytes = Encoding.Unicode.GetBytes(clearText); 
    byte[] encryptedBytes = rsa.Encrypt(plainBytes, false); 
    return Convert.ToBase64String(encryptedBytes); 
} 

sto usando Java per consumare questo servizio web e in questo momento, sto avendo problemi a tradurre tale codice #C in codice Java, perché che il servizio web non può decifrare la password corretta.

Ecco il mio attuale tentativo fallito: -

// my clear text password 
String clearTextPassword = "XXXXX"; 

// these values are provided by the web service team 
String modulusString = "..."; 
String publicExponentString = "..."; 

BigInteger modulus = new BigInteger(1, Base64.decodeBase64(modulusString.getBytes("UTF-8"))); 
BigInteger publicExponent = new BigInteger(1, Base64.decodeBase64(publicExponentString.getBytes("UTF-8"))); 

KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 

RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, publicExponent); 
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); 

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"); 
cipher.init(Cipher.ENCRYPT_MODE, publicKey); 

String encodedEncryptedPassword = new String(Base64.encodeBase64(cipher.doFinal(clearTextPassword.getBytes("UTF-8")))); 

Che cosa ho fatto di sbagliato? Grazie mille.

2013-08-07 - AGGIORNAMENTO

stavo leggendo this website e mi sono reso conto che il mio valore di modulo e il valore di esponente pubblico non sono in esadecimale. Così, ho modificato il mio codice un po 'e ho provato con RSA/ECB/PKCS1PADDING come menzionato da @Dev.

// my clear text password 
String clearTextPassword = "XXXXX"; 

// these are the actual values I get from the web service team 
String modulusString = "hm2oRCtP6usJKYpq7o1K20uUuL11j5xRrbV4FCQhn/JeXLT21laKK9901P69YUS3bLo64x8G1PkCfRtjbbZCIaa1Ci/BCQX8nF2kZVfrPyzcmeAkq4wsDthuZ+jPInknzUI3TQPAzdj6gim97E731i6WP0MHFqW6ODeQ6Dsp8pc="; 
String publicExponentString = "AQAB"; 

Base64 base64Encoder = new Base64(); 

String modulusHex = new String(Hex.encodeHex(modulusString.getBytes("UTF-8"))); 
String publicExponentHex = new String(Hex.encodeHex(publicExponentString.getBytes("UTF-8"))); 

BigInteger modulus = new BigInteger(modulusHex, 16); 
BigInteger publicExponent = new BigInteger(publicExponentHex); 

KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 

RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, publicExponent); 
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); 

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); 
cipher.init(Cipher.ENCRYPT_MODE, publicKey); 

String encodedEncryptedPassword = new String(base64Encoder.encode(cipher.doFinal(clearTextPassword.getBytes("UTF-8")))); 

Quando mi ha colpito il webservice, sto ottenendo questo errore: "I dati da decifrati supera il massimo per questo modulo di 128 byte." Sembra che la password di testo non sia ancora crittografata correttamente.

Qualsiasi aiuto o suggerimento è molto apprezzato. Grazie.

2013-08-09 - SOLUZIONE

ho postato la mia soluzione di lavoro finale di seguito.

risposta

8

Trovato la soluzione.

String modulusString = "hm2oRCtP6usJKYpq7o1K20uUuL11j5xRrbV4FCQhn/JeXLT21laKK9901P69YUS3bLo64x8G1PkCfRtjbbZCIaa1Ci/BCQX8nF2kZVfrPyzcmeAkq4wsDthuZ+jPInknzUI3TQPAzdj6gim97E731i6WP0MHFqW6ODeQ6Dsp8pc="; 
String publicExponentString = "AQAB"; 

byte[] modulusBytes = Base64.decodeBase64(modulusString); 
byte[] exponentBytes = Base64.decodeBase64(publicExponentString); 
BigInteger modulus = new BigInteger(1, modulusBytes); 
BigInteger publicExponent = new BigInteger(1, exponentBytes); 

RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, publicExponent); 
KeyFactory fact = KeyFactory.getInstance("RSA"); 
PublicKey pubKey = fact.generatePublic(rsaPubKey); 
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); 
cipher.init(Cipher.ENCRYPT_MODE, pubKey); 

byte[] plainBytes = clearTextPassword.getBytes("UTF-16LE"); 
byte[] cipherData = cipher.doFinal(plainBytes); 
String encryptedStringBase64 = Base64.encodeBase64String(cipherData); 
+0

Ho avuto la sensazione che questo sarebbe finito per essere un problema di protocollo di accesso invece del codice. Avevamo coperto quasi tutto il resto. Sono contento che tu l'abbia capito. – Dev

+0

Quando vedo 'Encoding.Unicode.GetBytes (String)' Sto pensando a 'UTF-8', non a' UTF-16LE', presupposto evidentemente errato, quindi una buona presa sulla tua parte. – Dev

+0

Grazie per quello - risolto il mio problema. Sembra che le persone in .NET utilizzino spesso Encoding.Unicode.GetBytes/Encoding.Unicode.GetString senza rendersi conto che non è UTF-8. – mvmn

1

In base ai documenti MSDN allo RSACryptoServiceProvider.Encrypt, quando il secondo argomento è false, il codice utilizza il riempimento PKCS # 1 v1.5. Quindi, a prima vista, la tua specifica di cifratura non è corretta.

Prova RSA/ECB/PKCS1PADDING invece.

Si sta convertendo il proprio materiale chiave in gran parte nel secondo esempio di codice e l'avete corrotto, il che finisce per fare in modo che il vostro cifrario pensi di avere più materiale chiave di quello che effettivamente avete e rende il vostro messaggio troppo lungo (che causa il vostro errore) così come incomprensibile al cifrario di decodifica sull'altro capo. Converti direttamente in matrici di byte e passa a BigInteger.

String modulusString = "..."; 
String publicExponentString = "..."; 

byte[] mod = Base64.decodeBase64(modulusString); 
byte[] e = Base64.decodeBase64(publicExponentString); 

BigInteger modulus = new BigInteger(1, mod); 
BigInteger publicExponent = new BigInteger(1, e); 
+0

Ho provato "RSA/ECB/PKCS1PADDING" e anche "RSA" per il codice. Entrambi fallirono. – limc

+0

@limc Chi usa la classe Base64'? – Dev

+0

Attualmente sto usando Commons Codec. Inizialmente ho usato Spring Codec, quindi ho pensato che sarebbe stato il problema, quindi sono passato a Commons Codec ... ma hanno prodotto lo stesso risultato. – limc

Problemi correlati