系统要求
1. Windows系统、Linux系统、Mac系统
2. JDK7及以上
3. JDK使用无限制的安全策略文件
TcpGmSslServer.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.atomic.AtomicInteger;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
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.NioSocketAcceptor;
public class TcpGmSslServer extends IoHandlerAdapter
{
public static final int PORT = 18567;
public static final int MAX_RECEIVED = 50000;
private static long t0;
private AtomicInteger nbReceived = new AtomicInteger(0);
public void exceptionCaught(IoSession session, Throwable cause) throws Exception
{
cause.printStackTrace();
session.closeNow();
}
public void messageReceived(IoSession session, Object message) throws Exception
{
int nb = this.nbReceived.incrementAndGet();
if (nb == 1)
{
t0 = System.currentTimeMillis();
}
if (nb == MAX_RECEIVED)
{
long t1 = System.currentTimeMillis();
System.out.println("-------------> end " + (t1 - t0));
}
if (nb % 5000 == 0)
{
System.out.println("Received " + nb + " messages");
}
session.write(message);
}
public void sessionClosed(IoSession session) throws Exception
{
System.out.println("Session closed...");
System.out.println("Nb message received : " + this.nbReceived.get());
this.nbReceived.set(0);
}
public void sessionCreated(IoSession session) throws Exception
{
System.out.println("Session created...");
}
public void sessionIdle(IoSession session, IdleStatus status) throws Exception
{
System.out.println("Session idle...");
}
public void sessionOpened(IoSession session) throws Exception
{
System.out.println("Session Opened...");
}
public TcpGmSslServer() throws IOException, GeneralSecurityException
{
NioSocketAcceptor acceptor = new NioSocketAcceptor();
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
SslFilter sslFilter = new SslFilter(GmSslContextFactory.getInstance(true));
chain.addLast("sslFilter", sslFilter);
acceptor.setHandler(this);
acceptor.bind(new InetSocketAddress(18567));
System.out.println("Server started...");
}
public static void main(String[] args) throws Exception
{
new TcpGmSslServer();
}
}
GmSslContextFactory.java代码
/**
*
*/
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;
/**
* @author https://www.doubleca.com
*
*/
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
Server started...
Session created...
Session Opened...
Received 5000 messages
Received 10000 messages
Received 15000 messages
Received 20000 messages
Received 25000 messages
Received 30000 messages
Received 35000 messages
Received 40000 messages
Received 45000 messages
-------------> end 105305
Received 50000 messages
Session closed...
Nb message received : 50001
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/11751970
授权码保留好,如果授权数据丢失,可凭授权码在 PP商业软件自主授权平台 回授权数据