Java Android密钥库错误“;无法在密钥库中生成密钥;
我在尝试为某些设备生成密钥时出错。我能够在运行4.4.2的三星Galaxy Note上重现错误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
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;
}
}