在Android密钥库中存储hmac密钥

时间:2015-11-28 20:54:06

标签: java android cryptography keystore hmac

我使用以下代码创建一个hmac键并将其作为字符串返回。

scala> def foo(request: Request) = request match {
     |  case (_: One.type | _: Two.type | _: Three.type | _: Four.type ) => ???
     | }

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

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();
    }

无论hmacKey采用何种格式,我都会收到错误:字符串/字节或KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); KeyStore.ProtectionParameter param = new KeyStore.PasswordProtection("test".toCharArray()); keyStore.setEntry("key1",hmacKey,param); 。以下是错误: 如果传递密钥javax.crypto.SecretKey

hmacKey

在我传递字符串或字节数组的情况下也一样。

如果我将参数强制转换为Wrong 2nd argument type. Found: 'java.security.Key', required: 'java.security.KeyStore.Entry' ,它仍然无效。

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

1 个答案:

答案 0 :(得分:3)

创建Android密钥库是为了允许您在应用程序代码中使用非对称密钥和对称密钥 。按照规定in the training material

  

密钥材料永远不会进入申请流程。当应用程序使用Android密钥库密钥执行加密操作时,在幕后明文,密文和要签名或验证的消息被馈送到执行加密操作的系统进程。如果应用程序的进程受到攻击,攻击者可能能够使用应用程序的密钥,但无法提取其密钥材料(例如,要在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