依赖引入

<dependency>
     <groupId>io.netty</groupId>
     <artifactId>netty-tcnative-boringssl-static</artifactId>
     <version>2.0.26.Final</version>
</dependency>

这个依赖默认是64位的,32位jdk是无法运行的,这里提供一个32位jar连接,系统最低要求win7

https://cloud.189.cn/t/ZRRBvmRzmEnu

生成客户端和服务端密钥

CA 证书

创建CA PSCK1私钥

openssl genrsa -out ca/ca-key1.pem 1024

CA PSCK1转PSCK8私钥

openssl pkcs8 -topk8 -inform PEM -in ca/ca-key1.pem -outform pem -nocrypt -out ca/ca-key.pem

CA私钥 创建CSR请求(此处会要求证书相关信息参数)

openssl req -new -out ca/ca-req.csr -key ca/ca-key.pem -config openssl.cnf

生成CA的X509证书

openssl x509 -req -in ca/ca-req.csr -out ca/ca-cert.pem -signkey ca/ca-key.pem -days 3650

服务端证书

创建服务器PSCK1私钥

openssl genrsa -out server/server-key.pem 1024

服务器 PSCK1转PSCK8私钥

openssl pkcs8 -topk8 -inform PEM -in server/server-key.pem -outform pem -nocrypt -out server/server-pkcs8.pem

服务器私钥 创建CSR请求(此处会要求证书相关信息参数)

openssl req -new -out server/server-req.csr -key server/server-pkcs8.pem -config openssl.cnf

生成服务器的X509证书

openssl x509 -req -in server/server-req.csr -out server/server-cert.pem -signkey server/server-key.pem -CA ca/ca-cert.pem -CAkey ca/ca-key.pem -CAcreateserial -days 3650

客户端证书

创建客户端PSCK1私钥

openssl genrsa -out client/client-key.pem 1024

客户端 PSCK1转PSCK8私钥

openssl pkcs8 -topk8 -inform PEM -in client/client-key.pem -outform pem -nocrypt -out client/client-pkcs8.pem

客户端私钥 创建CSR请求(此处会要求证书相关信息参数)

openssl req -new -out client/client-req.csr -key client/client-pkcs8.pem -config openssl.cnf

生成客户端的X509证书

openssl x509 -req -in client/client-req.csr -out client/client-cert.pem -signkey client/client-key.pem -CA ca/ca-cert.pem -CAkey ca/ca-key.pem -CAcreateserial -days 3650

服务端代码

public class FidsServerChannelInit extends ChannelInitializer<SocketChannel> {

    @Resource
    FidsServerHandler fidsServerHandler;

    public void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();

        pipeline.addFirst(getSslHandler());
        pipeline.addLast(ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP));
        pipeline.addLast(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
        pipeline.addLast(new ObjectEncoder());
        pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(getClass().getClassLoader())));
        pipeline.addLast(fidsServerHandler);
    }

    /**
     * 通信加密
     *
     * @return
     */
    private SslHandler getSslHandler() {
        try {
            InputStream key = new ClassPathResource("cert/server/server-pkcs8.pem").getInputStream();
            InputStream cert = new ClassPathResource("cert/server/server-cert.pem").getInputStream();
            InputStream ca = new ClassPathResource("cert/ca/ca-cert.pem").getInputStream();

            SslContext sslContext = SslContextBuilder.forServer(cert, key)
                    .trustManager(ca)
                    .clientAuth(ClientAuth.REQUIRE)
                    .sslProvider(SslProvider.OPENSSL)
                    .build();

            return sslContext.newHandler(ByteBufAllocator.DEFAULT);
        } catch (Exception e) {
            log.error("初始化SSL context 错误", e);
        }

        return null;
    }
}

客户端代码

public class FidsClientChannelInit extends ChannelInitializer<SocketChannel> {

    @Resource
    private FidsClientHandler fidsClientHandler;

    @Resource
    private PrependClientIdEncoder prependClientIdEncoder;

    public static SslHandler getSslHandler() {
        try {
            InputStream key = new ClassPathResource("cert/client/client-pkcs8.pem").getInputStream();
            InputStream cert = new ClassPathResource("cert/client/client-cert.pem").getInputStream();
            InputStream ca = new ClassPathResource("cert/ca/ca-cert.pem").getInputStream();

            SslContext sslContext = SslContextBuilder.forClient()
                    .trustManager(ca)
                    .keyManager(cert, key)
                    .sslProvider(SslProvider.OPENSSL)
                    .build();

            return sslContext.newHandler(ByteBufAllocator.DEFAULT);
        } catch (Exception e) {
            log.error("初始化SSL context 错误",e);
        }

        return null;
    }

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        pipeline.addLast(ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP));
        pipeline.addLast(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
        pipeline.addLast(prependClientIdEncoder);
        pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(getClass().getClassLoader())));
        pipeline.addLast(fidsClientHandler);
        pipeline.addFirst(getSslHandler());
    }
}

后记

不要使用JDK自带的ssl加密,性能很差,以本代码为例会增加3~4秒额外延时。



JAVA      加密 NETTY

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!