简体   繁体   English

Android字符串加密/解密

[英]Android String Encryption/Decryption

I want to encrypt and decrypt a String from an EditText using AndroidKeyStore . 我想使用AndroidKeyStoreEditText加密和解密String My problem is that at the decrypt process is get a BadPaddingException . 我的问题是在解密过程中得到一个BadPaddingException

Key generator code: 密钥生成器代码:

        KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

        KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT).
                setBlockModes(KeyProperties.BLOCK_MODE_GCM).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE).build();

        keyGenerator.init(keyGenParameterSpec);
        keyGenerator.generateKey();

Encryption code: 加密代码:

            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);

            KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null);
            SecretKey secretKey = secretKeyEntry.getSecretKey();

            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            cipherIV = cipher.getIV();

            plainText.setText(new String(cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));

Decryption code: 解密代码:

            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);

            final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null);
            final SecretKey secretKey = secretKeyEntry.getSecretKey();

            final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            final GCMParameterSpec spec = new GCMParameterSpec(128, cipherIV);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);

            byte[] decrypted = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
            plainText.setText(new String(decrypted, StandardCharsets.UTF_8));
byte[] decrypted = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));

This line may not work well because of the call of getBytes(StandardCharsets.UTF_8) . 由于getBytes(StandardCharsets.UTF_8)的调用,此行可能无法正常工作。 If your EditText is hex representation, try to convert it to string and then invoke getBytes() . 如果您的EditText是十六进制表示,请尝试将其转换为字符串,然后调用getBytes() Eg 例如

public static byte[] convertHexStringToByteArray(String hexString) {

    int l = hexString.length();
    byte[] data = new byte[l/2];
    for (int i = 0; i < l; i += 2) {
        data[i/2] = (byte)((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i+1), 16));
    }

    return data;
}

This line is in error: 这条线有误:

plainText.setText(new String(cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));

If we break it apart, we have something like 如果我们将它分开,我们会有类似的东西

byte [] cipherBytes = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
plainText.setText(new String(cipherBytes, StandardCharsets.UTF_8);

The problem is that cipherBytes is a sequence of arbitrary bytes rather than the characters of a string. 问题是cipherBytes是一个任意字节序列而不是字符串的字符。 The String constructor will silently replace invalid characters with something else, a process which corrupts the data. String构造函数将使用其他东西静默替换无效字符,这是一个破坏数据的进程。

If you want to display the cipher bytes or otherwise send it to a character oriented channel you must encode it. 如果要显示密码字节或以其他方式将其发送到面向字符的通道,则必须对其进行编码 Typically encodings are base64 or hex. 通常编码是base64或hex。 To decrypt the String you must then decode it to bytes first and then decrypt it. 要解密字符串,您必须先将其解码为字节然后解密。

Example: 例:

byte [] cipherBytes = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
plainText.setText(Base64.encodeToString(cipherBytes, Base64.DEFAULT));

And on decrypt: 在解密时:

byte[] cipherBytes = Base64.decode(plainText.getText().toString(), Base64.DEFAULT);
byte[] decrypted = cipher.doFinal(cipherBytes);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM