腾讯Kona国密套件是由腾讯云安全团队开发的一套加密解决方案,采用国密算法实现数据加密和安全通信。国密算法是由中国政府推动的一套国家密码标准,采用了一系列经过严格测试和验证的密码算法,包括SM2、SM3、SM4等,具有较高的安全性和可靠性。
通道加密是在网络通信中对数据进行加密保护,以防止数据在传输过程中被窃取、篡改或者伪造。采用腾讯Kona国密套件进行通道加密具有以下重要性:
数据安全保障: 通道加密可以有效保护数据在传输过程中的安全性,确保数据不会被未经授权的人员窃取或篡改,保障数据的机密性和完整性。
符合法规要求: 针对一些行业或国家的法规要求数据必须采用特定的加密算法或者实现特定的加密标准,采用腾讯Kona国密套件可以满足相关的法规合规要求。
防止中间人攻击: 通道加密可以有效防止中间人攻击,确保通信双方的身份认证和通信内容的安全性,避免数据被篡改或者劫持。
保护隐私数据: 对于一些敏感数据或者个人隐私数据的传输,通道加密可以有效保护数据的隐私性,防止敏感信息泄露。
增强系统可靠性: 采用通道加密可以增强系统的安全性和可靠性,降低系统遭受攻击和数据泄露的风险,提升系统的稳定性和可用性。
Kona 国密套件
背景:
- 国家密码标准推动: 中国政府自2010年开始推动国家密码算法的研发和标准化工作,旨在提升国家信息安全水平,保护国家核心利益和重要数据。
- 国际安全形势: 随着互联网的发展和应用范围的扩大,网络安全威胁不断增加,对于数据的保护和加密需求日益迫切。 行业规范和法律法规要求:
- 一些行业或国家的法规要求特定领域的数据必须采用特定的加密算法或实现特定的加密标准,为了满足法规合规要求,需要提供符合国内国密算法标准的加密解决方案。
特点:
- 符合国内国密标准:
Kona国密套件采用的加密算法符合中国国家密码管理局颁布的相关国密标准,包括SM2、SM3、SM4等算法,能够满足国内各行业的加密需求。 - 高安全性和可靠性: 国密算法经过严格的安全性评估和验证,具有较高的安全性和可靠性,能够有效保护数据的机密性和完整性。
- 丰富的应用场景:
Kona国密套件可广泛应用于各种网络通信场景,包括Web安全、移动应用、物联网、云计算等领域,为不同行业和领域的应用提供安全保障。 - 性能优化和可扩展性: Kona国密套件针对国密算法进行了性能优化和功能扩展,能够满足大规模应用的性能需求,并提供灵活的配置和定制化功能。
- 与国际标准兼容: Kona国密套件在满足国内国密标准的同时,也兼容国际通用的加密算法和协议,可以与国际标准的加密产品进行互操作和兼容。
Kona 国密套件提供的加密算法和协议支持概述
- SM2非对称加密算法: SM2是一种国家标准的非对称加密算法,适用于数字签名、密钥交换等场景,具有较高的安全性和性能。
- SM3哈希算法: SM3是一种国家标准的哈希算法,适用于消息摘要和数据完整性校验,具有较高的安全性和抗碰撞性。
- SM4对称加密算法: SM4是一种国家标准的对称加密算法,适用于数据加密和解密,具有较高的安全性和性能。
- 国密SSL/TLS协议支持:
Kona国密套件提供了对基于国密算法的SSL/TLS协议的支持,包括服务器端和客户端的实现,能够保护网络通信的安全性和机密性。 - 国密IPSec协议支持:
Kona国密套件还提供了对基于国密算法的IPSec协议的支持,包括VPN网关和终端设备的实现,能够保护企业内部网络和互联网之间的通信安全。 - 国密HTTPS协议支持: Kona国密套件支持基于国密算法的HTTPS协议,能够保护Web应用程序的安全通信,包括网站和移动应用等。
- 国密SMQ消息队列协议支持: Kona国密套件提供了对基于国密算法的SMQ消息队列协议的支持,能够保护消息传输的安全性和机密性。
准备工作
上图是对项目的简介,通过上图可知如果我们要是想实现服务端可以看“Kona-demo”模块,“kona-ssl”模块的test中有很多使用案例,本文主要是对普通socket进行通道加密所以我选择查看Netty得Demo
下载项目源代码,重点查看kona-ssl模块的测试集
这个类中是包裹netty实现的socket通讯,内容包含客户端与服务端。找到测试用例
@Test
public void tlcpDemo() throws Exception {
// Output debug info.
// System.setProperty("com.tencent.kona.ssl.debug", "all");
// Add providers.
TestUtils.addProviders();
// Run Netty server, which supports TLCP connection.
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ServerChannelInitializer(
createJdkContext(false)));
ChannelFuture channelFuture = bootstrap.bind(0).sync();
int port = ((InetSocketAddress) channelFuture.channel()
.localAddress()).getPort();
runClient(port);
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
// Run Netty client, which supports TLCP connection.
private void runClient(int port) throws Exception {
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workerGroup);
bootstrap.channel(NioSocketChannel.class);
bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
bootstrap.handler(new ClientChannelInitializer(
createJdkContext(true)));
ChannelFuture future = bootstrap.connect("127.0.0.1", port).sync();
future.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
}
在测试客户端的代码中发现“createJdkContext(true)”,继续追进到如下代码
private static SSLContext createContext() throws Exception {
KeyStore trustStore = createTrustStore(CA, null);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "KonaSSL");
tmf.init(trustStore);
KeyStore keyStore = createKeyStore(SIGN_EE, SIGN_EE_ID, SIGN_EE_KEY, ENC_EE, ENC_EE_ID, ENC_EE_KEY);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509", "KonaSSL");
kmf.init(keyStore, PASSWORD.toCharArray());
SSLContext context = SSLContext.getInstance("TLCPv1.1", "KonaSSL");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
return context;
}
找到这一段代码,我们可以通过此处获取SSLContext 然后生成socket。
创建一个maven项目,并且添加相关依赖
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.47</version>
</dependency>
<dependency>
<groupId>com.tencent.kona</groupId>
<artifactId>kona-ssl</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>com.tencent.kona</groupId>
<artifactId>kona-provider</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>com.tencent.kona</groupId>
<artifactId>kona-pkix</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>com.tencent.kona</groupId>
<artifactId>kona-crypto</artifactId>
<version>1.0.10</version>
</dependency>
实现通道加密
需要把源码中的包复制下来
package org;
import com.tencent.kona.sun.security.x509.SMCertificate;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
/**
* A comprehensive demo for TLCP with Netty.
*/
public class TLCPWithNettyDemo {
//region CA && CA KEY
private static final String CA = Utils.readFileToString("src/main/resources/root.pem");
// The CA private key.
private static final String CA_KEY = "MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgPWgd9v0oxNwV1/nL\n" + "UVaZuqCxxJmSeyVzvaWgb4lxB3qhRANCAAS/2B8sH0dPDeYEqxRzT3WIRF3sWSU9\n" + "m4x0Mx30ZsaXGttBIUqrNHV96AEDeI/Y58nNj/3+RYLYAtBTKsvQ5Mhh";
//endregion
//region SIGN_EE SING_EE_ID KEY ENC_EE ENC_KEY
private static final String SIGN_EE = Utils.readFileToString("src/main/resources/sign.pem");
private static final String SIGN_EE_ID = "1234567812345678";
// The sign certificate private key.
private static final String SIGN_EE_KEY = Utils.readFileToString("src/main/resources/sign.key");
private static final String ENC_EE = Utils.readFileToString("src/main/resources/enc.pem");
private static final String ENC_EE_ID = "1234567812345678";
// The enc certificate private key.
private static final String ENC_EE_KEY = Utils.readFileToString("src/main/resources/enc.key");
//endregion
private static final String PASSWORD = "password";
public static SSLContext createContext() throws Exception {
KeyStore trustStore = createTrustStore(CA, null);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "KonaSSL");
tmf.init(trustStore);
KeyStore keyStore = createKeyStore(SIGN_EE, SIGN_EE_ID, SIGN_EE_KEY, ENC_EE, ENC_EE_ID, ENC_EE_KEY);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509", "KonaSSL");
kmf.init(keyStore, PASSWORD.toCharArray());
SSLContext context = SSLContext.getInstance("TLCPv1.1", "KonaSSL");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
return context;
}
private static KeyStore createTrustStore(String caStr, String caId) throws Exception {
KeyStore trustStore = KeyStore.getInstance("PKCS12", "KonaPKIX");
trustStore.load(null, null);
trustStore.setCertificateEntry("tlcp-trust-demo", loadCert(caStr, caId));
return trustStore;
}
private static KeyStore createKeyStore(String signEeStr, String signEeId, String signEeKeyStr, String encEeStr, String encEeId, String encEeKeyStr) throws Exception {
KeyStore keyStore = KeyStore.getInstance("PKCS12", "KonaPKIX");
keyStore.load(null, null);
keyStore.setKeyEntry("tlcp-sign-ee-demo", loadPrivateKey(signEeKeyStr), PASSWORD.toCharArray(), new Certificate[]{loadCert(signEeStr, signEeId)});
keyStore.setKeyEntry("tlcp-enc-ee-demo", loadPrivateKey(encEeKeyStr), PASSWORD.toCharArray(), new Certificate[]{loadCert(encEeStr, encEeId)});
return keyStore;
}
private static X509Certificate loadCert(String certPEM, String id) throws Exception {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "KonaPKIX");
X509Certificate x509Cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certPEM.getBytes()));
if (id != null && !id.isEmpty()) {
((SMCertificate) x509Cert).setId(id.getBytes(StandardCharsets.UTF_8));
}
return x509Cert;
}
private static PrivateKey loadPrivateKey(String keyPEM) throws Exception {
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(keyPEM));
KeyFactory keyFactory = KeyFactory.getInstance("EC", "KonaCrypto");
return keyFactory.generatePrivate(privateKeySpec);
}
}
删除用不到部分,综合如上。
在测试类中创建socket客户端如下
Security.addProvider(new KonaCryptoProvider());
Security.addProvider(new KonaPKIXProvider());
Security.addProvider(new KonaSSLProvider());
SSLContext sslContext = TLCPWithNettyDemo.createContext();
Socket socket = sslContext.getSocketFactory().createSocket("127.0.0.1", 15001);