Java非对称加密:存储公钥/私钥的首选方式 [英] Java asymmetric encryption: preferred way to store public/private keys

查看:171
本文介绍了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();
// ...写入文件

//将字节转换回公钥/私钥
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



选项二:存储模数指数

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

//存储模数和指数为BigIntegers
BigInteger modes = pub.getModulus());
BigInteger exponent = pub.getPublicExponent());
// ...写入文件

//重新创建公钥(同样适用于私钥)
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 
/ pre>

然后,您可以通过以下方式直接获取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;
}

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



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


This code generates a pair of public/private keys:

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair keypair = keyGen.genKeyPair();
PrivateKey privateKey = keypair.getPrivate();
PublicKey publicKey = keypair.getPublic();

What I'd like to know is how do you usually store the public key:

Option 1: store the bytes

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

What I don't like is to tie the code to concrete implementations such as PKCS8EncodedKeySpec and X509EncodedKeySpec.

Option 2: store the modulus and exponent

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

The second option is easier to implement, but I don't know if it could be less performant.

Any advise ?

解决方案

In our applications, we store public and private keys in DER format so they can be used and manipulated outside java more easily. In our case, the private keys do not have passwords on them.

To convert the private key to something more easily usable in java:

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

Then you can obtain an RSA private key directly by:

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

The public key is similar:

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

and to read it:

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

Many people store then keystores. For our purposes, we needed the same key to be shared across multiple applications in several different languages, and didn't want to duplicate the files on disk.

In either case, the performance shouldn't be a huge concern, because you're likely to store those keys in some sort of Singleton or cache instead of regenerating them each time.

这篇关于Java非对称加密:存储公钥/私钥的首选方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆