2015-10-26 56 views
1

我已经编写了一个API,以便我的不同应用程序可以使用它。它只是检查应用程序是否在服务器上注册。如果不是那么它会生成公钥/私钥对,并获得通过将CSR发送到我的服务器来签署证书。下一次它使用签名证书和私钥。最初,我有原始的默认密钥库文件(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(); 
    } 
} 

,并通过以下方法,我生成我的密钥库,但我搞不清如何以及在哪里可以安全地存储此密钥库,使我可以在应用程序的其余部分使用它(除非密钥被盗)。正如在共享偏好我不能存储任何对象,所以在哪里保存这个keystore.Right现在我有我的类中的静态密钥库对象(这是我知道最糟糕,但只是为了使它工作,我已经使它静态)

private boolean addToStore(){ 
     try { 
      Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1); 
      clientPkcs12 = KeyStore.getInstance("PKCS12"); 
      clientPkcs12.load(null, null); 
      clientPkcs12.setKeyEntry("clientCert", keyPair.getPrivate(), "123456".toCharArray(), chain); 
     } 
     catch(Exception ex){ 
      Log.e("",ex.getCause().getMessage()); 
     } 
     return false; 
    } 

我已经经历了几个帖子,其中这是显而易见的一个nelenkov.blogspot,但没有得到我如何实现我的目标,或者我在保存密钥库时出错?我的意思是每次都必须创建密钥存储区?

回答

1

我不知道当你有Keystore时,为什么要保留共享首选项中的凭据。一旦将密钥库文件加载到内存中,您可以随时添加/检索密钥。而当你与刚刚完成其保存在文件中通过调用:从文件

FileOutputStream out = new FileOutputStream(keystoreFile); 
    keystore.store(out, password); 
    out.close(); 

负载:

keystore.load(new FileInputStream(keystoreFile, password); 

@answer评论

您应该只使用Keystore。来自共享偏好的数据不安全,并且从中检索私钥非常容易。您没有使用任何加密方式,因此您的密钥存储在普通的PEM文本中。但是,如果您使用Keystore,则您的密钥受密码保护(在密钥级别和密钥库级别),因此如果任何人无密码获得Keystore文件,则破解它将会困难得多。保存Keystore文件的最佳位置是您的应用程序内部空间磁盘,无法在没有固定电话的情况下访问(创建文件时为Context.MODE_PRIVATE)。

+0

thnx回复,我已经提到可能是我错了,所以如你所说我有两件事要问,1#我需要将我的密钥保存在SP中,因为我正在做或只有密钥库足够? 2#在哪里保存这个文件,以便其他人不能访问它? – SSH

+0

@SSH我编辑了我的答案,您的评论回复 – Than

+0

thnx再次,测试与此,将接受您的答案,一旦我将获得成功 – SSH

0

您已回答了您自己的问题。将它们保存在KeyStore,而不是中。

相关问题