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.
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"); }
where
private TlsSignerCredentials tlsSignerCredentials(TlsContext context) throws IOException { return new DefaultTlsSignerCredentials(context, bcCert, PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded())); }
This is the client code:
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();
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.
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);
And this is the validation:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With