如何在不同的Android应用之间共享密钥(敏感信息)?

时间:2019-04-02 16:10:17

标签: android sharedpreferences keychain android-keystore

如何在不同的Android应用之间共享密钥(敏感信息)?

我尝试将蓝牙设备连接到多个android应用程序。我想对所有应用程序(AES256)使用相同的长期密钥(LTK),并从每个应用程序中的该LTK派生会话密钥,以建立安全的通信隧道。我在私有模式下使用共享首选项,该模式允许具有相同捆绑软件ID的应用程序访问相同的数据,但是不幸的是,共享首选项不够安全,并且该数据也可用于其他根访问级别请求。我正在使用Android密钥库来存储LTK(附加了部分代码实现),但是我需要针对以下两种情况改进解决方案: 1.具有相同捆绑软件ID的应用。 和 2.使用相同的SDK使用具有不同捆绑软件ID的应用。

我正在寻找一种安全的方法来将LTK存储在那些特定应用可以访问的android设备中。

//-----
private boolean saveLTK(byte[] userKey)
{
        try
        {
            prefEncryptCipher.init(Cipher.ENCRYPT_MODE, preferenceKey);
            SharedPreferences settings = context.createPackageContext(packageNameSpace,
                    Context.MODE_PRIVATE).getSharedPreferences(KEY_PREFS_NAME, Activity.MODE_PRIVATE);
            SharedPreferences.Editor editor = settings.edit();
            byte[] encUsrKey = prefEncryptCipher.doFinal(userKey);
            ByteBuffer byteBuffer = ByteBuffer.allocate(4 + prefEncryptCipher.getIV().length + encUsrKey.length);
            byteBuffer.putInt(prefEncryptCipher.getIV().length);
            byteBuffer.put(prefEncryptCipher.getIV());
            byteBuffer.put(encUsrKey);
            byte[] encUsrKeyMessage = byteBuffer.array();
            editor.putString(encodeToString(address.getBytes(), DEFAULT), encodeToString(encUsrKeyMessage, DEFAULT));
            return editor.commit();
        }
        catch (PackageManager.NameNotFoundException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e)
        {
            e.printStackTrace();
        }
        return false;
}

//-----
private boolean loadLTK(byte[] userKey)
{
        try
        {
            SharedPreferences settings = context.createPackageContext(packageNameSpace,
                    Context.MODE_PRIVATE).getSharedPreferences(KEY_PREFS_NAME, Activity.MODE_PRIVATE);
            String userKeyStr = settings.getString(encodeToString(address.getBytes(), DEFAULT), null);
            if (userKeyStr != null)
            {
                byte[] decUsrKey = decode(userKeyStr, DEFAULT);
                ByteBuffer byteBuffer = ByteBuffer.wrap(decUsrKey);
                int ivLength = byteBuffer.getInt();
                byte[] iv = new byte[ivLength];
                byteBuffer.get(iv);
                byte[] decUsrKeyText = new byte[byteBuffer.remaining()];
                byteBuffer.get(decUsrKeyText);
                prefDecryptCipher.init(Cipher.DECRYPT_MODE, preferenceKey, new GCMParameterSpec(128, iv));
                byte[] userKeyStrBytes = prefDecryptCipher.doFinal(decUsrKeyText);
                if (userKeyStrBytes.length == userKey.length)
                {
                    System.arraycopy(userKeyStrBytes, 0, userKey, 0, userKeyStrBytes.length);
                    return true;
                }
            }
        }
        catch (PackageManager.NameNotFoundException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException | InvalidKeyException e)
        {
            e.printStackTrace();
        }
        return false;
}

现在是否存在类似于可用于Android的Apple钥匙串的解决方案? (我认为Android密钥链的工作方式有所不同。我更喜欢Apple密钥链之类的解决方案,以将可信赖的安全性和挑战转移到操作系统级别。) 或者,我应该使用共享首选项并自己保护它吗?在这方面,如果我应该使用Android密钥库来生成和存储LTK,那么Android密钥库是否允许我从具有不同包ID的不同应用程序访问同一密钥?请描述不同的选项和限制。

1 个答案:

答案 0 :(得分:0)

通常,什么是最安全,最便捷的方式来存储配对信息和密钥,以及在Android中的不同应用之间共享配对信息和密钥?