如何使用 BouncyCastle 进行 TLS? [英] How do I do TLS with BouncyCastle?
问题描述
有人知道使用 BouncyCastle 的 TLS 示例吗?我对互联网上缺少它们感到惊讶.如果真的没有,让我们收集它们作为答案.
Does anybody know about examples of TLS with BouncyCastle? I was surprised by the lack of them on Internet. If there are really none, let's collect them as answers.
推荐答案
这是一个非常基本的示例,具有仅服务器身份验证和自签名证书.代码基于 BC 1.49,主要是轻量级 API:
This is a very basic example, with server-only authentication and self-signed cert. The code is based on BC 1.49, mostly leightweight API:
ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
final KeyPair keyPair = ...
final Certificate bcCert = new Certificate(new org.spongycastle.asn1.x509.Certificate[] {
new X509V3CertificateStrategy().selfSignedCertificateHolder(keyPair).toASN1Structure()});
while (true) {
Socket socket = serverSocket.accept();
TlsServerProtocol tlsServerProtocol = new TlsServerProtocol(
socket.getInputStream(), socket.getOutputStream(), secureRandom);
tlsServerProtocol.accept(new DefaultTlsServer() {
protected TlsSignerCredentials getRSASignerCredentials() throws IOException {
return tlsSignerCredentials(context);
}
});
new PrintStream(tlsServerProtocol.getOutputStream()).println("Hello TLS");
}
哪里
private TlsSignerCredentials tlsSignerCredentials(TlsContext context) throws IOException {
return new DefaultTlsSignerCredentials(context, bcCert,
PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded()));
}
这是客户端代码:
Socket socket = new Socket(<server IP>, SERVER_PORT);
TlsClientProtocol tlsClientProtocol = new TlsClientProtocol(
socket.getInputStream(), socket.getOutputStream());
tlsClientProtocol.connect(new DefaultTlsClient() {
public TlsAuthentication getAuthentication() throws IOException {
return new ServerOnlyTlsAuthentication() {
public void notifyServerCertificate(Certificate serverCertificate) throws IOException {
validateCertificate(serverCertificate);
}
};
}
});
String message = new BufferedReader(
new InputStreamReader(tlsClientProtocol.getInputStream())).readLine();
您需要使用来自 tlsClient/ServerProtocol 的输入和输出流来读取和写入加密数据(例如 tlsClientProtocol.getInputStream()).否则,如果您使用例如socket.getOutputStream(),你只会写未加密的数据.
You need to use the input and output stream from tlsClient/ServerProtocol to read and write encrypted data (e.g. tlsClientProtocol.getInputStream()). Otherwise, if you used e.g. socket.getOutputStream(), you would just write unencrypted data.
如何实现validateCertificate?我正在使用自签名证书.这意味着我只是在没有任何证书链的情况下在密钥库中查找它们.这是我创建密钥库的方式:
How to implement validateCertificate? I am using self-signed certificates. This means I just look them up in the key-store without any certificate chains. This is how I create the key store:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, password);
X509Certificate certificate = ...;
keyStore.setCertificateEntry(alias, certificate);
这是验证:
private void validateCertificate(org.spongycastle.crypto.tls.Certificate cert) throws IOException, CertificateException, KeyStoreException {
byte[] encoded = cert.getCertificateList()[0].getEncoded();
java.security.cert.Certificate jsCert =
CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(encoded));
String alias = keyStore.getCertificateAlias(jsCert);
if(alias == null) {
throw new IllegalArgumentException("Unknown cert " + jsCert);
}
}
令人困惑的是三个不同的证书类.您必须在它们之间进行转换,如上所示.
What is rather confusing, are the three different Certificate classes. You have to convert between them as shown above.
这篇关于如何使用 BouncyCastle 进行 TLS?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!