2016-05-31 4 views
-1

Ich versuche, die Login-Logik in meiner Android-App zu implementieren.RSA Verschlüsseln Zeichenfolge mit angegebenen öffentlichen Schlüssel XML - Module und Exponenten - ANDROID

Dies ist das Szenario:

  • auf klicken Sie auf die App eine GET-Anfrage an Azure Server senden und eine XML-Zeichenfolge mit dem RSA-Public-Key (Modul + exp)
  • das Passwort gehasht erhalten wird und encripted
  • RSA (Hash (Pwd)) wird an meinen Server gesendet.

Ich benutze diese Logik in meiner eckigen App und es funktioniert gut.

Das Problem

Wenn ich versuche, mein Hash-Passwort, das Verfahren retur einig illeggible Charakter .. Eine Umwandlung Problem zu verschlüsseln?

Die Android-Code

if (jsonToken.has("data")) 
    { 
     // Converte la Stringa in XML 
     String publicToken = jsonToken.getString("data"); 
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder builder = factory.newDocumentBuilder(); 
     Document publicTokenXML = builder.parse(new InputSource(new StringReader(publicToken))); 


     Log.i("out", token.toString()); 
     Log.i("outXML", publicTokenXML.getFirstChild().getFirstChild().getNextSibling().getTextContent()); 

     // prendo le due parti che mi servono dall'XML 
     byte[] expBytes = Base64.decode(publicTokenXML.getFirstChild().getFirstChild().getNextSibling().getTextContent(), Base64.NO_PADDING); 
     byte[] modBytes = Base64.decode(publicTokenXML.getFirstChild().getFirstChild().getTextContent(), Base64.NO_PADDING); 
     byte[] dBytes = Base64.decode(d, Base64.DEFAULT); 


     BigInteger modules = new BigInteger(1, modBytes); 
     BigInteger exponent = new BigInteger(1, expBytes); 
     BigInteger d = new BigInteger(1, dBytes); 

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


     RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modules, exponent); 
     PublicKey pubKey = keyFactory.generatePublic(pubSpec); 
     cipher.init(Cipher.ENCRYPT_MODE, pubKey); 
     byte[] encrypted = cipher.doFinal(bin2hex(getHash(pwd)).getBytes("UTF-8")); 
     // new String(encrypted)) is correct?!? 
     Log.i("encrypted: ", new String(encrypted)); 

     RSAPrivateKeySpec privSpec = new RSAPrivateKeySpec(modules, d); 
     PrivateKey privKey = keyFactory.generatePrivate(privSpec); 
     cipher.init(Cipher.DECRYPT_MODE, privKey); 
     byte[] decrypted = cipher.doFinal(encrypted); 
     System.out.println("decrypted: " + new String(decrypted)); 
     Log.i("hash", bin2hex(getHash(pwd))); 
    } 

'entschlüsselt' und 'Hash' Protokolle zurückkehren mir die gleiche Hash-String. Ich habe den Teil des öffentlichen und privaten Schlüssels protokolliert und sie sind korrekt.

ABER

The android studio output

Wie ich es in der richtigen Form lesen kann?

Danke an alle.

** EDIT/Lösung **

Denn wer, wie ich, einige Tutorial im Internet für implementieren RSA-Verschlüsselung in .NET gefolgt, das ist die Lösung, die für das Szenario für mich gearbeitet I beschrieben an der Spitze der SO Abfrage:

die Android-Code

if (jsonToken.has("data")) 
    { 
     // Converte la Stringa in XML 
     String publicToken = jsonToken.getString("data"); 
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder builder = factory.newDocumentBuilder(); 
     Document publicTokenXML = builder.parse(new InputSource(new StringReader(publicToken))); 


     Log.i("out", token.toString()); 
     Log.i("outXML", publicTokenXML.getFirstChild().getFirstChild().getNextSibling().getTextContent()); 

     // <RSAKeyValue><Modulus>*Modulus*</Modulus><Exponent>*Exponent*</Exponent></RSAKeyValue> 
     byte[] expBytes = Base64.decode(publicTokenXML.getFirstChild().getFirstChild().getNextSibling().getTextContent(), Base64.DEFAULT); 
     byte[] modBytes = Base64.decode(publicTokenXML.getFirstChild().getFirstChild().getTextContent(), Base64.DEFAULT); 
     byte[] dBytes = Base64.decode(d, Base64.DEFAULT); 


     BigInteger modules = new BigInteger(1, modBytes); 
     BigInteger exponent = new BigInteger(1, expBytes); 
     BigInteger d = new BigInteger(1, dBytes); 

     KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 
     // ***** 
     Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
     // ***** 

     RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modules, exponent); 
     PublicKey pubKey = keyFactory.generatePublic(pubSpec); 
     cipher.init(Cipher.ENCRYPT_MODE, pubKey); 
     byte[] encrypted = cipher.doFinal(bin2hex(getHash(pwd)).getBytes("UTF-8")); 

     // ***** 
     Log.i("encrypted: ", Base64.encodeToString(encrypted, Base64.DEFAULT).replace("\n", "")); 
     // ***** 

     // Decrypt 
     RSAPrivateKeySpec privSpec = new RSAPrivateKeySpec(modules, d); 
     PrivateKey privKey = keyFactory.generatePrivate(privSpec); 
     cipher.init(Cipher.DECRYPT_MODE, privKey); 
     byte[] decrypted = cipher.doFinal(encrypted); 
     System.out.println("decrypted: " + new String(decrypted)); 
     Log.i("hash", bin2hex(getHash(pwd))); 
    } 

** Das .NET Cor e Code **

private string RsaMyAndroidDecrypt(string passwordCrypt) 
    { 

     // Don't use OAEP padding (PKCS#1 v2). 
     var doOaepPadding = false; 
     // ------------------------------------------------ 
     // Decrypt 
     // ------------------------------------------------ 
     // Convert base64 string back to bytes. 
     var encryptedBytes = Convert.FromBase64String(passwordCrypt); 

     // Create a new instance of RSACryptoServiceProvider. 
     var rsa = new RSACryptoServiceProvider(); 
     // Import the RSA Key information. 
     rsa.ImportParameters(keyForUserPassword.ExportParameters(true)); 
     // Decrypt byte array. 
     var decryptedBytes = rsa.Decrypt(encryptedBytes, doOaepPadding); 
     // Get decrypted data. 
     return Encoding.UTF8.GetString(decryptedBytes); 
    } 
+2

Sie drucken die Binärdaten in die Protokolldatei, dies wird nie funktionieren. Niemals einen 'neuen String (verschlüsselt)' auf einem 'Byte []' aufrufen, das Binärdaten enthält! Konvertiere es vor dem Drucken in hex oder base64! – Robert

+1

Erforschen Sie die Zeichenkodierung. Beachten Sie, dass nicht alle Bytewerte für druckbare Zeichen kodierbar sind. – zaph

+0

Bitte editieren Sie die Antwort nicht in Ihrer Frage. Stattdessen, bitte [akzeptiere die Antwort] (// stackoverflow.com/help/accepted-answer), die dir am meisten geholfen hat. (Wenn Sie die Antwort selbst gefunden haben, können Sie sogar Ihre Frage selbst beantworten.) Wenn Sie genug [Reputation] haben (// stackoverflow.com/help/whats- Reputation), können Sie auch [upvote] (// stackoverflow.com/privileges/vote-up) Antworten, die Ihnen geholfen haben. –

Antwort

0

Für .NET Kern verwenden, sollten Sie nicht RSACryptoServiceProvider, sondern eher:

private byte[] Decrypt(string input) 
{ 
    // Don't use OAEP padding (PKCS#1 v2). 
    RSAEncryptionPadding padding = RSAEncryptionPadding.Pkcs1; 

    // ------------------------------------------------ 
    // Decrypt 
    // ------------------------------------------------ 
    // Convert base64 string back to bytes. 
    byte[] encryptedBytes = Convert.FromBase64String(passwordCrypt); 

    // Create a new instance of RSA. 
    using (RSA rsa = RSA.Create()) 
    { 
     // Import the RSA Key information. 
     rsa.ImportParameters(keyForUserPassword.ExportParameters(true)); 

     // Decrypt byte array. 
     byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, padding); 
     return decryptedBytes; 
    } 
} 

ich das Teil bin ignorieren hier, wo man es in eine UTF-8 beim Abbiegen Zeichenfolge. Und der Teil, wo Sie eine Sache wiederherstellen, die Sie ein Passwort nennen.

RSACryptoServiceProvider funktioniert nur unter Windows. RSA.Create() gibt eine geeignete Implementierung von RSA für jede Plattform zurück, auf der der Code ausgeführt wird.

Verwandte Themen