我的博客

openssl 生成证书实现 python 和 Java 的 SSL 通信(pem格式私钥)

目录

之前做过一些 ssl 相关的东西

python ssl demo(github)

openssl生成证书供java使用(我的博客)

这一次的需求是:

  1. 服务器端 python,客户端是 Java (android)
  2. 通过证书双向认证
  3. 证书可以方便的导入 app

在 python ssl demo 的基础上

1
2
3
4
5
6
7
8
9
10
11
# generate CA certificate
openssl req -newkey rsa:2048 -nodes -keyout CA_private.pem -x509 -subj "/CN=MY_CA" -days 365 -out CA_cert.crt


openssl genrsa -out client.pem 1024
openssl req -new -key client.pem -out client.csr -subj "/CN=client"
openssl x509 -req -days 3650 -in client.csr -CA CA_cert.crt -CAkey CA_private.pem -CAcreateserial -out client.crt

openssl genrsa -out server.pem 1024
openssl req -new -key server.pem -out server.csr -subj "/CN=server"
openssl x509 -req -days 3650 -in server.csr -CA CA_cert.crt -CAkey CA_private.pem -CAcreateserial -out server.crt

再添加一句

1
openssl pkcs8 -topk8 -inform PEM -in client.pem -outform PEM -nocrypt > client2.pem

把 rsa 私钥转换为 pkcs8 格式。这样可以直接在 java 中通过 java.security.spec.PKCS8EncodedKeySpec 读取。

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package com.company;

import javax.net.ssl.*;
import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.nio.file.Files;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.cert.Certificate;


public class Main {

protected static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter) {
String data = new String(pem);
String[] tokens = data.split(beginDelimiter);
tokens = tokens[1].split(endDelimiter);
return DatatypeConverter.parseBase64Binary(tokens[0]);
}

protected static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory factory = KeyFactory.getInstance("RSA");

return (RSAPrivateKey)factory.generatePrivate(spec);
}

protected static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException {
CertificateFactory factory = CertificateFactory.getInstance("X.509");

return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes));
}

protected static SSLSocketFactory getSocketFactoryPEM(String certPath, String privatePath, String caPath) {
try {
byte[] certAndKey = Files.readAllBytes((new File(certPath)).toPath());
byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
certAndKey = Files.readAllBytes((new File(privatePath)).toPath());
byte[] keyBytes = parseDERFromPEM(certAndKey, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----");
certAndKey = Files.readAllBytes((new File(caPath)).toPath());
byte[] caCertBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
X509Certificate cert = generateCertificateFromDER(certBytes);
X509Certificate cacert = generateCertificateFromDER(caCertBytes);
RSAPrivateKey key = generatePrivateKeyFromDER(keyBytes);

KeyStore keystore = KeyStore.getInstance("JKS");
KeyStore tkeystore = KeyStore.getInstance("JKS");
keystore.load(null);
tkeystore.load(null);
keystore.setCertificateEntry("client", cert);
tkeystore.setCertificateEntry("MY_CA", cacert);
keystore.setKeyEntry("key-alias", key, "<password>".toCharArray(), new Certificate[] {cert});

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
kmf.init(keystore, "<password>".toCharArray());
tmf.init(tkeystore);


KeyManager[] km = kmf.getKeyManagers();

SSLContext context = SSLContext.getInstance("TLS");
context.init(km, tmf.getTrustManagers(), null);
return context.getSocketFactory();
} catch (IOException | CertificateException | NoSuchAlgorithmException | UnrecoverableKeyException | InvalidKeySpecException | KeyStoreException | KeyManagementException e) {
e.printStackTrace();
}
return null;
}

public static void main(String[] args) {
String host = "127.0.0.1";
int port = 12345;
try {
SSLSocket sslSocket = (SSLSocket) getSocketFactoryPEM("client.crt", "client.pem2", "CA_cert.crt").createSocket(host, port);
String hello = "hello server!\n";
OutputStream out = sslSocket.getOutputStream();
out.write(hello.getBytes(), 0, hello.getBytes().length);
out.flush();

//从SSLSocket中读取数据
InputStream in = sslSocket.getInputStream();
byte[] buffer = new byte[50];
in.read(buffer);
System.out.println(new String(buffer));
} catch (IOException e) {
e.printStackTrace();
}

}
}

评论无需登录,可以匿名,欢迎评论!