Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/233.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何安全地保存密钥库_Java_Android_Ssl_X509certificate_Keystore - Fatal编程技术网

Java 如何安全地保存密钥库

Java 如何安全地保存密钥库,java,android,ssl,x509certificate,keystore,Java,Android,Ssl,X509certificate,Keystore,我已经编写了一个API,以便我的不同应用程序可以使用它。它只是检查应用程序是否已在服务器上注册。如果未注册,它将生成公钥/私钥对,并通过向我的服务器发送CSR来获得签名证书。下次使用签名证书和私钥时。最初我在raw中有默认密钥库文件(b/c我的所有通信都是通过SSL进行的,即最初使用默认密钥库,在注册用户生成的密钥库之后) 我的API运行良好。我遇到的问题与我缺乏知识或方法错误有关,因此我需要帮助 我正在使用以下类来保存/检索我的密钥对 public class KeyIOHandler {

我已经编写了一个API,以便我的不同应用程序可以使用它。它只是检查应用程序是否已在服务器上注册。如果未注册,它将生成公钥/私钥对,并通过向我的服务器发送CSR来获得签名证书。下次使用签名证书和私钥时。最初我在raw中有默认密钥库文件(b/c我的所有通信都是通过SSL进行的,即最初使用默认密钥库,在注册用户生成的密钥库之后)

我的API运行良好。我遇到的问题与我缺乏知识或方法错误有关,因此我需要帮助

我正在使用以下类来保存/检索我的密钥对

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);