如何在Java中使用keystore来存储私钥?

我使用KeyPairGenerator生成RSA密钥对。 如果我没错,KeyStore仅用于存储证书而不是密钥。 如何在计算机上正确存储私钥?

你可以这样做:

  KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048); KeyPair kp = kpg.genKeyPair(); KeyFactory fact = KeyFactory.getInstance("RSA"); RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class); saveToFile(PUBLIC_KEY_FILE, pub.getModulus(), pub.getPublicExponent()); RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class); saveToFile(PRIVATE_KEY_FILE, priv.getModulus(), priv.getPrivateExponent()); 

保存function:

 private static void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws SomeException { ObjectOutputStream oout = new ObjectOutputStream( new BufferedOutputStream(new FileOutputStream(fileName))); try { oout.writeObject(mod); oout.writeObject(exp); } catch (Exception e) { throw new SomeException(e); } finally { oout.close(); } } 

并以同样的方式回读:

 private static PublicKey readPublicKey() throws SomeException { InputStream in = new FileInputStream(PUBLIC_KEY_FILE); ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in)); try { BigInteger m = (BigInteger) oin.readObject(); BigInteger e = (BigInteger) oin.readObject(); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e); KeyFactory fact = KeyFactory.getInstance("RSA"); PublicKey pubKey = fact.generatePublic(keySpec); return pubKey; } catch (Exception e) { throw new SomeException(e); } finally { oin.close(); } } 

读私钥是类似的。

这段代码将在AndroidKeyStore上生成并存储KeyPair。 (注意:省略了exception捕获)

 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); String alias = "my_key"; // replace as required or get it as a function argument int nBefore = keyStore.size(); // debugging variable to help convince yourself this works // Create the keys if necessary if (!keyStore.containsAlias(alias)) { Calendar notBefore = Calendar.getInstance(); Calendar notAfter = Calendar.getInstance(); notAfter.add(Calendar.YEAR, 1); KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this) .setAlias(alias) .setKeyType("RSA") .setKeySize(2048) .setSubject(new X500Principal("CN=test")) .setSerialNumber(BigInteger.ONE) .setStartDate(notBefore.getTime()) .setEndDate(notAfter.getTime()) .build(); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); generator.initialize(spec); KeyPair keyPair = generator.generateKeyPair(); } int nAfter = keyStore.size(); Log.v(TAG, "Before = " + nBefore + " After = " + nAfter); // Retrieve the keys KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null); RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey(); RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey(); Log.v(TAG, "private key = " + privateKey.toString()); Log.v(TAG, "public key = " + publicKey.toString()); 

http://snipplr.com/view/18368/

要么

http://docs.oracle.com/javase/1.5.0/docs/api/java/security/KeyStore.html

要么

http://java.sun.com/docs/books/tutorial/security/apisign/vstep2.html这是最有希望的

要么

在不受信任的环境中保护密钥是不可能的。 您可以对代码进行模糊处理,也可以从任意变量创建密钥。 最后,假设您使用标准的javax.crypto库,您必须调用Mac.getInstance(),稍后您将在该实例上调用init()。 想要你的钥匙的人会得到它。

但是,我认为解决方案是将密钥绑定到环境而不是程序。 签名意味着数据源自已知来源,并且自该源提供以来未被篡改。 目前,您试图说“保证我的程序生成数据”。 相反,将您的要求更改为“保证我的程序的特定用户生成数据”。 然后将责任转移给该用户以照顾他/她的钥匙。

根据私钥的格式,您可能需要将其转换为java keytool可以使用的格式。

但如果它是一个keytool支持的格式,你应该能够使用keytool导入它。 更多信息:

http://docs.oracle.com/javase/tutorial/security/toolfilex/rstep1.html

http://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/keytool.html