ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

从AndroidKeystore加载私钥时出现问题

2019-07-27 18:26:49  阅读:198  来源: 互联网

标签:android


Android提供了一个API,用于为加密操作生成密钥,并在Androids Systemkeystore中存储/加载它们.

我按照KeyGenParameterSpec类的JavaDocs中的Example进行操作.密钥的生成,存储和加载工作.但是如果我尝试使用密钥,则密码对象的init()调用将失败.我调试了一下,我可以看到,加载的Key的类型为“android.security.keystore.AndroidKeyStoreSecretKey”.此实现可防止密钥的byte []被暴露.我出于安全原因理解这一点,但如果我想使用密钥,我必须获得关键内容.所以,我必须做错事.也许,在Android中使用加密操作还有另一种方法吗?或者Key的加载代码是错误的?

这是代码:

KeyGenerator keyGenerator = KeyGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder("demo-alias", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT);
builder.setKeySize(256);
builder.setBlockModes(KeyProperties.BLOCK_MODE_CBC);
builder.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);
keyGenerator.init(builder.build());

// this key will work with a CipherObject ...
SecretKey key = keyGenerator.generateKey();

// Load the key from the Keystore
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);

// This key will not work with the Cipher Object
SecretKey notWorkingKey = (SecretKey) keyStore.getKey("demo-alias", null);

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// That call fails
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(new byte[]{87, 99, -94, 23, -17, 26, 84, -117, 59, -59, 25, -88, -66, 86, -42, 78}));

byte[] crypted = cipher.doFinal("testdata".getBytes());

密码的init(…)失败,出现以下异常:

java.lang.NullPointerException: Attempt to get length of null array
    at com.android.org.bouncycastle.crypto.params.KeyParameter.<init>(KeyParameter.java:13)
    at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(BaseBlockCipher.java:557)
    at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:608)
    at javax.crypto.Cipher.tryCombinations(Cipher.java:532)
    at javax.crypto.Cipher.getSpi(Cipher.java:437)
    at javax.crypto.Cipher.init(Cipher.java:909)
    at javax.crypto.Cipher.init(Cipher.java:859)
    at de.demo.crypt.LoginActivity.executeLogin(LoginActivity.java:95)
    at de.demo.crypt.LoginActivity.access$000(LoginActivity.java:37)
    at de.demo.crypt.LoginActivity$1.onClick(LoginActivity.java:58)
    at de.demo.crypt.ActionButton.buttonClicked(ActionButton.java:104)
    at de.demo.crypt.ActionButton.access$000(ActionButton.java:17)
    at de.demo.crypt.ActionButton$1.onClick(ActionButton.java:60)
    at android.view.View.performClick(View.java:5198)
    at android.view.View$PerformClick.run(View.java:21147)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

解决方法:

对Cipher.getInstance使用“AES / CBC / PKCS7Padding”或“AES / CBC /”KeyProperties.ENCRYPTION_PADDING_PKCS7.

Android Keystore仅支持AES的PKCS#7填充(请参阅https://developer.android.com/training/articles/keystore.html#SupportedCiphers).对于大于64位的块大小(AES使用128位块),技术上没有定义PKCS#5填充.通常情况下,当人们说PKCS#5填充时,他们​​的意思是PKCS#7填充.

您看到的特殊错误是因为Bouncy Castle错误地声称支持AES / CBC / PKCS5Padding的Android Keystore密钥(请参阅Bouncy Castle问题跟踪器问题BJA-543).

P. S.最佳做法是让加密密码实现为您生成随机IV,而不是自己为密码提供IV – 您可以稍后使用Cipher.getIV()查询生成的IV.如果由于某种原因,您必须在加密时提供自己的IV,则在生成密钥时,您需要禁用密钥上的随机加密的默认要求(https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder.html#setRandomizedEncryptionRequired(boolean)).

标签:android
来源: https://codeday.me/bug/20190727/1556316.html

专注分享技术,共同学习,共同进步。侵权联系[admin#icode9.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有