2012-04-17 13 views
5

So habe ich viele Beispiele gesehen, und eine Menge googeln, und schaute Beispiele auf Stack Overflow ... und ich brauche Hilfe. Ich habe eine Android-Anwendung, und ich bin zu speichern Benutzernamen und Passwörter auf dem Gerät, und ich brauche sie AES auf Beispiele 256. Vom Blick zu verschlüsseln, ist es das, was ich bisher:Android AES 256-Bit Verschlüsseln von Daten

public class Security { 
    Cipher ecipher; 
    Cipher dcipher; 

    // 8-byte Salt 
    byte[] salt = { 
     (byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32, 
     (byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03 
    }; 

    // Iteration count 
    int iterationCount = 19; 

    public Security (String passPhrase) { 
     try { 
      // Create the key 
      KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); 
      SecretKey key = SecretKeyFactory.getInstance(
       "PBEWithSHAAndAES").generateSecret(keySpec); 
      ecipher = Cipher.getInstance(key.getAlgorithm()); 
      dcipher = Cipher.getInstance(key.getAlgorithm()); 

      // Prepare the parameter to the ciphers 
      AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); 

      // Create the ciphers 
      ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); 
      dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public String encrypt(String str) { 
     try { 
      // Encode the string into bytes using utf-8 
      byte[] utf8 = str.getBytes("UTF8"); 

      // Encrypt 
      byte[] enc = ecipher.doFinal(utf8); 

      // Encode bytes to base64 to get a string 
      return Base64.encodeToString(enc, Base64.DEFAULT); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 

    public String decrypt(String str) { 
     try { 
      // Decode base64 to get bytes 
      byte[] dec = Base64.decode(str, Base64.DEFAULT); 

      // Decrypt 
      byte[] utf8 = dcipher.doFinal(dec); 

      // Decode using utf-8 
      return new String(utf8, "UTF8"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 
} 

I‘ Ich versuche, es passwortbasiert zu machen, so dass ein Benutzer beim ersten Mal ein Benutzerkonto mit dem Benutzernamen und dem Kennwort für die Kommunikation mit dem Server erstellt und eine PIN erstellt, die als Schlüssel für diese in der Datenbank gespeicherten Anmeldeinformationen verwendet wird.

Worüber ich hauptsächlich besorgt bin, ist dieses Aussehen sicher? Ich weiß, dass ein festes Salz schlecht ist, wie repariere ich das?

ich weiß, dass es wie eine Milliarde Fragen zu diesem Thema gewesen, aber ich jemand will einfach nur kommen und zu sagen: „DIES IST SICHER“ oder „Das ist nicht sicher, ändern Sie diesen“

Dank!


EDIT:

Das ist also der Code, den ich bisher habe, und es scheint zu funktionieren ...

public class Security { 

    Cipher ecipher; 
    Cipher dcipher; 
    byte[] salt = new byte[8]; 
    int iterationCount = 200; 

    public Security(String passPhrase) { 
     try { 
      // generate a random salt 
      SecureRandom random = new SecureRandom(); 
      random.nextBytes(salt); 

      // Create the key 
      KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount); 
      SecretKey key = SecretKeyFactory.getInstance(
       "PBEWithSHA256And256BitAES-CBC-BC").generateSecret(keySpec); 
      ecipher = Cipher.getInstance(key.getAlgorithm()); 
      dcipher = Cipher.getInstance(key.getAlgorithm()); 

      // Prepare the parameter to the ciphers 
      AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); 

      // Create the ciphers 
      ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); 
      dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public String encrypt(String str) { 
     try { 
      // Encode the string into bytes using utf-8 
      byte[] utf8 = str.getBytes("UTF8"); 

      // Encrypt 
      byte[] enc = ecipher.doFinal(utf8); 

      // Encode bytes to base64 to get a string 
      return Base64.encodeToString(enc, Base64.DEFAULT); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 

    public String decrypt(String str) { 
     try { 
      // Decode base64 to get bytes 
      byte[] dec = Base64.decode(str, Base64.DEFAULT); 

      // Decrypt 
      byte[] utf8 = dcipher.doFinal(dec); 

      // Decode using utf-8 
      return new String(utf8, "UTF8"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 

    public int getIterationCount() { 
     return iterationCount; 
    } 

    public String getSalt() { 
     return Base64.encodeToString(salt, Base64.DEFAULT); 
    } 
} 

ich diesen Code verwendet, um es zu testen:

Security s = new Security(pinBox.getText().toString()); 
      String encrypted = s.encrypt(passwordBox.getText().toString()); 
      String decrypted = s.decrypt(encrypted); 
      builder.setMessage("pin: " + pinBox.getText().toString() + "\n" + 
        "password: " + passwordBox.getText().toString() + "\n" + 
        "encrypted: " + encrypted + "\n" + 
        "decrypted: " + decrypted + "\n" + 
        "salt: " + s.getSalt()); 

Also muss ich nicht über einen Initialisierungsvektor sorgen? Oder speziell einen Cipher-Algorithmus hardcodieren?

Danke nochmal!

+0

Danke Kumpel für diese Hilfe .. :) – Noman

+0

können Sie mir dabei helfen? http://stackoverflow.com/questions/34061675/convert-ios-cryption-to-android :( – MetaSnarf

Antwort

4

EDIT: Während der folgende Code richtig ist, tut was Sie haben im Grunde die gleiche Sache, mit der IV aus dem Passwort abgeleitet, so dass Sie es nicht separat speichern müssen.

Funktioniert Ihr Code wie erwartet? Für die eigentliche Verschlüsselung/Entschlüsselung würden Sie AES wahrscheinlich im CBC-Modus verwenden. Dann würden Sie eine IV benötigen, so wird es so etwas wie dieses:

ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
byte[] iv = new byte[IV_LENGTH]; 
SecureRandom random = new SecureRandom(); 
random.nextBytes(iv); 
ecipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv)); 
byte[] enc = ecipher.doFinal(utf8); 

Ob es sicher ist, hängt davon ab, was Sie dies für verwenden. Der Zweck des Salzes besteht darin, das Erzwingen der Passphrase zu erschweren: Wenn es zufällig ist, kann der Angreifer keine vorgenerierten Passphrasetabellen verwenden (Passphrase-> Schlüssel). Wenn Sie sich über diese Art von Angriff nicht allzu viele Sorgen machen, können Sie dies möglicherweise nicht beheben. Wenn Sie sich entschließen, es zufällig zu machen, speichern Sie es einfach mit den verschlüsselten Daten. Gleiches mit dem IV.

+0

Ich nehme an, ich würde die Salz-und iv verschlüsseln, bevor Sie sie mit dem verschlüsselten Benutzernamen und Passwort speichern? Wenn ja, wie würde Ich entschlüssele? Ich würde nicht das Salz und iv haben, um den Entschlüsseler einzurichten, also vielleicht bin ich ein Missverständnis? – Josh

+0

Das Salz ist nicht selbst ein Geheimnis, es muss nicht verschlüsselt werden, noch ist die IV. –

+0

Ok. "Das macht Sinn. Danke, dass Sie mir geholfen haben. Ich werde meinen Code bearbeiten und zurück posten. Ich möchte sicherstellen, dass ich die bestmögliche Lösung bekomme." Würdest du die Iterationszahl erklären können? Es ist egal, ob es zufällig ist, ich denke, ich habe es gelesen, wenn es höher ist, dauert der Code länger, aber ich nehme an, dass höher ist besser?Ich vermute, es ist etwas zu bewirken, den Algorithmus iteration_count mal vor dem Zurückgeben eines endgültigen Wertes laufen zu lassen? – Josh

Verwandte Themen