如何解决如何在Android API 22上创建AES密钥并通过私钥对其进行加密?
我知道有关此主题的文章很多,但是加密技术的安全性每年都在变化,因此我想确保我的应用程序是安全的。 我想创建一个 AES密钥,该密钥将对我的数据库(SQLCipher)进行加密。然后,该密钥将由 SharedPreferences (在Api23中生成的EncryptedSharedPreferences)中生成的公钥和保留进行加密。 我知道现在是更好的选择,但所需的最低SDK为23(我的最低为22)... 所以我尽力了。 我编写的代码是否符合当今的安全要求?
生成密钥对
KeyStore keyStore = KeyStore.getInstance(Constants.AndroidKeyStore);
keyStore.load(null);
if (keyStore.getKey(Constants.KEY_ALIAS,null) == null) {
Calendar notBefore = Calendar.getInstance();
Calendar notAfter = Calendar.getInstance();
notAfter.add(Calendar.YEAR,1);
KeyPairGeneratorSpec spec = null;
spec = new KeyPairGeneratorSpec.Builder(context)
.setAlias("QWEKey")
.setKeySize(2048)
.setSubject(new X500Principal("CN=MyCompany"))
.setSerialNumber(BigInteger.ONE)
.setStartDate(notBefore.getTime())
.setEndDate(notAfter.getTime())
.build();
KeyPairGenerator generator = null;
try {
generator = KeyPairGenerator.getInstance("RSA","AndroidKeyStore");
generator.initialize(spec);
} catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
generator.generateKeyPair();
}
return keyStore;
现在,创建 AES密钥:
// check if encrypted AES key is in SharedPreferences
String encryptedKeyB64 = sharedPreferences.getString(Constants.ENCRYPTED_KEY,null);
if (encryptedKeyB64 == null || encryptedKeyB64.equals("")) {
// if not - create new AES key
byte[] key = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(key);
byte[] encryptedKey = new byte[0];
try {
// encrypt AES key (method below)
encryptedKey = rsaEncrypt(mKeyStore,key);
Log.d(TAG,"getEncryptedKeyB64: encryptedKey: " + encryptedKey.toString());
} catch (Exception e) {
e.printStackTrace();
}
// save encrypted key in sharedPreferences
encryptedKeyB64 = Base64.encodeToString(encryptedKey,Base64.DEFAULT);
Log.d(TAG,"getEncryptedKeyB64: encryptedKey64: (NEW) " + encryptedKeyB64);
SharedPreferences.Editor edit2 = sharedPreferences.edit();
edit2.putString(Constants.ENCRYPTED_KEY,encryptedKeyB64);
edit2.apply();
}
Log.d(TAG,"getEncryptedKeyB64: lenght: " + encryptedKeyB64.length());
return encryptedKeyB64;
//(编辑)现在我正在使用:
new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
EncryptedSharedPreferences
.create(
context,ENCRYPTED_KEY,masterKey,EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
方法 rsaEncrypt():
public static byte[] rsaEncrypt(KeyStore mKeyStore,byte[] secret) throws Exception{
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) mKeyStore.getEntry(Constants.KEY_ALIAS,null);
// Encrypt the text
Cipher inputCipher = Cipher.getInstance(Constants.RSA_MODE,"AndroidOpenSSL");
inputCipher.init(Cipher.ENCRYPT_MODE,privateKeyEntry.getCertificate().getPublicKey());
Log.d(TAG,"rsaEncrypt: Certificates: " + privateKeyEntry.getCertificate().getType()); // X.509
Log.d(TAG,"rsaEncrypt: Certificates: " + privateKeyEntry.getCertificate().getPublicKey().toString());
privateKeyEntry.getCertificate().verify(privateKeyEntry.getCertificate().getPublicKey());
Log.d(TAG,"rsaEncrypt: Certificates: " + privateKeyEntry.getPrivateKey().toString());
Log.d(TAG,"rsaEncrypt: Certificates: " + Arrays.toString(privateKeyEntry.getCertificateChain()));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream,inputCipher);
cipherOutputStream.write(secret);
cipherOutputStream.close();
byte[] vals = outputStream.toByteArray();
Log.d(TAG,"rsaEncrypt: vals length: " + vals.length);
return vals;
}
现在用于解密AES密钥和加密RoomDatabase的代码:
encrypted = Base64.decode(encryptedKeyB64,Base64.DEFAULT)
public static byte[] rsaDecrypt(KeyStore mKeyStore,byte[] encrypted) throws Exception {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) mKeyStore.getEntry(Constants.KEY_ALIAS,null);
Cipher output = Cipher.getInstance(Constants.RSA_MODE,"AndroidOpenSSL");
output.init(Cipher.DECRYPT_MODE,privateKeyEntry.getPrivateKey());
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(encrypted),output);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
Log.d(TAG,"rsaDecrypt: values lenght: " + values.size());
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
return bytes;
}
最后创建加密的数据库:
final SupportFactory factory = new SupportFactory(decryptedKey);
return Room.databaseBuilder(context.getApplicationContext(),ProductsDatabase.class,"ProductsDatabase")
.addCallback(sRoomDatabaseCallback)
.fallbackToDestructiveMigration()
.openHelperFactory(factory)
.build();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。