【问题标题】:Storing a hmac key in Android keystore在 Android 密钥库中存储 hmac 密钥
【发布时间】:2015-11-28 20:54:05
【问题描述】:

我正在使用下面的代码创建一个 hmac 密钥并将其作为字符串返回。

KeyGenerator keyGen = null;
    try {
        keyGen = KeyGenerator.getInstance("HmacSHA256");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    SecretKey key = keyGen.generateKey();
    byte[] encoded = key.getEncoded();
    String s=Base64.encodeToString(encoded, Base64.DEFAULT);
    Log.i("Hmac key before encrypt",s);

    try {
        KeyStore keystore = KeyStore.getInstance("AndroidKeyStore");
        keystore.load(null, null);
        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keystore.getEntry("temp", null);
        RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] cipherBytes = cipher.doFinal(encoded);

        return Base64.encodeToString(cipherBytes,Base64.DEFAULT);


    } catch (UnrecoverableEntryException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

如何将其存储在 android 密钥库中?我试过使用下面的代码:

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

        KeyStore.ProtectionParameter param = new KeyStore.PasswordProtection("test".toCharArray());
        keyStore.setEntry("key1",hmacKey,param);

无论 hmacKey 采用什么格式,我都会收到错误消息:String/Bytes 或 javax.crypto.SecretKey。以下是错误: 如果传递 Key hmacKey:

Wrong 2nd argument type. Found: 'java.security.Key', required: 'java.security.KeyStore.Entry'

在我传递字符串或字节数组的情况下也是如此。

如果我将参数类型转换为java.security.KeyStore.Entry,它仍然不起作用。

这是正确的做法吗?任何人都可以提供有关如何使用别名将 HMAC 密钥存储在密钥库中的指针。如何将hmack密钥转换为java.security.KeyStore.Entry格式?

【问题讨论】:

  • 抱歉含糊不清。编辑了问题
  • 你不能只存储上面生成的key 吗?我在这个问题中看到了很多绒毛。这似乎不是 MCSE。
  • 不,不能这样存储。我目前正在使用共享首选项来存储此密钥。不确定那里的安全方面是否存在,这就是我想将它存储在密钥库中的原因。代码的第一部分工作得很好,我可以创建一个 hmack 密钥并返回它。它是我试图将其存储在 android 密钥库中的部分,其别名导致问题。

标签: java android cryptography keystore hmac


【解决方案1】:

Android 密钥库的创建允许您在应用程序代码外部使用非对称密钥和对称密钥。如指定in the training material:

密钥材料永远不会进入申请流程。当应用程序使用 Android Keystore 密钥执行加密操作时,在后台将要签名或验证的明文、密文和消息馈送到执行加密操作的系统进程。如果应用程序的进程受到破坏,攻击者可能能够使用应用程序的密钥,但无法提取其密钥材料(例如,在 Android 设备之外使用)。

因此,在应用程序代码内部(因此在密钥存储之外)生成密钥的想法不是一个好主意。 API for the KeyGenParameterSpec class 中为 HMAC 密钥定义了如何在密钥库中生成密钥:

KeyGenerator keyGenerator = KeyGenerator.getInstance(
         KeyProperties.KEY_ALGORITHM_HMAC_SHA256, "AndroidKeyStore");
keyGenerator.initialize(
         new KeyGenParameterSpec.Builder("key2", KeyProperties.PURPOSE_SIGN).build());
SecretKey key = keyGenerator.generateKey();
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
...

// The key can also be obtained from the Android Keystore any time as follows:
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
key = (SecretKey) keyStore.getKey("key2", null);

其他按键类型可以找到in the KeyProperties class

【讨论】:

  • 问题是我正在从服务器接收加密的 hmack 密钥,因此我只需要将它存储在设备上最安全的选项中。稍后我将提取它,使用私钥解密并根据需要使用它。我相信密钥库会比共享首选项更安全,因此想用它来存储密钥。这就是我卡住的地方,所以我现在使用共享偏好。关于如何将外部生成的 hmac 保存在密钥库中的任何想法?还要感谢 Maarten 不断对此进行调查。
  • 用商店中的密钥包装该密钥怎么样?
  • 不知道该怎么做,如果你的意思是把它转换成一个密钥库条目,那是行不通的。同样在任何时候,我的密钥库中都只会有一个公钥/私钥对。除此之外,我还想存储 hmac 密钥。
  • @Sid 您应该做的是从服务器获取 HMAC 密钥并将其导入 Android KeyStore。不要费心自己加密它,Android KeyStore 会比你更好地保护它。有关如何将 HMAC 密钥导入 Android KeyStore 以及如何使用它的示例,请参阅 KeyProtection 文档 (developer.android.com/reference/android/security/keystore/…)。
  • 请注意:包装密钥是一种可从 Java cipher 类 (Cipher.WRAP) 获得的加密操作。
猜你喜欢
  • 2015-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多