Java Android密钥库错误“;无法在密钥库中生成密钥;

Java Android密钥库错误“;无法在密钥库中生成密钥;,java,android,runtime-error,android-keystore,Java,Android,Runtime Error,Android Keystore,我在尝试为某些设备生成密钥时出错。我能够在运行4.4.2的三星Galaxy Note上重现错误 java.lang.IllegalStateException: could not generate key in keystore at android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:100) at java.security.KeyPair

我在尝试为某些设备生成密钥时出错。我能够在运行4.4.2的三星Galaxy Note上重现错误

java.lang.IllegalStateException: could not generate key in keystore
        at android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:100)
        at java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:275)
        at com.eric.demo.MainActivity.generateKeyPair(MainActivity.java:65)
        at com.eric.demo.MainActivity.onClickButton(MainActivity.java:43)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at android.view.View$1.onClick(View.java:3964)
        at android.view.View.performClick(View.java:4640)
        at android.view.View$PerformClick.run(View.java:19421)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5476)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
        at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
        at dalvik.system.NativeStart.main(Native Method)
我创建了一个小应用程序,通过从Android开发者页面的“生成新私钥”下逐行复制代码来生成密钥

错误似乎发生在AndroidKeyPairGenerator.java内的kpg.generateKeyPair()中:

if (!mKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, keyType,
        mSpec.getKeySize(), mSpec.getFlags(), args)) {
    throw new IllegalStateException("could not generate key in keystore");
}
在KeyStore.java中:

public boolean generate(String key, int uid, int keyType, int keySize, int flags,
        byte[][] args) {
    try {
        return mBinder.generate(key, uid, keyType, keySize, flags, args) == NO_ERROR;
    } catch (RemoteException e) {
        Log.w(TAG, "Cannot connect to keystore", e);
        return false;
    }
}
调用mBinder.generate()似乎返回2,这意味着密钥库已锁定

// ResponseCodes
public static final int NO_ERROR = 1;
public static final int LOCKED = 2;
public static final int UNINITIALIZED = 3;
public static final int SYSTEM_ERROR = 4;
public static final int PROTOCOL_ERROR = 5;
public static final int PERMISSION_DENIED = 6;
public static final int KEY_NOT_FOUND = 7;
public static final int VALUE_CORRUPTED = 8;
public static final int UNDEFINED_ACTION = 9;
public static final int WRONG_PASSWORD = 10;
该错误可能与密钥库的此问题有关

我尝试了以下几种方法的单独和组合:
1.需要设置加密。结果是另一个错误:“如果需要加密,Android密钥库必须处于初始化和解锁状态”
2.设置锁定屏幕(模式、PIN、无、密码、刷卡)。同样的行为

3.以编程方式尝试使用
startActivity(新意图(“com.android.credentials.unlock”))解锁或重置凭据存储
startActivity(新意图(“com.android.credentials.RESET”)尝试解锁时会显示“输入凭证存储密码”消息,其中没有合理的密码,甚至清除凭证也没有帮助。

我认为这是正确的方向: 右键单击项目>Android工具>导出已签名的应用程序包 此时会出现导出Android应用程序向导。 选择要导出的项目,单击“下一步”。
此时会出现密钥库选择屏幕。

虽然我不知道完整答案,但我可以帮助您继续搜索。mBinder另一侧的绑定器实现是。如果我完全记得的话,它的行为是1)在软件级别支持密钥操作,或2)委托给OEM提供的keymaster库,该库(可能)与OEM的硬件支持密钥库接口。更多关于这方面的信息,以及


注意:我将放弃SO将外部链接内容拉入答案的常规策略,因为我将您链接到三篇都>1页的文章,并且发布6页的答案似乎有点可笑;-)

如果代码正常,请记住您需要为设备设置PIN/PW/指纹(安全解锁),以便密钥库开始工作。如果您试图生成密钥对,简单的刷卡就会产生这样的错误。

公共类EncryptionAPI18及以上{
public class EncryptionApi18AndAbove{
    private Context context;
    private KeyStore keyStore;
    private static String alias = "alias";

    public EncryptionApi18AndAbove(Context context) {
        this.context = context;
        try {
            keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
        } catch (Exception e) {
           // bla bla
        }
    }

    private String createNewKeys(String alias, Context context) {
        try {
            if (!keyStore.containsAlias(alias)) {
                Calendar start = Calendar.getInstance();
                Calendar end = Calendar.getInstance();
                end.add(Calendar.YEAR, 1);
                KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
                        .setAlias(alias)
                        .setSubject(new X500Principal("CN=Sample Name, O=Android Authority"))
                        .setSerialNumber(BigInteger.ONE)
                        .setStartDate(start.getTime())
                        .setEndDate(end.getTime())
                        .build();
                KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
                generator.initialize(spec);
                generator.initialize(spec);
                generator.generateKeyPair();
            }
        } catch (Exception e) {
            //bla bla
        }
        return alias;
    }

    @Override
    public String encrypt(String text) {
        if (text == null || text.length() == 0) {
            return text;
        }
        try {
            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(createNewKeys(alias, context), null);
            PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey();
            Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            inCipher.init(Cipher.ENCRYPT_MODE, publicKey);

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            CipherOutputStream cipherOutputStream = new CipherOutputStream(
                    outputStream, inCipher);
            cipherOutputStream.write(text.getBytes("UTF-8"));
            cipherOutputStream.close();

            return Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);
        } catch (Exception e) {
            //bla bla
        }
        return text;
    }

    @Override
    public String decrypt(String text) {
        if (text == null || text.length() == 0) {
            return text;
        }
        try {
            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(createNewKeys(alias, context), null);
            PrivateKey privateKey = privateKeyEntry.getPrivateKey();

            Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            output.init(Cipher.DECRYPT_MODE, privateKey);

            CipherInputStream cipherInputStream = new CipherInputStream(
                    new ByteArrayInputStream(Base64.decode(text, Base64.DEFAULT)), output);
            ArrayList<Byte> values = new ArrayList<>();
            int nextByte;
            while ((nextByte = cipherInputStream.read()) != -1) {
                values.add((byte) nextByte);
            }
            byte[] bytes = new byte[values.size()];
            for (int i = 0; i < bytes.length; i++) {
                bytes[i] = values.get(i).byteValue();
            }
            return new String(bytes, 0, bytes.length, "UTF-8");

        } catch (Exception e) {
            // bla bla
        }
        return text;
    }
}
私人语境; 私有密钥库; 私有静态字符串alias=“alias”; 公共加密PI18及以上(上下文){ this.context=上下文; 试一试{ keyStore=keyStore.getInstance(“AndroidKeyStore”); keyStore.load(null); }捕获(例外e){ //布拉布拉 } } 私有字符串createNewKeys(字符串别名、上下文){ 试一试{ 如果(!keyStore.containsAlias(别名)){ 日历开始=Calendar.getInstance(); 日历结束=Calendar.getInstance(); 结束。添加(日历年,1); KeyPairGeneratorSpec=新的KeyPairGeneratorSpec.Builder(上下文) .setAlias(别名) .setSubject(新的X500主体(“CN=示例名称,O=Android授权”)) .setSerialNumber(BigInteger.ONE) .setStartDate(start.getTime()) .setEndDate(end.getTime()) .build(); KeyPairGenerator generator=KeyPairGenerator.getInstance(“RSA”、“AndroidKeyStore”); 生成器初始化(规范); 生成器初始化(规范); generator.generateKeyPair(); } }捕获(例外e){ //布拉布拉 } 返回别名; } @凌驾 公共字符串加密(字符串文本){ if(text==null | | text.length()==0){ 返回文本; } 试一试{ KeyStore.PrivateKeyEntry PrivateKeyEntry=(KeyStore.PrivateKeyEntry)KeyStore.getEntry(createNewKeys(别名,上下文),null); PublicKey PublicKey=privateKeyEntry.getCertificate().getPublicKey(); Cipher inCipher=Cipher.getInstance(“RSA/ECB/PKCS1Padding”); inCipher.init(Cipher.ENCRYPT_模式,公钥); ByteArrayOutputStream outputStream=新建ByteArrayOutputStream(); CipherOutputStream CipherOutputStream=新CipherOutputStream( 输出流,导入器); cipherOutputStream.write(text.getBytes(“UTF-8”); cipherOutputStream.close(); 返回Base64.encodeToString(outputStream.toByteArray(),Base64.DEFAULT); }捕获(例外e){ //布拉布拉 } 返回文本; } @凌驾 公共字符串解密(字符串文本){ if(text==null | | text.length()==0){ 返回文本; } 试一试{ KeyStore.PrivateKeyEntry PrivateKeyEntry=(KeyStore.PrivateKeyEntry)KeyStore.getEntry(createNewKeys(别名,上下文),null); PrivateKey PrivateKey=privateKeyEntry.getPrivateKey(); 密码输出=Cipher.getInstance(“RSA/ECB/PKCS1Padding”); init(Cipher.DECRYPT_模式,privateKey); CipherInputStream CipherInputStream=新的CipherInputStream( 新的ByteArrayInputStream(Base64.decode(text,Base64.DEFAULT)),输出); ArrayList值=新的ArrayList(); int-nextByte; 而((nextByte=cipherInputStream.read())!=-1){ 添加((字节)下一个字节); } byte[]bytes=新字节[values.size()]; for(int i=0;ipublic class EncryptionApi18AndAbove{ private Context context; private KeyStore keyStore; private static String alias = "alias"; public EncryptionApi18AndAbove(Context context) { this.context = context; try { keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); } catch (Exception e) { // bla bla } } private String createNewKeys(String alias, Context context) { try { if (!keyStore.containsAlias(alias)) { Calendar start = Calendar.getInstance(); Calendar end = Calendar.getInstance(); end.add(Calendar.YEAR, 1); KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context) .setAlias(alias) .setSubject(new X500Principal("CN=Sample Name, O=Android Authority")) .setSerialNumber(BigInteger.ONE) .setStartDate(start.getTime()) .setEndDate(end.getTime()) .build(); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); generator.initialize(spec); generator.initialize(spec); generator.generateKeyPair(); } } catch (Exception e) { //bla bla } return alias; } @Override public String encrypt(String text) { if (text == null || text.length() == 0) { return text; } try { KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(createNewKeys(alias, context), null); PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey(); Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); inCipher.init(Cipher.ENCRYPT_MODE, publicKey); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); CipherOutputStream cipherOutputStream = new CipherOutputStream( outputStream, inCipher); cipherOutputStream.write(text.getBytes("UTF-8")); cipherOutputStream.close(); return Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT); } catch (Exception e) { //bla bla } return text; } @Override public String decrypt(String text) { if (text == null || text.length() == 0) { return text; } try { KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(createNewKeys(alias, context), null); PrivateKey privateKey = privateKeyEntry.getPrivateKey(); Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding"); output.init(Cipher.DECRYPT_MODE, privateKey); CipherInputStream cipherInputStream = new CipherInputStream( new ByteArrayInputStream(Base64.decode(text, Base64.DEFAULT)), output); ArrayList<Byte> values = new ArrayList<>(); int nextByte; while ((nextByte = cipherInputStream.read()) != -1) { values.add((byte) nextByte); } byte[] bytes = new byte[values.size()]; for (int i = 0; i < bytes.length; i++) { bytes[i] = values.get(i).byteValue(); } return new String(bytes, 0, bytes.length, "UTF-8"); } catch (Exception e) { // bla bla } return text; } }