【问题标题】:Can't create a KeyPair on Android无法在 Android 上创建密钥对
【发布时间】:2018-08-28 17:42:27
【问题描述】:

我正在使用 android 中的密钥,并试图生成一个公共/私有加密密钥对。不幸的是,我不断收到“KeyStoreException:无效的密钥 blob”。

我正在按照这里的说明进行操作:

https://developer.android.com/training/articles/keystore.html

尤其是标题为“生成新私钥”的部分,我觉得我的代码几乎是逐字复制的:

try {
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
    keyGen.initialize(
        new KeyGenParameterSpec.Builder(
            keyName,
            KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
           .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512).build()
    );

    KeyPair pair = keyGen.generateKeyPair();

} catch (NoSuchProviderException e) {
    e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
    e.printStackTrace();
}

keyName 的值来自用户输入,但我也尝试使用值"abc"

我得到的错误是:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.calebg.claimcreator, PID: 17389
        java.lang.IllegalStateException: Could not execute method for android:onClick
            at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
            at android.view.View.performClick(View.java:6579)
            at android.view.View.performClickInternal(View.java:6556)
            at android.view.View.access$3100(View.java:777)
            at android.view.View$PerformClick.run(View.java:25660)
            at android.os.Handler.handleCallback(Handler.java:819)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:164)
            at android.app.ActivityThread.main(ActivityThread.java:6656)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
        Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Method.invoke(Native Method)
            at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
            at android.view.View.performClick(View.java:6579) 
            at android.view.View.performClickInternal(View.java:6556) 
            at android.view.View.access$3100(View.java:777) 
            at android.view.View$PerformClick.run(View.java:25660) 
            at android.os.Handler.handleCallback(Handler.java:819) 
            at android.os.Handler.dispatchMessage(Handler.java:99) 
            at android.os.Looper.loop(Looper.java:164) 
            at android.app.ActivityThread.main(ActivityThread.java:6656) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823) 
        Caused by: java.security.ProviderException: Failed to load generated key pair from keystore
            at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.loadKeystoreKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:530)
            at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.generateKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:478)
            at java.security.KeyPairGenerator$Delegate.generateKeyPair(KeyPairGenerator.java:727)
            at com.example.calebg.claimcreator.CreateKeyActivity.createKey(CreateKeyActivity.java:76)
            at java.lang.reflect.Method.invoke(Native Method) 
            at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
            at android.view.View.performClick(View.java:6579) 
            at android.view.View.performClickInternal(View.java:6556) 
            at android.view.View.access$3100(View.java:777) 
            at android.view.View$PerformClick.run(View.java:25660) 
            at android.os.Handler.handleCallback(Handler.java:819) 
            at android.os.Handler.dispatchMessage(Handler.java:99) 
            at android.os.Looper.loop(Looper.java:164) 
            at android.app.ActivityThread.main(ActivityThread.java:6656) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823) 
        Caused by: java.security.UnrecoverableKeyException: Failed to obtain X.509 form of public key
            at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePublicKeyFromKeystore(AndroidKeyStoreProvider.java:239)
            at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(AndroidKeyStoreProvider.java:278)
            at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(AndroidKeyStoreProvider.java:289)
            at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.loadKeystoreKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:521)
            at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.generateKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:478) 
            at java.security.KeyPairGenerator$Delegate.generateKeyPair(KeyPairGenerator.java:727) 
            at com.example.calebg.claimcreator.CreateKeyActivity.createKey(CreateKeyActivity.java:76) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
            at android.view.View.performClick(View.java:6579) 
            at android.view.View.performClickInternal(View.java:6556) 
            at android.view.View.access$3100(View.java:777) 
            at android.view.View$PerformClick.run(View.java:25660) 
            at android.os.Handler.handleCallback(Handler.java:819) 
            at android.os.Handler.dispatchMessage(Handler.java:99) 
            at android.os.Looper.loop(Looper.java:164) 
            at android.app.ActivityThread.main(ActivityThread.java:6656) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823) 
        Caused by: android.security.KeyStoreException: Invalid key blob
            at android.security.KeyStore.getKeyStoreException(KeyStore.java:823)
            at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStorePublicKeyFromKeystore(AndroidKeyStoreProvider.java:241)
            at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(AndroidKeyStoreProvider.java:278) 
            at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(AndroidKeyStoreProvider.java:289) 
            at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.loadKeystoreKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:521) 
            at android.security.keystore.AndroidKeyStoreKeyPairGeneratorSpi.generateKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:478) 
            at java.security.KeyPairGenerator$Delegate.generateKeyPair(KeyPairGenerator.java:727) 
            at com.example.calebg.claimcreator.CreateKeyActivity.createKey(CreateKeyActivity.java:76) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
            at android.view.View.performClick(View.java:6579) 
            at android.view.View.performClickInternal(View.java:6556) 
            at android.view.View.access$3100(View.java:777) 
            at android.view.View$PerformClick.run(View.java:25660) 
            at android.os.Handler.handleCallback(Handler.java:819) 
            at android.os.Handler.dispatchMessage(Handler.java:99) 
            at android.os.Looper.loop(Looper.java:164) 
            at android.app.ActivityThread.main(ActivityThread.java:6656) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823) 

我正在使用 Android Studio 3.0.1、minSdkVersion 23、targetSdkVersion 26,并且我正在“Nexus 6 API P”虚拟设备上进行测试。

我发现的唯一其他相关的 stackoverflow 问题(也是唯一的谷歌结果)看起来很有帮助:

android.security.KeyStoreException: Invalid key blob

但是我不清楚如何将答案应用于我的情况,并且我不相信在我的情况下这是一个正确的解决方案(当我刚刚初始化它时,如何锁定/未初始化密钥库?如何捕捉出现异常并再次尝试解决此问题?)。

谁能指出我做错了什么?

【问题讨论】:

    标签: java android key-pair


    【解决方案1】:

    你可以试试下面的代码,它是基于 AES-128 加密算法的。

    public void RandomKey(View view)
    {
    
        int[] Keys = new int[16];
        String keyString ="";
    
    
        //reset the secret key into null
        Secret_Key="";
        SecretKey.setText(Secret_Key);
    
        try
        {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            keyGen.init(128); // 128 bit
            javax.crypto.SecretKey secretKey = keyGen.generateKey(); //generate secret key
            SKey= secretKey.getEncoded();
            // to display
            for (int i = 0; i < 16; i++)
            {
    
                Keys[i] = SKey[i] & 0x000000FF;//convert byte to integer
                keyString = Integer.toHexString(Keys[i]);
    
                if (keyString.length() < 2)
                {
                    keyString="0"+keyString;
                }
                //Log.d("keys are"," "+i+keyString);
                Secret_Key = Secret_Key + " " + keyString;
            }
    
            SecretKey.setAllCaps(true);
            SecretKey.setText(Secret_Key);
        }
    

    更完整的程序可以参考这个: https://github.com/aliakbarpa/AES-128_for_Android

    【讨论】:

    • 感谢 AliAP,它给了我一个 SecretKey,但不是 KeyPair。另外,我尝试遵循 android 指南的原因是它谈到了将密钥库存储在手机内不易提取的位置。我想知道我需要做些什么来确保 Java 生成的密钥以这种方式存储?
    【解决方案2】:

    我在一个真实的设备上试过这个,它可以工作。不知道为什么,但由于某种原因,Android 模拟器无法根据 Android 文档创建密钥。

    【讨论】:

    【解决方案3】:

    我在尝试在 Android-P 上运行我的应用时遇到了同样的问题,我认为他们对密钥库 See the preview 进行了一些更改,我想知道您的物理设备是否运行 Android P?

    【讨论】:

    • 不,不是,但虚拟设备(不工作)是
    • 我们设法让它在运行 Android P 的实际设备上运行,看来问题来自模拟器。
    • 是的,这也是我得出的结论。
    猜你喜欢
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 2018-08-19
    • 1970-01-01
    • 1970-01-01
    • 2022-07-28
    相关资源
    最近更新 更多