Frage

Ich verwende diesen Code -Snippet, um Daten in der Datenbank meiner App zu verschlüsseln/zu entschlüsseln:

http://www.androidsnippets.com/encryptdecrypt-strings

Es scheint, dass der Operation von javax.crypto.KeyGenerator.generateKey () in Android 2.3.3 OS unterschiedlich funktioniert als in anderen (vorherigen?) Versionen. Dies zeigt natürlich ein großes Problem für meine Benutzer, wenn sie ihr Gerät von 2.2 auf 2.3.3 aktualisieren, und die App beginnt, Fehler zu werfen, um die Datenbank zu entschlüsseln.

Ist das ein bekanntes Problem? Verwende ich die Krypto -Bibliothek falsch? Hat jemand Vorschläge, wie man dies angibt, damit Daten in 2.2 verschlüsselt werden können, um in 2.3.3 zu entschlüsseln?

Ich habe eine Test -App erstellt, die Werte über die Verschlüsselungsfunktion füttert. Wenn ich es auf einem 2.2 AVD leite, bekomme ich ein Ergebnis. Wenn ich es auf einem 2.3.3 AVD ausführe, bekomme ich ein anderes Ergebnis.

    import java.security.SecureRandom;

    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;

    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;

    public class main extends Activity {
        TextView tvOutput;
        static String out;
        String TEST_STRING = "abcdefghijklmnopqrstuvwxyz";
        String PASSKEY = "ThePasswordIsPassord";

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            tvOutput = (TextView) findViewById(R.id.tvOutput);
        }

        @Override
        public void onResume() {
            super.onResume();
            out = "";
            runTest();
            tvOutput.setText(out);
        }

        private void runTest() {
            out = "Test string: " + TEST_STRING + "\n";
            out += "Passkey: " + PASSKEY + "\n";
            try {
                out += "Encrypted: " + encrypt(PASSKEY, TEST_STRING) + "\n";
            } catch (Exception e) {
                out += "Error: " + e.getMessage() + "\n";
                e.printStackTrace();
            }

        }

        public static String encrypt(String seed, String cleartext)
        throws Exception {
            byte[] rawKey = getRawKey(seed.getBytes());
            byte[] result = encrypt(rawKey, cleartext.getBytes());
            return toHex(result) + "\n" + "Raw Key: " + String.valueOf(rawKey)
                    + "\n";
        }

        private static byte[] getRawKey(byte[] seed) throws Exception {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
            sr.setSeed(seed);
            kgen.init(128, sr); // 192 and 256 bits may not be available
            SecretKey skey = kgen.generateKey();
            byte[] raw = skey.getEncoded();
            return raw;
        }

        private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
                byte[] encrypted = cipher.doFinal(clear);
            return encrypted;
        }

        public static String toHex(String txt) {
            return toHex(txt.getBytes());
        }

        public static String fromHex(String hex) {
            return new String(toByte(hex));
        }

        public static byte[] toByte(String hexString) {
            int len = hexString.length() / 2;
            byte[] result = new byte[len];
            for (int i = 0; i < len; i++)
                result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
                        16).byteValue();
            return result;
        }

        public static String toHex(byte[] buf) {
            if (buf == null)
                return "";
            StringBuffer result = new StringBuffer(2 * buf.length);
            for (int i = 0; i < buf.length; i++) {
                appendHex(result, buf[i]);
            }
            return result.toString();
        }

         private final static String HEX = "0123456789ABCDEF";

        private static void appendHex(StringBuffer sb, byte b) {
            sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
        }
    }

Mein main.xml -Layout sieht so aus:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <TextView android:layout_width="fill_parent"
            android:layout_height="wrap_content" android:id="@+id/tvOutput" />
    </LinearLayout>

Ich kann keine Links oder Bilder veröffentlichen, da ich ein neuer Benutzer bin, aber Sie können die URLs für die folgenden beiden Bilder entschlüsseln, wenn Sie die Ergebnisse sehen möchten:

Was ich von 2.2 bekomme:

wct.vg/wt/droid/2.2.png

..und von 2.3.3:

wct.vg/wt/droid/2.3.3.png

War es hilfreich?

Lösung

Sie missbrauchen einen Pseudo -Zufallszahlengenerator und es ist Saatgut als Schlüsselableitungsfunktion - dies ist wirklich schlechter Stil. Der Pseudo -Zufallszahlengenerator "sha1prng" ist kein Standard wie AES - daher wissen Sie nie, welche Implementierung Sie erhalten. Siehe auch Gibt es einen SHA1PRNG -Standard??

Es macht mich kein Wunder, dass Sie verschiedene Ergebnisse erzielen. Ein deterministisches Ergebnis auf der Grundlage eines bestimmten Saatguts zu erhalten, ist keine Eigenschaft, die Sie von einer Pseudo -Zufallszahlfunktion erwarten können.

Wenn Sie einen kryptografischen Schlüssel aus einem Passwort abgeben möchten, verwenden Sie bitte a Schlüsselableitungsfunktion Wie PKCS #5 / PBKDF2. Eine Implementierung von PBKDF2 ist in der Bouncy Castle einbezogen.

Andere Tipps

Die Antwort ist in dieser Frage: Bouncycastle AES -Fehler beim Upgrade auf 1,45

Ich möchte allen danken, die zu dieser Frage beigetragen haben.

Hier ist, was ich letztendlich als Beispiel für die Verschlüsselung/Entschlüsselung eines Kennworts erstellt habe, das zwischen Android 2.2 und 2.3.3 konsistent erscheint.

Hauptaktivität:

package cc.ndl.testencryption;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class main extends Activity {
    TextView tvOutput;
    static String out;
    String TEST_STRING = "abcdefghijklmnopqrstuvwxyz";
    static String PASSKEY = "ThePasswordIsPassord";
    static byte[] SALT = { 1, 2, 4, 5 };
    static int ITERATIONS = 1979;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tvOutput = (TextView) findViewById(R.id.tvOutput);
    }

    @Override
    public void onResume() {
        super.onResume();
        out = "";
        runTest();
        tvOutput.setText(out);
    }

    private void runTest() {
        out = "Test string: " + TEST_STRING + "\n";
        out += "Passkey: " + PASSKEY + "\n";
        try {
            Crypto crypto = new Crypto(PASSKEY);
            String encryptedData = crypto.encrypt(TEST_STRING);
            out += "Encrypted: " + encryptedData + "\n";
            out += "Decrypted: " + crypto.decrypt(encryptedData);
        } catch (Exception e) {
            out += "Error: " + e.getMessage() + "\n";
            e.printStackTrace();
        }

    }
}

Hauptlayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView android:layout_width="fill_parent"
        android:layout_height="wrap_content" android:id="@+id/tvOutput" />
</LinearLayout>

Crypto -Objekt:

package cc.ndl.testencryption;

import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

public class Crypto {

    Cipher ecipher;
    Cipher dcipher;

    // 8-byte Salt
    byte[] salt = { 1, 2, 4, 5, 7, 8, 3, 6 };

    // Iteration count
    int iterationCount = 1979;

    Crypto(String passPhrase) {
        try {
            // Create the key
            KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt,
                    iterationCount);
            SecretKey key = SecretKeyFactory.getInstance(
                    "PBEWITHSHA256AND128BITAES-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) {
        }
    }

    public String encrypt(String str) {
        String rVal;
        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
            rVal = toHex(enc);
        } catch (Exception e) {
            rVal = "Error encrypting: " + e.getMessage();
        }
        return rVal;
    }

    public String decrypt(String str) {
        String rVal;
        try {
            // Decode base64 to get bytes
            byte[] dec = toByte(str);

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

            // Decode using utf-8
            rVal = new String(utf8, "UTF8");
        } catch (Exception e) {
            rVal = "Error encrypting: " + e.getMessage();
        }
        return rVal;
    }

    private static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
                    16).byteValue();
        return result;
    }

    private static String toHex(byte[] buf) {
        if (buf == null)
            return "";
        StringBuffer result = new StringBuffer(2 * buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }

    private final static String HEX = "0123456789ABCDEF";

    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top