在Android设计数据存储的加密方式时,开发者应该从以下几个方面进行考虑:
1、秘钥。加/解密使用的密钥不应写在代码中,建议由用户输入或由程序产生随机密钥。
2、密钥存储。密钥尽量不要存储在存储设备上,如文件或数据库中。在考虑用户使用方便的情况下(用户无须每次输入密码),可以将密钥分成几段乱序存储,并将密钥经过一些计算后作为加/解密的密钥,如SHA-1。
3、加密后数据处理。由于经加密算法加密之后的数据为二进制数据,因此在保存时,尤其是保存到数据库时,为防止出错,建议将数据转换成ASCII字符的形式。推荐使用base64算法。
可用于任何数据的通用加密模块,代码:
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
public class MyCrypto {
private byte[] cipher(byte[] data, byte[] seed, int mode)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException {
// 使用SHA-1 算法计算key
MessageDigest digester = MessageDigest.getInstance("SHA-1");
byte[] key = digester.digest(seed);
digester.reset();
// 使用SHA-1算法计算IV
byte[] iv = digester.digest(key);
SecretKeySpec spec = new SecretKeySpec(key, "AES");
IvParameterSpec iv1 = new IvParameterSpec(iv);
// 加密算法使用AES,CBC模式
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(mode, spec, iv1);
return c.doFinal(data);
}
private byte[] encrypt(byte[] data, byte[] seed)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException {
return cipher(data, seed, Cipher.ENCRYPT_MODE);
}
private byte[] decrypt(byte[] data, byte[] seed)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException {
return cipher(data, seed, Cipher.DECRYPT_MODE);
}
public String doEncrypt(byte[] data, byte[] seed)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException {
// 将加密结果以base64编码作为结果返回
return Base64.encodeToString(encrypt(data, seed), Base64.DEFAULT);
}
public String doDecrypt(String data, byte[] seed)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException {
// 解密时首先使用Base64编码方式解码
return new String(decrypt(Base64.decode(data, Base64.DEFAULT), seed));
}
}