gpt4 book ai didi

java - 如何生成可用于 C 和 Java 的公钥和私钥?

转载 作者:行者123 更新时间:2023-11-30 08:14:41 25 4
gpt4 key购买 nike

我正在尝试在 Windows 7 64 位上使用 OpenSSL 生成 PKCS12 公钥和私钥,这些 key 可以由 C 语言的 Microsoft CryptoAPI 以及 Java 程序使用。

以下是我遵循的步骤:

已下载安装的 Microsoft Visual C++ 2008 Redistributable Package (x64) de: http://www.microsoft.com/en-us/download/details.aspx?id=15336

下载安装的“Win64 OpenSSL v1.0.2a Light”de: http://slproweb.com/products/Win32OpenSSL.html

要使用非对称(公共(public)) key 加密技术加密/解密任意大小的文件,您需要使用 S/MIME 编码:

1) 生成 key 对。这将生成 2048 位公共(public)加密 key /证书 rsakpubcert.key 和匹配的私有(private)解密 key rsakpriv.key。 -days 10000 表示长期有效(27 年左右)。系统将要求您(两次)输入 PEM 密码来加密私钥。如果您不想加密它,请传递 -nodes 选项。公钥可以分发给任何想要向您发送数据的人。

md C:\OpenSSL-Win64\bin    
cd C:\OpenSSL-Win64\bin
set OPENSSL_CONF=C:\OpenSSL-Win64\bin\openssl.cfg
openssl req -x509 -days 10000 -newkey rsa:2048 -keyout c:\opensslkeys\rsakpriv.key -out c:\opensslkeys\rsakpubcert.key

// pass phrase used: mypassword

2)创建自签名证书请求

openssl req -new -key c:\opensslkeys\rsakpriv.key -out c:\opensslkeys\server.csr

3)从私钥中删除密码

openssl rsa -in c:\opensslkeys\rsakpriv.key -out c:\opensslkeys\rsakprivnopassword.key

4) 自签名证书请求(-days 是过期天数)
重要提示:使用“以管理员身份运行”启动命令提示符。否则你会得到同样的结果:无法写入“随机状态”错误。

cd C:\OpenSSL-Win64\bin    
set OPENSSL_CONF=C:\OpenSSL-Win64\bin\openssl.cfg
openssl x509 -req -days 365 -in c:\opensslkeys\server.csr -signkey c:\opensslkeys\rsakprivnopassword.key -out c:\opensslkeys\server.crt

5) 将输出转换为我们可以在代码中使用的 PKCS#12 格式(-keysig 参数允许我们使用 key 对进行签名)

openssl pkcs12 -export -in c:\opensslkeys\server.crt -inkey c:\opensslkeys\rsakprivnopassword.key -out c:\opensslkeys\mypublicencryptionkey.p12    
// export password used: mypassword

此时我可以使用 openssl 使用以下命令加密和解密文件:

加密:

openssl smime -encrypt -binary -aes-256-cbc -in c:\opensslkeys\todo.txt -out c:\opensslkeys\done.txt -outform DER c:\opensslkeys\server.crt

解密:

openssl smime -decrypt -binary -in c:\opensslkeys\done.txt -inform DER -out c:\opensslkeys\redone.txt -inkey c:\opensslkeys\rsakprivnopassword.key

但是,当我尝试在 Java 中使用 key 时,程序卡住了,说 key 格式错误。

非常感谢任何帮助!我保证为其他人发布完整的工作答案。

<小时/>

完整的Java代码:

/*
PrivatePublicKey.java
*/
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import javax.crypto.Cipher;
/* for IBM JDK need to replace: */
//import java.util.Base64;
/* with: */
import org.apache.commons.codec.binary.Base64;

public class PrivatePublicKey
{
public static void main(String[] args) throws Exception
{
try
{
PublicKeyReader myPublic = new PublicKeyReader();
PublicKey publicKey = myPublic.get("./rsakpubcert.key");

PrivateKeyReader myPrivate = new PrivateKeyReader();
PrivateKey privateKey = myPrivate.get("./rsakprivnopassword.key");

// Let's encrypt with private and decrypt with public
// Encrypt with private key
String firstString = "Ishana";

Cipher privateEncryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
privateEncryptCipher.init(Cipher.ENCRYPT_MODE, privateKey);

byte[] encryptedFirstString = privateEncryptCipher.doFinal(firstString.getBytes());
String encodedEncryptedFirstString = Base64.encodeBase64String(encryptedFirstString);

System.out.println("Encoded encrypted String for Ishana: " + encodedEncryptedFirstString);

// Decrypt with public key
// First decode the string
byte[] decodedEncryptedFirstString = Base64.decodeBase64(encodedEncryptedFirstString);

Cipher publicDecryptCipher = Cipher
.getInstance("RSA/ECB/PKCS1Padding");
publicDecryptCipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] decryptedFirstStringByte = publicDecryptCipher.doFinal(decodedEncryptedFirstString);
System.out.println("Decrypted String for Ishana: " + new String(decryptedFirstStringByte));
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

编辑,添加帮助代码:

import java.io.*;
import java.security.*;
import java.security.spec.*;


public class PublicKeyReader {

public static PublicKey get(String filename)
throws Exception {

File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int)f.length()];
dis.readFully(keyBytes);
dis.close();

X509EncodedKeySpec spec =
new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
}

import java.io.*;
import java.security.*;
import java.security.spec.*;

public class PrivateKeyReader {

public static PrivateKey get(String filename)
throws Exception {

File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int)f.length()];
dis.readFully(keyBytes);
dis.close();

PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
}

最佳答案

How to generate public and private keys usable for both C and Java?

生成 key 对并在内存中表示它们与在 Java 或其他框架/库(如 OpenSSL)中使用它们不同。

在内存中表示键是特定于框架/库的。

对 key 进行编码,以便不同的框架/库可以使用它们是诀窍。

<小时/>

However when I try to use the keys in Java the program chokes, saying the key format is wrong.

在 Java 中,通常只需在键上调用 getBytes() 即可。 key 将以自然表示形式提供。例如,在 RSA 公钥上调用它将会产生来自 PKCS 1 的 ASN.1 编码。

您可以考虑实现互操作性的其他格式包括用于私钥的 PKCS8 和 PKCS12。

还有 PEM,但它是一种较旧的格式。 PEM 适用于公钥,但您应该使用 PKCS8 或 PKCS12 作为私钥。

<小时/>

您使用 OpenSSL 生成的私有(private)文件可能是加密的 PEM 格式(您应该说明您使用的编码)。请参阅java read pem encoded keyHow to read a password encrypted key with java? 。如果其 DER 编码,则参见 java read der encoded key

关于java - 如何生成可用于 C 和 Java 的公钥和私钥?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29825492/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com