简体   繁体   English

如何生成 PEM 格式的公钥和私钥

[英]how to generate public and private key in PEM format

I need to generating a RSA and DSA key pair (public and private key) in PEM format using java.我需要使用 java 生成 PEM 格式的 RSA 和 DSA 密钥对(公钥和私钥)。 I want the public and private key files to be opened with this format:我希望以这种格式打开公钥和私钥文件:

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAryQICCl6NZ5gDKrnSztO 3Hy8PEUcuyvg/ikC+VcIo2SFFSf18a3IMYldIugqqqZCs4/4uVW3sbdLs/6PfgdX 7O9D22ZiFWHPYA2k2N744MNiCD1UE+tJyllUhSblK48bn+v1oZHCM0nYQ2NqUkvS j+hwUU3RiWl7x3D2s9wSdNt7XUtW05a/FXehsPSiJfKvHJJnGOX0BgTvkLnkAOTd OrUZ/wK69Dzu4IvrN4vs9Nes8vbwPa/ddZEzGR0cQMt0JBkhk9kU/qwqUseP1QRJ 5I1jR4g8aYPL/ke9K35PxZWuDp3U0UPAZ3PjFAh+5T+fc7gzCs9dPzSHloruU+gl FQIDAQAB -----END PUBLIC KEY----- -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAryQICCl6NZ5gDKrnSztO 3Hy8PEUcuyvg/ikC+VcIo2SFFSf18a3IMYldIugqqqZCs4/4uVW3sbdLs/6PfgdX 7O9D22ZiFWHPYA2k2N744MNiCD1UE+tJyllUhSblK48bn+v1oZHCM0nYQ2NqUkvS j+hwUU3RiWl7x3D2s9wSdNt7XUtW05a/FXehsPSiJfKvHJJnGOX0BgTvkLnkAOTd OrUZ/wK69Dzu4IvrN4vs9Nes8vbwPa/ddZEzGR0cQMt0JBkhk9kU/qwqUseP1QRJ 5I1jR4g8aYPL/ke9K35PxZWuDp3U0UPAZ3PjFAh+5T+fc7gzCs9dPzSHloruU+gl FQIDAQAB -----结束公钥-----

My public key is already generated before with this format that i do not want it:我的公钥之前已经生成了我不想要的这种格式:

0Ÿ0 *†H†÷ 0Ÿ0 *†H†÷ 0×0 *†H†÷ 0×0 *†H†÷

ok, this is my code of key generation:好的,这是我的密钥生成代码:

private static void createKey()
        throws Exception {

            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            System.out.print("Password to encrypt the private key: ");
            String password = in.readLine();
            System.out.println("Generating an RSA keypair...");

            // Create an RSA key
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024);
            KeyPair keyPair = keyPairGenerator.genKeyPair();

            System.out.println("Done generating the keypair.\n");

            // Now we need to write the public key out to a file
            System.out.print("Public key filename: ");
            String publicKeyFilename = "C:/Users/Joe/Desktop/" + in.readLine();

            // Get the encoded form of the public key so we can
            // use it again in the future. This is X.509 by default.
            byte[] publicKeyBytes = keyPair.getPublic().getEncoded();

            // Write the encoded public key out to the filesystem
            FileOutputStream fos = new FileOutputStream(publicKeyFilename);
            fos.write(publicKeyBytes);
            fos.close();

            // Now we need to do the same thing with the private key,
            // but we need to password encrypt it as well.
            System.out.print("Private key filename: ");
            String privateKeyFilename = "C:/Users/Joe/Desktop/" + in.readLine();

            // Get the encoded form. This is PKCS#8 by default.
            byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();

            // Here we actually encrypt the private key
            byte[] encryptedPrivateKeyBytes =
            passwordEncrypt(password.toCharArray(),privateKeyBytes);

            fos = new FileOutputStream(privateKeyFilename);
            fos.write(encryptedPrivateKeyBytes);
            fos.close();
        }

thank you for your help..谢谢您的帮助..

Maybe a bit late but there is my solution.也许有点晚了,但有我的解决方案。 Hope it helps others.希望它可以帮助其他人。

byte[] publicKeyBytes = keyPair.getPublic().getEncoded();

Here you're taking bytes of key and writing directly to file.在这里,您将获取密钥字节并直接写入文件。 So you get the appropriate result - DER-encoded file.所以你会得到适当的结果 - DER 编码的文件。 However PEM is Base64 encoded format with line breaks each 64 symbols and header/footer.然而,PEM 是 Base64 编码格式,每 64 个符号和页眉/页脚有换行符。

There is code implementing this logic:有代码实现这个逻辑:

String publicKeyContent = Base64.encode(publicKeyBytes);
String publicKeyFormatted = "-----BEGIN PUBLIC KEY-----" + System.lineSeparator();
for (final String row: 
        Splitter
            .fixedLength(64)
            .split(publicKeyContent)
    ) 
{
    publicKeyFormatted += row + System.lineSeparator();
}
publicKeyFormatted += "-----END PUBLIC KEY-----";

So publicKeyFormatted will contain PEM-encoded string of public key.因此 publicKeyFormatted 将包含 PEM 编码的公钥字符串。

PS Splitter is a class provided in Guava lib, but you can split the string with a simple cycle or somehow. PS Splitter 是 Guava lib 中提供的一个类,但您可以使用简单的循环或以某种方式拆分字符串。

Instead of manually generating the PEM String, you can use the bouncy castle to do it for you: since it's a tested library you can be sure about the output.您可以使用充气城堡代替手动生成 PEM 字符串:因为它是一个经过测试的库,您可以确定输出。 The following code is in Kotlin but can easily be used with Java syntax:以下代码在 Kotlin 中,但可以很容易地与 Java 语法一起使用:

        val gen = KeyPairGenerator.getInstance("RSA")
        gen.initialize(2048)
        val pair = gen.generateKeyPair()
        val privateKey: PrivateKey = pair.private
       
  
        val pemObject = PemObject("RSA PRIVATE KEY", privateKey.encoded)
        
        val byteStream = ByteArrayOutputStream()
        val pemWriter = PemWriter(OutputStreamWriter(byteStream))
        pemWriter.writeObject(pemObject)
        pemWriter.close();
        println(String(byteStream.toByteArray()))

I've written a library that includes methods which can do this.我编写了一个库,其中包含可以执行此操作的方法。 It's called Reasonably Easy Cryptography and you can use the PEMHandler methods for this.它被称为合理简单的密码术,您可以为此使用PEMHandler方法。 Here's how you could do it, assuming you've imported PEMHandler from my library, and that key 's class is an implementation of java.security.Key such as a PrivateKey :假设您已经从我的库中导入PEMHandler ,并且该key的 class 是java.security.Key的实现,例如PrivateKey

String pem = PEMHandler.keyToPem(key);

This works with any kind of Key , it'll figure out whether it's a public or private key and what algorithm it uses on its own (it isn't perfect and I'm still working on finding the best way to do that, but it does work fine with PrivateKey and PublicKey ).这适用于任何类型的Key ,它会确定它是公钥还是私钥以及它自己使用的算法(它并不完美,我仍在努力寻找最好的方法来做到这一点,但是它确实适用于PrivateKeyPublicKey )。 There's also a method to do this for both keys in a KeyPair in one call, and methods to convert the PEM string back to a Key.还有一种方法可以在一次调用中对 KeyPair 中的两个键执行此操作,以及将 PEM 字符串转换回 Key 的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM