系统要求
1. Windows系统、Linux系统、Mac系统
2. JDK7及以上
3. JDK使用无限制的安全策略文件
TcpGmSslClient.java代码
/**
* @author https://www.doubleca.com
*/
package com.doubleca.security.gmssl.sample.mina2;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.GeneralSecurityException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.ssl.SslFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
public class TcpGmSslClient extends IoHandlerAdapter
{
private IoConnector connector;
private static IoSession session;
private IoBuffer buffer = IoBuffer.allocate(8);
private long t0;
private long t1;
private CountDownLatch counter;
public TcpGmSslClient() throws GeneralSecurityException, IOException
{
this.connector = new NioSocketConnector();
SSLContext sslContext = GmSslContextFactory.getInstance(false);
SslFilter sslFilter = new SslFilter(sslContext);
sslFilter.setUseClientMode(true);
this.connector.getFilterChain().addFirst("sslFilter", sslFilter);
this.connector.setHandler(this);
ConnectFuture connFuture = this.connector.connect(new InetSocketAddress("localhost", 18567));
connFuture.awaitUninterruptibly();
session = connFuture.getSession();
}
public void exceptionCaught(IoSession session, Throwable cause) throws Exception
{
cause.printStackTrace();
}
public void messageReceived(IoSession session, Object message) throws Exception
{
long received = ((IoBuffer) message).getLong();
if (received != this.counter.getCount())
{
System.out.println("Error !");
session.closeNow();
}
else if (this.counter.getCount() == 0L)
{
this.t1 = System.currentTimeMillis();
System.out.println("-------------> end " + (this.t1 - this.t0));
session.closeNow();
}
else
{
this.counter.countDown();
this.buffer.flip();
this.buffer.putLong(this.counter.getCount());
this.buffer.flip();
session.write(this.buffer);
}
}
public void messageSent(IoSession session, Object message) throws Exception
{
if (this.counter.getCount() % 5000L == 0L)
{
System.out.println("Sent " + this.counter + " messages");
}
}
public void sessionClosed(IoSession session) throws Exception
{
}
public void sessionCreated(IoSession session) throws Exception
{
}
public void sessionIdle(IoSession session, IdleStatus status) throws Exception
{
}
public void sessionOpened(IoSession session) throws Exception
{
}
public static void main(String[] args) throws Exception
{
TcpGmSslClient client = new TcpGmSslClient();
client.t0 = System.currentTimeMillis();
client.counter = new CountDownLatch(50000);
client.buffer.putLong(client.counter.getCount());
client.buffer.flip();
session.write(client.buffer);
int nbSeconds = 0;
while ((client.counter.getCount() > 0L) && (nbSeconds < 120))
{
client.counter.await(1L, TimeUnit.SECONDS);
nbSeconds++;
}
client.connector.dispose(true);
}
}
GmSslContextFactory.java代码
/**
* @author https://www.doubleca.com
*/
package com.doubleca.security.gmssl.sample.mina2;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import doubleca.security.gmssl.provider.DoubleCASSE;
import doubleca.security.provider.DoubleCA;
/**
*
*
*/
public class GmSslContextFactory
{
/**
* Protocol to use.
*/
private static final String PROTOCOL = "GMSSLv1.1";
private static final String KEY_MANAGER_FACTORY_ALGORITHM;
/**
*
*/
private static DoubleCASSE dcsse = new DoubleCASSE();
/**
* 用终端授权请求编码去http://www.pplic.com申请授权数据
*/
private static void generateLicRequest()
{
StringBuffer licRequest = new StringBuffer();
int result = dcsse.generateLicRequest(licRequest);
if (result == 0x70000000)
{
System.out.println("终端授权请求编码:");
System.out.println(licRequest.toString());
}
else
{
System.out.println("终端授权请求编码出错,错误编号:0x" + Integer.toHexString(result));
}
}
/**
* 用授权数据初始化dcsse
*/
private static void initLic()
{
// 获得的本机授权数据,在http://www.pplic.com授权平台获取
String licData = "ASeraPDybn/wwAABTGQnuKT71OrK0gnV/OSwjRcgHXJAtseX+Tu2kqOJCnT4r4b9/FUYOKXfJ3nsjDarus6mo+WPax6Z4W8ONonjro7Ql0WxJgIM234bdV2xBvv8pUkD/dffwZfkQ/HfjXsz4QH2+TQ0eWcUr4f2hnfNDxczJ+g88pWVUuCbcxTLWdCWW547Bp2TJ5FQt28zWxSTXqoJxXavYMffp1PnvBL9DOjKLFhqRdLVVsoiIVTsikGEgHeKrUsjmft01PqSd9ErqWEXsGpslzVzuVBjGtyQh6Arz3Ksy1wyipor+7y4KrsTuD9qxvfEjKdHm58p0BacfOHXfLe8XUKDLADIddfDyMIgAXAiUG8Zh+oRw0qDIuIgVgaRGcQ0SEWpXQbl2wCXye2B9Oa2Pr+9+/OWS4LbxWIiDOEbTA4kQT/lklQ3sfBZZJkXPJtmMQx0HgNcsrX6tkoiZC1G0c4mSkbq6k8R5dIS6KcEycS2SekKCqmNmC1yd9QC2iAXIG/pcTaGWuTzPWbU+6lfu0MMm4zL9po1wBORzpVqxsTh6hhe0URpxqPdNQOWHRp7PxaCRhJrZAh7/DiwulJwu7I42zbXdkncmwHHj07DCyJiUJScXz4tVaC/BgRV93ySirRh9gTjV61DM97pS43adyOA2U4cGNO7nm5b7JLKInE4ukuislJZHDB/5hiDRE/H48KPZNB/EsEZVcEgIXaAaRwf1jOG6pvM9qS6Pg==";
dcsse.setLicData(licData);
System.out.println("授权有效期:" + dcsse.getLicEndTime().toLocaleString());
}
static
{
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
if (algorithm == null)
{
algorithm = KeyManagerFactory.getDefaultAlgorithm();
}
KEY_MANAGER_FACTORY_ALGORITHM = algorithm;
Security.addProvider(new DoubleCA());
Security.addProvider(dcsse);
initLic();
}
/**
* GmSSL Server certificate keystore file name.
* https://www.doubleca.com
*/
private static final String DoubleCA_Server_KEYSTORE = "resources/SERVER.dcks";
/**
* GmSSL Client certificate keystore file name.
* https://www.doubleca.com
*/
private static final String DoubleCA_Client_KEYSTORE = "resources/CLIENT.dcks";
/**
* Bougus keystore password.
*/
private static final char[] DCKS_PW = {'D', 'o', 'u', 'b', 'l', 'e', 'C', 'A'};
private static SSLContext serverInstance = null;
private static SSLContext clientInstance = null;
/**
* Get SSLContext singleton.
*
* @return SSLContext
* @throws java.security.GeneralSecurityException
* @throws IOException
*
*/
public static SSLContext getInstance(boolean server) throws GeneralSecurityException, IOException
{
SSLContext retInstance = null;
if (server)
{
synchronized (GmSslContextFactory.class)
{
if (serverInstance == null)
{
try
{
serverInstance = createDoubleCAServerGmSslContext();
}
catch (Exception ioe)
{
throw new GeneralSecurityException("Can't create Server SSLContext:" + ioe);
}
}
}
retInstance = serverInstance;
}
else
{
synchronized (GmSslContextFactory.class)
{
if (clientInstance == null)
{
clientInstance = createDoubleCAClientGmSslContext(false);
}
}
retInstance = clientInstance;
}
return retInstance;
}
private static SSLContext createDoubleCAServerGmSslContext() throws GeneralSecurityException, IOException
{
// Create keystore
KeyStore ks = KeyStore.getInstance("DCKS", DoubleCA.PROVIDER_NAME);
InputStream in = null;
try
{
in = new FileInputStream(DoubleCA_Server_KEYSTORE);
ks.load(in, DCKS_PW);
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException ignored)
{
}
}
}
// Set up key manager factory to use our key store
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM, DoubleCASSE.PROVIDER_NAME);
kmf.init(ks, DCKS_PW);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM, DoubleCASSE.PROVIDER_NAME);
tmf.init(ks);
// Initialize the SSLContext to work with our key managers.
SSLContext sslContext = SSLContext.getInstance(PROTOCOL, DoubleCASSE.PROVIDER_NAME);
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return sslContext;
}
private static SSLContext createDoubleCAClientGmSslContext(boolean clientAuth) throws GeneralSecurityException, IOException
{
SSLContext sc = SSLContext.getInstance(PROTOCOL, DoubleCASSE.PROVIDER_NAME);
KeyManager[] clientCertManager = null;
if (clientAuth == true)
{
// 双向认证
// 客户端证书
KeyStore sm2ClientKeyStore = KeyStore.getInstance("DCKS");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM, DoubleCASSE.PROVIDER_NAME);
InputStream in = null;
try
{
in = new FileInputStream(DoubleCA_Client_KEYSTORE);
sm2ClientKeyStore.load(in, DCKS_PW);
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException ignored)
{
}
}
}
kmf.init(sm2ClientKeyStore, DCKS_PW);
clientCertManager = kmf.getKeyManagers();
}
// 信任管理器,服务端根证书要放在这里,否则需要忽略服务器证书的信任
KeyStore sm2TrustKeyStore = KeyStore.getInstance("DCKS");
InputStream in = null;
try
{
in = new FileInputStream(DoubleCA_Client_KEYSTORE);
sm2TrustKeyStore.load(in, DCKS_PW);
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException ignored)
{
}
}
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_MANAGER_FACTORY_ALGORITHM, DoubleCASSE.PROVIDER_NAME);
tmf.init(sm2TrustKeyStore);
sc.init(clientCertManager, tmf.getTrustManagers(), null);
return sc;
}
}
GmTrustManagerFactory.java代码
/**
* @author https://www.doubleca.com
*/
package com.doubleca.security.gmssl.sample.mina2;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactorySpi;
import javax.net.ssl.X509TrustManager;
/**
* @author https://www.doubleca.com
*
*/
class GmTrustManagerFactory extends TrustManagerFactorySpi
{
static final X509TrustManager X509 = new X509TrustManager()
{
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
{
}
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[0];
}
};
static final TrustManager[] X509_MANAGERS = new TrustManager[]{X509};
public GmTrustManagerFactory()
{
}
@Override
protected TrustManager[] engineGetTrustManagers()
{
return X509_MANAGERS;
}
@Override
protected void engineInit(KeyStore keystore) throws KeyStoreException
{
// noop
}
@Override
protected void engineInit(ManagerFactoryParameters managerFactoryParameters) throws InvalidAlgorithmParameterException
{
// noop
}
}
运行结果:
------ http://www.DoubleCA.com ---- 大宝CA ------
------- Watchdata & DoubleCA -------
授权有效期:2999-2-20 1:01:01
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 50000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 45000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 40000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 35000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 30000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 25000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 20000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 15000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 10000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 5000] messages
Sent java.util.concurrent.CountDownLatch@6cf56dcc[Count = 0] messages
DCKS国密SSL通信证书和密钥文件在 大宝CA 网站上免费申请
国密SSL的JAR包需要授权使用,generateLicRequest函数生成终端授权请求编码,获取到授权数据放在initLic函数中即可完成授权,申请授权数据的具体步骤:
1. 访问 PP商业软件自主授权平台
2. 点击“应用方入口”
3. “软件1编号”填写:66-61F74672E9534ACEAF86EEFB8D8E75D0,免费授权码数量有限,获取请联系QQ:1337588982,将授权码写在“授权码”输入框内,“终端请求授权编码”框内复制generateLicRequest函数生成的终端授权请求编码
4. 提交授权请求后页面会生成授权数据,将授权数据复制到initLic函数中即可完成授权
最新版本JAVA NIO MINA2调用大宝CA版本JSSE访问国密SSL安全通道的JAR包和示例代码下载地址:https://download.csdn.net/download/upset_ming/11453849
授权码保留好,如果授权数据丢失,可凭授权码在 PP商业软件自主授权平台 回授权数据