diff --git a/examples/tls/demo/pom.xml b/examples/tls/demo/pom.xml new file mode 100644 index 000000000..884862536 --- /dev/null +++ b/examples/tls/demo/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + com.alibaba.dragonwell.security.tls.demo + demo + 1.0-SNAPSHOT + demo + + http://www.example.com + + UTF-8 + 11 + 11 + 1.35 + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + provided + + + org.bouncycastle + bcprov-jdk15on + 1.70 + + + com.alibaba.dragonwell + security-native-uber + 1.0.0 + + + + junit + junit + 4.11 + test + + + + + + kr.motd.maven + os-maven-plugin + 1.4.1.Final + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.3.0 + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + \ No newline at end of file diff --git a/examples/tls/demo/run.sh b/examples/tls/demo/run.sh new file mode 100755 index 000000000..0a5c79354 --- /dev/null +++ b/examples/tls/demo/run.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +mvn clean package + +java -cp ./target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar com.alibaba.dragonwell.security.tls.demo.SMDemo \ No newline at end of file diff --git a/examples/tls/demo/src/main/java/com/alibaba/dragonwell/security/tls/demo/CertificateBuild.java b/examples/tls/demo/src/main/java/com/alibaba/dragonwell/security/tls/demo/CertificateBuild.java new file mode 100644 index 000000000..649f46b28 --- /dev/null +++ b/examples/tls/demo/src/main/java/com/alibaba/dragonwell/security/tls/demo/CertificateBuild.java @@ -0,0 +1,79 @@ +package com.alibaba.dragonwell.security.tls.demo; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Base64; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import org.conscrypt.OpenSSLX509Certificate; + +public class CertificateBuild { + private static final char[] EMPTY_PASSWORD = new char[0]; + private static final String SERVER_CA = "/cert/sm2-root.crt"; + private static final String PRIVATE_KEY = "/cert/sm2-root.key"; + private static KeyStore ks = null; + + static { + try { + // Create an empty keystore + ks = KeyStore.getInstance("PKCS12", new BouncyCastleProvider()); + ks.load(null, null); + + // Build a service CA + X509Certificate ca = OpenSSLX509Certificate + .fromX509PemInputStream(CertificateBuild.class.getResourceAsStream(SERVER_CA)); + PrivateKey privateKey = readSM2PrivateKeyPemFile(PRIVATE_KEY); + + ks.setKeyEntry("default", privateKey, EMPTY_PASSWORD, new X509Certificate[] { ca }); + ks.setCertificateEntry("CA", ca); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static PrivateKey readSM2PrivateKeyPemFile(String name) throws Exception { + InputStream inputStream = CertificateBuild.class.getResourceAsStream(name); + InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + StringBuilder sb = new StringBuilder(); + String line = null; + while ((line = bufferedReader.readLine()) != null) { + if (line.startsWith("-")) { + continue; + } + sb.append(line).append("\n"); + } + String ecKey = sb.toString().replaceAll("\\r\\n|\\r|\\n", ""); + Base64.Decoder base64Decoder = Base64.getDecoder(); + byte[] keyByte = base64Decoder.decode(ecKey.getBytes(StandardCharsets.UTF_8)); + PKCS8EncodedKeySpec eks2 = new PKCS8EncodedKeySpec(keyByte); + KeyFactory keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider()); + PrivateKey privateKey = keyFactory.generatePrivate(eks2); + return privateKey; + } + + public static KeyManager[] keyManagerBuilder() throws Exception { + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, EMPTY_PASSWORD); + return kmf.getKeyManagers(); + } + + public static TrustManager[] trustManagerBuilder() throws Exception { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + return tmf.getTrustManagers(); + } +} diff --git a/examples/tls/demo/src/main/java/com/alibaba/dragonwell/security/tls/demo/SMDemo.java b/examples/tls/demo/src/main/java/com/alibaba/dragonwell/security/tls/demo/SMDemo.java new file mode 100644 index 000000000..485d87065 --- /dev/null +++ b/examples/tls/demo/src/main/java/com/alibaba/dragonwell/security/tls/demo/SMDemo.java @@ -0,0 +1,91 @@ +package com.alibaba.dragonwell.security.tls.demo; + +import javax.net.ssl.*; + +import com.alibaba.dragonwell.security.DragonwellSecurityProvider; + +import java.io.*; +import java.security.*; +import java.util.concurrent.CountDownLatch; + +/** + * tls1.3 + rfc8998 demo + */ +public class SMDemo { + private static final String SSL_13_TYPE = "TLSv1.3"; + private static final String CIPHER_SUITE = "TLS_SM4_GCM_SM3"; + private static final String HELLO_REQUEST = "hello request"; + private static final String HELLO_RESPONSE = "hello response"; + + private static volatile int port = -1; + + private static SSLContext createServerSSLContext() throws Exception { + TrustManager[] tms = CertificateBuild.trustManagerBuilder(); + KeyManager[] kms = CertificateBuild.keyManagerBuilder(); + + SSLContext sslContext = SSLContext.getInstance(SSL_13_TYPE, new DragonwellSecurityProvider()); + sslContext.init(kms, tms, new SecureRandom()); + return sslContext; + } + + private static SSLServerSocket buildSSLServerSocket(SSLContext serverContext) throws Exception { + SSLServerSocketFactory serverFactory = serverContext.getServerSocketFactory(); + SSLServerSocket svrSocket = (SSLServerSocket) serverFactory.createServerSocket(0); + port = svrSocket.getLocalPort(); + svrSocket.setNeedClientAuth(false); + return svrSocket; + } + + private static SSLContext createClientSSLContext() throws Exception { + TrustManager[] tms = CertificateBuild.trustManagerBuilder(); + SSLContext sslContext = SSLContext.getInstance(SSL_13_TYPE, new DragonwellSecurityProvider()); + sslContext.init(null, tms, new SecureRandom()); + return sslContext; + } + + private static SSLSocket buildSSLClientSocket(SSLContext clientContext) throws Exception { + SSLSocketFactory sslCntFactory = clientContext.getSocketFactory(); + SSLSocket sslSocket = (SSLSocket) sslCntFactory.createSocket("localhost", port); + sslSocket.setEnabledCipherSuites(new String[] { CIPHER_SUITE }); + return sslSocket; + } + + public static void main(String[] args) throws Exception { + CountDownLatch downLatch = new CountDownLatch(1); + + // Start server asynchronously. + SSLServerSocket serverSocket = buildSSLServerSocket(createServerSSLContext()); + Thread serverThread = new Thread(() -> { + try { + downLatch.countDown(); + SSLSocket sslSocket = (SSLSocket) serverSocket.accept(); + BufferedReader ioReader = new BufferedReader(new InputStreamReader(sslSocket.getInputStream())); + PrintWriter ioWriter = new PrintWriter(sslSocket.getOutputStream()); + String tmpMsg = ioReader.readLine(); + if (tmpMsg != null) { + ioWriter.println(HELLO_RESPONSE); + ioWriter.flush(); + System.out.println(sslSocket.getSession().getCipherSuite()); + Thread.sleep(1_000); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); + serverThread.setDaemon(true); + serverThread.start(); + + // Start client. + downLatch.await(); + // Wait for server startup. + Thread.sleep(2_000); + SSLSocket clientSocket = buildSSLClientSocket(createClientSSLContext()); + BufferedReader ioReader = new BufferedReader(new InputStreamReader( + clientSocket.getInputStream())); + PrintWriter ioWriter = new PrintWriter(clientSocket.getOutputStream()); + ioWriter.println(HELLO_REQUEST); + ioWriter.flush(); + System.out.println(ioReader.readLine()); + clientSocket.close(); + } +} diff --git a/examples/tls/demo/src/main/resources/cert/sm2-root.crt b/examples/tls/demo/src/main/resources/cert/sm2-root.crt new file mode 100644 index 000000000..f92e63775 --- /dev/null +++ b/examples/tls/demo/src/main/resources/cert/sm2-root.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB6jCCAZECFE4j9T8o2H4CqpaqcnhX2AenXBR2MAoGCCqBHM9VAYN1MHgxCzAJ +BgNVBAYTAkNIMQswCQYDVQQIDAJaSjELMAkGA1UEBwwCSFoxDDAKBgNVBAoMA0pW +TTEMMAoGA1UECwwDQWxpMQ8wDQYDVQQDDAZzZXJ2ZXIxIjAgBgkqhkiG9w0BCQEW +E3N1cGVyYWp1bkBnbWFpbC5jb20wHhcNMjIxMjI1MTIzNjQzWhcNMjMwMTI0MTIz +NjQzWjB4MQswCQYDVQQGEwJDSDELMAkGA1UECAwCWkoxCzAJBgNVBAcMAkhaMQww +CgYDVQQKDANKVk0xDDAKBgNVBAsMA0FsaTEPMA0GA1UEAwwGc2VydmVyMSIwIAYJ +KoZIhvcNAQkBFhNzdXBlcmFqdW5AZ21haWwuY29tMFkwEwYHKoZIzj0CAQYIKoEc +z1UBgi0DQgAEiyrkFGrfi23L8jWC99NGtX1ph9t8UwPHiAixb3DvRisb5zaHzMJJ +Lmb1wm7iaNRxSNagEq4dcPv7XwhxD7B8sDAKBggqgRzPVQGDdQNHADBEAiBa542C +GtKPrCN2isAJ+snocHZgoWH3r6aSCL889psVMgIgUxt7TquMmZ7EGJBrDDb0sstN +6nksnUhXejscUV6/hdg= +-----END CERTIFICATE----- diff --git a/examples/tls/demo/src/main/resources/cert/sm2-root.key b/examples/tls/demo/src/main/resources/cert/sm2-root.key new file mode 100644 index 000000000..af0c26270 --- /dev/null +++ b/examples/tls/demo/src/main/resources/cert/sm2-root.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgaWifCWJvYzRRI3Dq +0rhmNwID3+HF2VE+iD5HPd4DfPihRANCAASLKuQUat+LbcvyNYL300a1fWmH23xT +A8eICLFvcO9GKxvnNofMwkkuZvXCbuJo1HFI1qASrh1w+/tfCHEPsHyw +-----END PRIVATE KEY-----