安全 加密解密
项目中的经验和用法
在实际开发中,不是太重要的数据用一种加密方式感觉就可以了。但是比较重要的数据建议用多种加密方式结合的方式,比如我用的RSA+AES加密。他主要解决了两个问题:
1.RSA加解密速度慢,不适合大量数据文件加密
2.AES加密速度很快,但是安全性没有RSA加密方式的安全。
其主要思想就是服务端生成公钥私钥,并提供接口将公钥给android端,android端生成AES秘钥,并用AES秘钥对大量数据进行加密(解决RSA加解密速度慢的问题),然后用调用接口拿到的RSA公钥对自己生成AES秘钥进行加密,客户端将得到的秘钥和通过AES加密的数据发送给服务器。(秘钥可以放在请求头中,数据放在请求体中,这个随意了)。服务拿到你的秘钥和数据后,用私钥加密得到AES秘钥,再通过秘钥得到发送的数据就好了。
[详细请看](https://juejin.im/entry/59b09f4c5188251240635da3)
如果是Jetpack 框架的话就直接用,但是要求minSDK >=23
implementation ‘androidx.security:security-crypto:1.0.0-rc01’
String masterKeyAlias = null;
try {
masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
"secret_shared_prefs",
masterKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
// use the shared preferences and editor as you normally would
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("key", "value").apply();// 存
editor.getString("key",null);//取
利用KeyStore来进行密码和token的加密解密
public class EncryUtils {
static EncryUtils encryUtilsInstance;
KeyStore keyStore;
public static EncryUtils getInstance() {
synchronized (EncryUtils.class) {
if (null == encryUtilsInstance) {
encryUtilsInstance = new EncryUtils();
}
}
return encryUtilsInstance;
}
private EncryUtils() {
}
private void initKeyStore(String alias){
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
}
catch(Exception e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
createNewKeys(alias);
}
}
private void createNewKeys(String alias){
if(!"".equals(alias)){
try {
// Create new key if needed
if (!keyStore.containsAlias(alias)) {
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
end.add(Calendar.YEAR, 1);
KeyPairGeneratorSpec spec = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
spec = new KeyPairGeneratorSpec.Builder(Application.getApplication())
.setAlias(alias)
.setSubject(new X500Principal("CN=Sample Name, O=Android Authority"))
.setSerialNumber(BigInteger.ONE)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.build();
}
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
generator.initialize(spec);
}
KeyPair keyPair = generator.generateKeyPair();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 加密方法
* @param needEncryptWord 需要加密的字符串
* @param alias 加密秘钥
* @return
*/
public String encryptString(String needEncryptWord, String alias) {
if(!"".equals(alias)&&!"".equals(needEncryptWord)){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
initKeyStore(alias);
}
String encryptStr="";
byte [] vals=null;
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
// RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();
if(needEncryptWord.isEmpty()) {
// Toast.makeText(this, "Enter text in the 'Initial Text' widget", Toast.LENGTH_LONG).show();
return encryptStr;
}
Cipher inCipher;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
}else {
//若加密慢则改用上面的代码
inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
}
// inCipher.init(Cipher.ENCRYPT_MODE, publicKey);
inCipher.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, inCipher);
cipherOutputStream.write(needEncryptWord.getBytes("UTF-8"));
cipherOutputStream.close();
vals = outputStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return Base64.encodeToString(vals, Base64.DEFAULT);
}
return "";
}
public String decryptString(String needDecryptWord, String alias) {
if(!"".equals(alias)&&!"".equals(needDecryptWord)){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
initKeyStore(alias);
}
String decryptStr="";
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
// RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();
// Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// output.init(Cipher.DECRYPT_MODE, privateKey);
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(needDecryptWord, Base64.DEFAULT)), output);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
decryptStr = new String(bytes, 0, bytes.length, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return decryptStr;
}
return "";
}
}