Java非对称加密:存储公钥/私钥的首选方式

代码生成一对公/私钥:
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair keypair = keyGen.genKeyPair();
PrivateKey privateKey = keypair.getPrivate();
PublicKey publicKey = keypair.getPublic();

我想知道的是你通常如何存储公钥:

选项1:存储字节

byte[] privateKeyBytes = privateKey.getEncoded();
byte[] publicKeyBytes = publicKey.getEncoded();
// ... write to file

// convert bytes back to public/private keys
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

我不喜欢的是将代码绑定到具体的实现,如PKCS8EncodedKeySpec和X509EncodedKeySpec.

选项2:存储模数和指数

KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(publicKey,RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(privateKey,RSAPrivateKeySpec.class);

// store modulus and exponent as BigIntegers
BigInteger modulus = pub.getModulus());
BigInteger exponent = pub.getPublicExponent());
// ... write to file

// recreate public key (the same applies to the private key)
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus,exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);

第二个选项更容易实现,但我不知道它是否可能性能较差.

任何建议?

解决方法

在我们的应用程序中,我们以DER格式存储公钥和私钥,以便在java之外更容易地使用和操作.在我们的例子中,私钥没有密码.

将私钥转换为更容易在java中使用的东西:

openssl pkcs8 -topk8 -nocrypt -in key.pem -inform PEM -out key.der -outform DER

然后,您可以直接通过以下方式获取RSA私钥:

public static RSAPrivateKey getPrivateKey(File privateKeyFile) throws IOException,GeneralSecurityException {
    byte[] keyBytes = new byte[(int)privateKeyFile.length()];
    FileInputStream fis = new FileInputStream(privateKeyFile);
    fis.read(keyBytes);
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(spec);
    return privKey;
}

公钥是相似的:

openssl rsa -in private.pem -pubout -outform DER -out public.der

并阅读它:

public static RSAPublicKey getPublicKey(File publicKeyFile) throws IOException,GeneralSecurityException {
    byte[] keyBytes = new byte[(int)publicKeyFile.length()];
    FileInputStream fis = new FileInputStream(publicKeyFile);
    fis.read(keyBytes);
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory factory = KeyFactory.getInstance("RSA");
    RSAPublicKey pubKey = (RSAPublicKey)factory.generatePublic(publicKeySpec);
    return pubKey;
}

许多人存储然后密钥库.为了我们的目的,我们需要使用几种不同语言在多个应用程序之间共享相同的密钥,并且不想在磁盘上复制文件.

在任何一种情况下,性能不应该是一个巨大的问题,因为您可能将这些密钥存储在某种单例或缓存中,而不是每次重新生成.

相关文章

1.Linux实时查看Java接口数据的方法 在Linux系统中实时查看J...
应用场景 C端用户提交工单、工单创建完成之后、会发布一条工...
线程类,设置有一个公共资源 package cn.org.chris.concurre...
Java中的数字(带有0前缀和字符串)
在Java 9中使用JLink的目的是什么?
Java Stream API Filter(过滤器)