gpt4 book ai didi

java - 是否可以生成 64 字节(256 位) key 并使用 AndroidKeyStore 存储/检索它?

转载 作者:行者123 更新时间:2023-12-02 01:43:08 25 4
gpt4 key购买 nike

在我的 Android 应用程序中,我需要一种方法来加密存储在本地数据库中的数据。我选择 Realm DB 是因为它提供了与加密的无缝集成。我只需要在初始化 Realm 实例时传递一个 key 。该 key 的大小必须为 64 字节。

出于安全原因,我发现存储此 key 的最佳方法是在 AndroidKeyStore 中。我正在努力寻找一种方法来生成具有该大小的 key (使用任何算法),并将其放入 64 字节数组中。我试图保留 API 19 的 minSdk,但我相信如果需要的话我可以将其提高到 23(这两个版本之间对 AndroidKeyStore 进行了许多更改)。

有人有想法吗?这是我的代码:

类加密.java

private static KeyStore ks = null;
private static String ALIAS = "com.oi.pap";

public static byte[] loadkey(Context context) {

byte[] content = new byte[64];
try {
if (ks == null) {
createNewKeys(context);
}

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

content= ks.getCertificate(ALIAS).getEncoded(); //<----- HERE, I GET SIZE GREATER THAN 64
Log.e(TAG, "original key :" + Arrays.toString(content));
} catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
content = Arrays.copyOfRange(content, 0, 64); //<---- I would like to remove this part.
return content;
}

private static void createNewKeys(Context context) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {

ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
try {
// Create new key if needed
if (!ks.containsAlias(ALIAS)) {
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
end.add(Calendar.YEAR, 1);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
.setAlias(ALIAS)
.setSubject(new X500Principal("CN=PapRealmKey, O=oipap"))
.setSerialNumber(BigInteger.ONE)
.setStartDate(start.getTime())
.setEndDate(end.getTime())
.setKeySize(256)
.setKeyType(KeyProperties.KEY_ALGORITHM_EC)
.build();
KeyPairGenerator generator = KeyPairGenerator
.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
generator.initialize(spec);

KeyPair keyPair = generator.generateKeyPair();
Log.e(TAG, "generated key :" + Arrays.toString(keyPair.getPrivate().getEncoded()));

}
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}

最佳答案

AndroidKeyStore 的目的是将敏感的 key Material 从您的应用程序、操作系统中移出,转移到永远不会泄露或受到损害的安全硬件中。因此,根据设计,如果您在 AndroidKeyStore 中创建 key ,则永远无法取出 key Material 。

在这种情况下,Realm DB 需要 key Material ,因此您无法为其提供 AndroidKeyStore key 。另外,Realm 想要的是两个 AES key ,而不是您尝试生成的 EC key 。

生成您需要的 key Material 的正确方法是:

byte[] dbKey = new byte[64];
Random random = new SecureRandom();
random.nextBytes(dbKey);
// Pass dbKey to Realm DB...
Arrays.fill(dbKey, 0); // Wipe key after use.

只有 64 个随机字节。但是,您需要将这些字节存储在某处。您可以使用 AndroidKeyStore 创建 AES key 并使用它来加密 dbKey。像这样的东西:

KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(
new KeyGenParameterSpec.Builder("dbKeyWrappingKey",
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
SecretKey key = keyGenerator.generateKey();

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = cipher.getIV();
byte[] encryptedDbKey = cipher.doFinal(dbKey);

您需要将 ivencryptedDbKey 保存在某处(不是数据库中!),以便可以恢复 dbKey。然后你可以用以下命令解密:

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
key = (SecretKey) keyStore.getKey("dbKeyWrappingKey", null);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv));
byte[] dbKey = cipher.doFinal(encryptedDbKey);
// Pass dbKey to Realm DB and then wipe it.

但是,尽管如此......我认为您不应该这样做。我认为这实际上并没有给你带来 Android 默认情况下没有给你的任何安全性。如果攻击者尝试转储包含数据库的设备存储,他将一无所获,因为 Android 无论如何都会加密所有存储。如果攻击者可以 root 设备,他就可以像您的应用一样运行代码,并使用它来解密 dbKey,就像您的应用一样。

如果您在 dbKeyWrappingKey 上添加一些额外的保护,AndroidKeyStore 可能真正增加值(value)。例如,如果您将其设置为要求在五分钟内进行用户身份验证,则只有当用户在输入他们的信息时才可以使用 dbWrappingKey 来解密 dbKey 。 PIN/图案/密码或触摸指纹扫描仪。请注意,这仅在用户拥有 PIN/图案/密码时才有效,但如果他们没有,那么您的数据库对任何拿起电话的人都是开放的。

请参阅 KeyGenParameterSpec,了解您可以执行的所有操作来限制 dbKeyWrappingKey 的使用方式。

关于java - 是否可以生成 64 字节(256 位) key 并使用 AndroidKeyStore 存储/检索它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54148214/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com