Java 如何安全地保存密钥库
我已经编写了一个API,以便我的不同应用程序可以使用它。它只是检查应用程序是否已在服务器上注册。如果未注册,它将生成公钥/私钥对,并通过向我的服务器发送CSR来获得签名证书。下次使用签名证书和私钥时。最初我在raw中有默认密钥库文件(b/c我的所有通信都是通过SSL进行的,即最初使用默认密钥库,在注册用户生成的密钥库之后) 我的API运行良好。我遇到的问题与我缺乏知识或方法错误有关,因此我需要帮助 我正在使用以下类来保存/检索我的密钥对Java 如何安全地保存密钥库,java,android,ssl,x509certificate,keystore,Java,Android,Ssl,X509certificate,Keystore,我已经编写了一个API,以便我的不同应用程序可以使用它。它只是检查应用程序是否已在服务器上注册。如果未注册,它将生成公钥/私钥对,并通过向我的服务器发送CSR来获得签名证书。下次使用签名证书和私钥时。最初我在raw中有默认密钥库文件(b/c我的所有通信都是通过SSL进行的,即最初使用默认密钥库,在注册用户生成的密钥库之后) 我的API运行良好。我遇到的问题与我缺乏知识或方法错误有关,因此我需要帮助 我正在使用以下类来保存/检索我的密钥对 public class KeyIOHandler {
public class KeyIOHandler {
public static void writePublicKeyToPreferences(KeyPair key, Context context) {
StringWriter publicStringWriter = new StringWriter();
try {
PemWriter pemWriter = new PemWriter(publicStringWriter);
pemWriter.writeObject(new PemObject("myapp.PUBLIC KEY", key.getPublic().getEncoded()));
pemWriter.flush();
pemWriter.close();
SharedPreferences preferences = context.getSharedPreferences("SHARED_PREFERENCES",0);
preferences.edit().putString("RSA_PUBLIC_KEY", publicStringWriter.toString()).commit();
Log.e("Public Key", publicStringWriter.toString());
} catch (IOException e) {
Log.e("RSA", e.getMessage());
e.printStackTrace();
}
}
public static void writePrivateKeyToPreferences(KeyPair keyPair, Context context) {
StringWriter privateStringWriter = new StringWriter();
try {
PemWriter pemWriter = new PemWriter(privateStringWriter);
pemWriter.writeObject(new PemObject("myapp.PRIVATE KEY", keyPair.getPrivate().getEncoded()));
pemWriter.flush();
pemWriter.close();
SharedPreferences preferences = context.getSharedPreferences("SHARED_PREFERENCES",0);
preferences.edit().putString("RSA_PRIVATE_KEY", privateStringWriter.toString()).commit();
Log.e("Private Key",privateStringWriter.toString());
} catch (IOException e) {
Log.e("RSA", e.getMessage());
e.printStackTrace();
}
}
public static PublicKey getRSAPublicKeyFromString(String publicKeyPEM) throws Exception {
publicKeyPEM = stripPublicKeyHeaders(publicKeyPEM);
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "SC");
byte[] publicKeyBytes = Base64.decode(publicKeyPEM.getBytes("UTF-8"));
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
return keyFactory.generatePublic(x509KeySpec);
}
public static PrivateKey getRSAPrivateKeyFromString(String privateKeyPEM) throws Exception {
privateKeyPEM = stripPrivateKeyHeaders(privateKeyPEM);
KeyFactory fact = KeyFactory.getInstance("RSA", "SC");
byte[] clear = Base64.decode(privateKeyPEM);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(clear);
PrivateKey priv = fact.generatePrivate(keySpec);
Arrays.fill(clear, (byte) 0);
return priv;
}
public static String stripPublicKeyHeaders(String key) {
//strip the headers from the key string
StringBuilder strippedKey = new StringBuilder();
String lines[] = key.split("\n");
for (String line : lines) {
if (!line.contains("BEGIN PUBLIC KEY") && !line.contains("END PUBLIC KEY") && !isNullOrEmpty(line.trim())) {
strippedKey.append(line.trim());
}
}
return strippedKey.toString().trim();
}
public static String stripPrivateKeyHeaders(String key) {
StringBuilder strippedKey = new StringBuilder();
String lines[] = key.split("\n");
for (String line : lines) {
if (!line.contains("BEGIN PRIVATE KEY") && !line.contains("END PRIVATE KEY") && !isNullOrEmpty(line.trim())) {
strippedKey.append(line.trim());
}
}
return strippedKey.toString().trim();
}
public static boolean isNullOrEmpty(String str) {
return str == null || str.isEmpty();
}
}
通过使用以下方法,我生成了我的密钥库,但我不知道如何以及在何处安全地存储该密钥库,以便在应用程序的剩余生命中使用它(除非密钥被盗)。正如在共享首选项中一样,我无法存储任何对象,因此将该密钥库保存在何处。目前,我的类中有静态密钥库对象。(这是我所知道的最糟糕的情况,但为了使其正常工作,我将其设置为静态)
我已经通过了几个帖子,其中这是一个明显的,但没有得到我如何才能实现我的目标或我在保存密钥库错误?我的意思是每次都必须创建密钥库吗 我不知道当您拥有
密钥库时,为什么要将凭据保留在共享首选项中。将密钥库文件加载到内存后,您可以随时添加/检索密钥。完成后,只需调用以下命令将其保存到文件中:
FileOutputStream out = new FileOutputStream(keystoreFile);
keystore.store(out, password);
out.close();
从文件加载:
keystore.load(new FileInputStream(keystoreFile, password);
@对评论的答复
您应该只使用密钥库
。来自共享首选项的数据不安全,从中检索私钥非常容易。您没有使用任何类型的加密,因此您的密钥存储在纯PEM文本中。但是,如果您使用Keystore
您的密钥受密码保护(在密钥级别和密钥存储级别),因此如果任何人在没有密码的情况下获得Keystore
文件,他将很难破解该文件。保存Keystore
文件的最佳位置是您的应用程序内部空间磁盘,如果没有根手机(Context.MODE\u PRIVATE
创建文件),则无法访问该磁盘。您已经回答了自己的问题。将它们保存在密钥库中,而不是保存在首选项文件中。thnx对于回答,我已经提到可能是我弄错了,所以正如您所说,我有两件事要问,1#我是否需要像保存密钥库一样将密钥保存在SP中,或者只保存密钥库就足够了?2#将此文件保存在何处,以便其他人无法访问?再次测试,一旦我成功,thnx将接受您的答案Nikolay Elenkov博客是Android中所有与安全相关的信息的重要来源。我建议你浏览一下他所有的博客文章,以获得更多关于这方面的知识。您也可以查看他的书:
keystore.load(new FileInputStream(keystoreFile, password);