2016-04-13 7 views
3

Ich muss String für projektbezogene Zwecke verschlüsseln und erhielt den untenstehenden Code für denselben Anbieter.C# RSACryptoServiceProvider-Code in Java konvertieren

public static string EncryptString(string StringToEncrypt) 
{ 
    RSACryptoServiceProvider provider = new RSACryptoServiceProvider(); 
    string xmlString = "<RSAKeyValue><Modulus>qqoWhMwGrrEBRr92VYud3j+iIEm7652Fs20HvNckH3tRDJIL465TLy7Cil8VYxJre69zwny1aUAPYItybg5pSbSORmP+hMp6Jhs+mg3qRPvHfNIl23zynb4kAi4Mx/yEkGwsa6L946lZKY8f9UjDkLJY7yXevMML1LT+h/a0a38=</Modulus><Exponent>AQAB</Exponent><P>20PwC7nSsfrfA9pzwSOnRYdbhOYivFSuERxvXHvNjCll5XdmFYYp1d2evXcXbyj3E1k8azce1avQ9njH85NMNQ==</P><Q>x0G0lWcQ13NDhEcWbA7R2W5LPUmRqcjQXo8qFIaHk7LZ7ps9fAk/kOxaCR6hvfczgut1xSpXv6rnQ5IGvxaHYw==</Q><DP>lyybF2qSEvYVxvFZt8MeM/jkJ5gIQPLdZJzHRutwx39PastMjfCHbZW0OYsflBuZZjSzTHSfhNBGbXjO22gmNQ==</DP><DQ>NJVLYa4MTL83Tx4vdZ7HlFi99FOI5ESBcKLZWQdTmg+14XkIVcZfBxDIheWWi3pEFsWqk7ij5Ynlc/iCXUVFvw==</DQ><InverseQ>X5Aw9YSQLSfTSXEykTt7QZe6SUA0QwGph3mUae6A2SaSTmIZTcmSUsJwhL7PLNZKbMKSWXfWoemj0EVUpZbZ3Q==</InverseQ><D>jQL4lEUYCGNMUK6GEezIRgiB5vfFg8ql3DjsOcXxnOmBcEeD913kcYnLSBWEUFW55Xp0xW/RXOOHURgnNnRF3Ty5UR73jPN3/8QgMSxV8OXFo3+QvX+KHNHzf2cjKQDVObJTKxHsHKy+L2qjfULA4e+1cSDNn5zIln2ov51Ou3E=</D></RSAKeyValue>"; 
    provider.FromXmlString(xmlString); 
    return Convert.ToBase64String(provider.Encrypt(Encoding.ASCII.GetBytes(StringToEncrypt), false)); 
} 

Allerdings muss ich es zu JAVA ändern oder übersetzen. Ich habe die folgende Methode für den gleichen Zweck geschrieben.

public static String EncryptString(String strToBeEncrypted) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException 
{ 
    String modulusString = "qqoWhMwGrrEBRr92VYud3j+iIEm7652Fs20HvNckH3tRDJIL465TLy7Cil8VYxJre69zwny1aUAPYItybg5pSbSORmP+hMp6Jhs+mg3qRPvHfNIl23zynb4kAi4Mx/yEkGwsa6L946lZKY8f9UjDkLJY7yXevMML1LT+h/a0a38="; 
    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 = strToBeEncrypted.getBytes("US-ASCII"); 
    byte[] cipherData = cipher.doFinal(plainBytes); 
    String encryptedStringBase64 = Base64.encodeBase64String(cipherData); 

    return encryptedStringBase64; 
} 

Aber die Beispielergebnisse stimmen nicht überein.

String ist "4111111111111111" und verschlüsselte Ergebnis sein sollte:

PfU31ai9dSwWX4Im19TlikfO9JetkJbUE + btuvpBuNHTnnfrt4XdM4PmGA19z8rF + lPUC/kcOEXciUSxFrAPyuRJHifIDqWFbbJvPhatbf269BXUiAW31UBX3X5bBOqNWjh4LDitYY0BtarlTU4xzOFyb7vLpLJe9aHGWhzs6q0 =

Aber das Ergebnis von Java-Code ist

Cxp5AIzTHEkrU6YWwYo5yYvpED2qg9IC/0ct + tRgDZi9fJb8LaK + E1l9lJEt7MFQ2KB/exo 4NYwijnBKYPeLStXyfVO1Bj6S76zMeKygAlCtDukq1UhJaJKaCXY94wi9Kel09VTmj + VByIYvAGUFqZGaK1CyLnd8QXMcdcWi3sA =

+2

Was passiert, wenn Sie Ihren C# - und Java-Code erneut ausführen? Verändern sich die Chiffrate? Wenn dies der Fall ist, wird ein randomisiertes Padding verwendet (wichtig) und Sie müssen es in einem verschlüsseln und im anderen entschlüsseln, um die Kompatibilität zu überprüfen. –

+0

Danke @ArtjomB. Ich habe nur die Kompatibilität mit dem Entschlüsselungscode des Anbieters überprüft und es funktioniert gut. – RahulMuk07

+0

@ArtjomB. Für die Verschlüsselung muss randomisiertes Padding * verwendet * werden. Die Verschlüsselung muss nicht deterministisch sein, sonst erhält man denselben Chiffretext für denselben Klartext (genau wie bei der symmetrischen ECB-Verschlüsselung). Nur Lehrbuch RSA ist deterministisch und sehr unsicher für alle Arten oder Gründe.Die Signaturerzeugung kann jedoch deterministisch sein. Könnten Sie eine Antwort posten? –

Antwort

1

Jeder Verschlüsselungsalgorithmus muss, um randomisiert werden semantische Sicherheit. Andernfalls bemerkt ein Angreifer möglicherweise, dass Sie dieselbe Nachricht erneut gesendet haben, indem Sie nur die Chiffriertexte beobachten. In symmetrischen Chiffren wird diese Eigenschaft durch eine zufällige IV erreicht. In RSA wird dies durch eine randomisierte Auffüllung erreicht (PKCS # 1 v1.5 Typ 2 und PKCS # 1 v2.x OAEP sind randomisiert).

Sie können überprüfen, ob das Padding randomisiert ist, indem Sie die Verschlüsselung erneut mit demselben Schlüssel und Klartext ausführen und die verschlüsselten Texte mit früheren verschlüsselten Texten vergleichen. Wenn sich die Chiffriertexte in C# oder Java zwischen den Ausführungen ändern, können Sie nicht erkennen, ob die Verschlüsselung kompatibel ist, indem Sie nur die Chiffriertexte betrachten.

Der richtige Weg, dies zu überprüfen, wäre, etwas in einer Sprache zu verschlüsseln und dann in der anderen Sprache zu entschlüsseln. Um die volle Kompatibilität zu gewährleisten, sollten Sie es auch anders herum versuchen.

in Ihrem Code Blick scheinen beide gleichwertig, weil false als zweiten Parameter in RSACryptoServiceProvider#Encrypt geben wird PKCS # 1 v1.5 Polsterung zu verwenden, und Cipher.getInstance("RSA/ECB/PKCS1PADDING") Anfragen der gleiche Polsterung. Die Eingabe/Ausgabe-Kodierungen scheinen ebenfalls äquivalent zu sein. Also, ja, dieser Code wird gleichwertig sein.


PKCS # 1 v1.5 padding sollte heute nicht mehr verwendet werden, da sie anfällig gegen einen Bleichenbacher Angriff ist (reference). Sie sollten OAEP für die Verschlüsselung und PSS für das Signieren verwenden, die als sicher gelten. C# und Java unterstützen beide OAEP, aber es kann Unterschiede in den Standard-Hash-Funktionen geben, die verwendet werden (Hash und MGF1).

+0

Hallo, ich habe das gleiche Szenario in der Frage. Wenn randomisiertes Padding verwendet wird, wie überprüfe ich, ob ein vom Benutzer eingegebenes Passwort mit dem Passwort in der Datenbank übereinstimmt, ohne das Passwort von der Datenbank zu entschlüsseln? Weil ich das Entschlüsseln des Passworts gehört habe, ist das keine gute Übung. Wir prüfen nur, ob der verschlüsselte Wert derselbe ist. Allerdings sehe ich hier nicht, wie ich das machen kann. Einzige Möglichkeit scheint das Passwort von db zu entschlüsseln. – nanospeck

+0

@nanospeck Sie sollten niemals die Passwörter Ihres Benutzers verschlüsseln. Sie müssen stattdessen Hashing mit einigen starken PBKDF2, bcrypt, scrypt und Argon2 verwenden. Da Hash-Funktionen eine Einwegfunktion sind, können Sie die Hashes nicht "entschlüsseln". Um Ihren Benutzer zu authentifizieren, können Sie das Passwort erneut über die Hash-Funktion ausführen, um es mit dem Hash zu vergleichen, der in der Datenbank gespeichert ist. Weitere Informationen: [Wie sichere Passwörter sicher zu hacken?] (Http://security.stackexchange.com/q/211/45523) RSA ist definitiv das falsche Werkzeug für den Job. –

+0

Ihre Worte haben mir wirklich zu diesem Thema geholfen. Leider portiere ich ein bereits in .NET implementiertes Projekt mit dem RSACryptoServiceProvider nach Java, so dass ich die Passwortverschlüsselung nicht neu implementieren kann. – nanospeck