isInsideSecureHardware () возвращает false для Android <= 7.1.1. Как заставить ключ храниться внутри оборудования? - PullRequest
1 голос
/ 17 июня 2020

Я работаю над использованием KeyStore для безопасного хранения секретов моего приложения в Android. Однако я обнаружил, что для устройств с Android 7.1.1 и ниже хранимый ключ, использующий KeyStore, не имеет «аппаратной поддержки?», То есть всякий раз, когда я вызываю метод isInsideSecureHardware () для KeyInfo, он всегда будет возвращать мне » ложный'.

Насколько я тестировал, это происходит, даже если устройство имеет «Тип хранилища = Аппаратное обеспечение» в Настройки-> Безопасность-> Хранилище учетных данных-> Тип хранилища. Но это не относится к Android 7.1.2 и выше, которые всегда возвращают мне «истину» для isInsideSecureHardware (), если тип хранилища учетных данных имеет аппаратную поддержку; никогда не пробовал с другими типами.

  1. Есть ли способ принудительно сохранить ключ внутри защищенного оборудования для Android 7.1.1 до 4.3 (насколько я понимаю, это где HSM в Представлено хранилище ключей; пожалуйста, поправьте меня, если я ошибаюсь)?

  2. Может ли кто-нибудь прояснить, что произойдет, если сохраненный ключ не находится внутри защищенного оборудования; где хранится ключ? насколько это безопасно? Чтобы упростить задачу, в чем разница между isInsideSecureHardware == true и isInsideSecureHardware == false?

Вот фрагмент моего кода для ввода ключа и проверки KeyInfo (да, я ' m с запросом до Android 4.3 ... пожалуйста, не обращайте внимания на проверку версии в коде):

private void injectKey(Context context, String keyName){
    KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        Calendar start = Calendar.getInstance();
        Calendar end = Calendar.getInstance();
        end.add(Calendar.YEAR, 1);

        keyGenerator.init(new KeyGenParameterSpec.Builder(keyName, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                .setRandomizedEncryptionRequired(true)
                .setKeyValidityStart(start.getTime())
                .setKeyValidityEnd(end.getTime())
                //.setUserAuthenticationRequired(true) //need PIN to get key
                //.setUserAuthenticationValidityDurationSeconds(86400) //1-day time can use key from entering PIN
                //.setUnlockedDeviceRequired(true) API level 28
                //.setIsStrongBoxBacked(true) API level 28
                .build()
        );
    }

    SecretKey secretKey = keyGenerator.generateKey();

    //check key info
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        SecretKeyFactory factory = SecretKeyFactory.getInstance(secretKey.getAlgorithm(), "AndroidKeyStore");
        KeyInfo keyInfo;

        try {
            keyInfo = (KeyInfo) factory.getKeySpec(secretKey, KeyInfo.class);
            boolean insideHW = keyInfo.isInsideSecureHardware();
            boolean authReq = keyInfo.isUserAuthenticationRequired();
            boolean authHW = keyInfo.isUserAuthenticationRequirementEnforcedBySecureHardware();
            String[] blockModes = keyInfo.getBlockModes();
            String[] digests = keyInfo.getDigests();
            String[] encryptionPaddings = keyInfo.getEncryptionPaddings();
            int keySize = keyInfo.getKeySize();
            Date keyValidityStart = keyInfo.getKeyValidityStart();
            Date keyEndValid = keyInfo.getKeyValidityForConsumptionEnd();
            String keyAlias = keyInfo.getKeystoreAlias();
            int keyPurpose = keyInfo.getPurposes();
            String [] signaturePaddings = keyInfo.getSignaturePaddings();
            int authType = keyInfo.getUserAuthenticationValidityDurationSeconds();

            MainActivity.showMessage(context, "Key Info",
                    "inside HW = " + insideHW + "\n" +
                            "auth Req = " + authReq + "\n" +
                            "auth HW = " + authHW + "\n" +
                            "keySize = " + keySize + "\n" +
                            "keyValidityStart = " + keyValidityStart + "\n" +
                            "keyEndValid = " + keyEndValid + "\n" +
                            "keyAlias = " + keyAlias + "\n" +
                            "keyPurpose = " + keyPurpose + "\n" +
                            "authType = " + authType + "\n");

            String checkKeyInfo = "";
        } catch (InvalidKeySpecException e) {
            String checkKeyInfo = "";
        }
    }
}
...