在 sqlcipher 中使用密钥
Using secret key with sqlcipher
我正在使用 sqlcipher 存储来自我的应用程序的数据,但我遇到了问题,首先是生成密钥,然后是存储在密钥库中。
顺便说一句,需要没有用户交互,如 android docs
中所述
下面是我尝试生成密钥的方式,
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey key = keyGen.generateKey();
这里是我设置 sql 数据库的地方
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(databaseFile, "password_string", null);
所以问题,我如何使用密码字符串中的秘密?目前,我只能获取字节数组形式的秘密。
请在下面找到将 AES 用于 encrypt/decrypt 的实用程序。您可以使用密钥 encrypt/decrypt 您的密码。但是,我不建议这样做,因为您还必须存储您的密钥并且问题仍然存在,您如何安全地保存您的密钥?在这种情况下,通常的做法是使用散列函数:SHA-256、MD5...来散列您的密码并存储它。稍后,当您想要检查用户是否输入了正确的密码时,只需散列他们输入的任何内容并与您存储的值进行比较。
private static int BLOCKS = 128;
public static byte[] encryptAES(String seed, String cleartext)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal(cleartext.getBytes("UTF8"));
}
public static byte[] decryptAES(String seed, byte[] data) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return cipher.doFinal(data);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(BLOCKS, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
这是我生成随机准安全密码的方法:
fun generatePassword(): String{
val androidId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
val passPassphraseBase = "${BuildConfig.APPLICATION_ID}_$androidId:"
val random = SecureRandom()
val salt = ByteArray(32)
random.nextBytes(salt)
val passPhrase = passPassphraseBase.toByteArray() + salt
val pass = Base64.encodeToString(passPhrase, Base64.NO_WRAP)
return pass
}
你可以问我需要什么申请ID和Android ID。
只是为了增加我们密码的熵(可能还有长度)。
然后我将这个密码加密存储在共享首选项中。
我使用密钥库 RSA 算法加密所有共享首选项密钥和值。
毕竟我们最终生成了用非对称算法加密的对称加密密码。
所有这些都只是一个白盒密码学,我们将密钥和加密数据存储在一个地方。
如果我们为至少部分密码添加一些外部来源,我们可以提高安全性。
为此,我们可以使用:
- 来自我们后端的东西
- 用户输入或生物识别
我正在使用 sqlcipher 存储来自我的应用程序的数据,但我遇到了问题,首先是生成密钥,然后是存储在密钥库中。
顺便说一句,需要没有用户交互,如 android docs
中所述下面是我尝试生成密钥的方式,
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey key = keyGen.generateKey();
这里是我设置 sql 数据库的地方
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(databaseFile, "password_string", null);
所以问题,我如何使用密码字符串中的秘密?目前,我只能获取字节数组形式的秘密。
请在下面找到将 AES 用于 encrypt/decrypt 的实用程序。您可以使用密钥 encrypt/decrypt 您的密码。但是,我不建议这样做,因为您还必须存储您的密钥并且问题仍然存在,您如何安全地保存您的密钥?在这种情况下,通常的做法是使用散列函数:SHA-256、MD5...来散列您的密码并存储它。稍后,当您想要检查用户是否输入了正确的密码时,只需散列他们输入的任何内容并与您存储的值进行比较。
private static int BLOCKS = 128;
public static byte[] encryptAES(String seed, String cleartext)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal(cleartext.getBytes("UTF8"));
}
public static byte[] decryptAES(String seed, byte[] data) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return cipher.doFinal(data);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(BLOCKS, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
这是我生成随机准安全密码的方法:
fun generatePassword(): String{
val androidId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
val passPassphraseBase = "${BuildConfig.APPLICATION_ID}_$androidId:"
val random = SecureRandom()
val salt = ByteArray(32)
random.nextBytes(salt)
val passPhrase = passPassphraseBase.toByteArray() + salt
val pass = Base64.encodeToString(passPhrase, Base64.NO_WRAP)
return pass
}
你可以问我需要什么申请ID和Android ID。 只是为了增加我们密码的熵(可能还有长度)。
然后我将这个密码加密存储在共享首选项中。 我使用密钥库 RSA 算法加密所有共享首选项密钥和值。
毕竟我们最终生成了用非对称算法加密的对称加密密码。
所有这些都只是一个白盒密码学,我们将密钥和加密数据存储在一个地方。
如果我们为至少部分密码添加一些外部来源,我们可以提高安全性。 为此,我们可以使用:
- 来自我们后端的东西
- 用户输入或生物识别