Java asymmetric encryption: preferred way to store public/private keys

白昼怎懂夜的黑 提交于 2019-12-02 16:00:25

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.

You're actually storing the bytes in both cases whether you realize it or not. I suppose the correct answer is hinted at in @Brian M. Carr answer, which is to store the higher-level object in its most natural form. In the case of public keys, the obvious choices are as a PKCS#1 RSAPublicKey ASN.1 structure, DER-encoded, or as an X509 SubjectPublicKeyInfo ASN.1 structure, DER-encoded. The latter is what the Sun providers give you, which the sun class X509EncodedKeySpec supports. Similarly, the PKCS8EncodedKeySpec supports a private key format. Both these formats are standards, and are supported by openssl for example. Sun tends -- tended :( -- to support existing standards rather then define their own.

If you want to define a format for storing the keys, then I would choose a format that is expendable so that it doesn't break when you want to change encryption (when the old one gets to weak for example).

So i would store the bytes encoded as base64, together with a string that describes the format, "rsa" maybe.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!