首页云计算 正文

Netty实现双向认证SSL连接的解决方案

2024-11-19 5 0条评论
  1. 首页
  2. 证书相关
  3. Netty实现双向认证SSL连接的解决方案

Netty实现双向认证SSL连接的解决方案

发布日期:2017-03-17

什么是Netty?

Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。

也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。

Netty实现双向认证SSL连接的解决方案

1. 前期准备工作

双向证书认证的双方称为client和server,首先为client和server生成证书。由于仅仅是自己学习使用,因此可以在本地自建一个CA,然后用CA的证书分别签发client和server的证书。CA的创建和签发使用OpenSSL。
在windows环境上安装OpenSSL,然后依据OpenSSL目录下的openssl.cnf中[ CA_default ]的配置创建相应的文件夹和文件

[html]

demoCA/ —- CA的根目录

|– newcerts/—- CA签发出去的证书

|– private/ —- CA自己的私钥,默认名称是cakey.pem

|– serial —- 存放证书序列号的文件

|– index.txt —- 签发过的证书的记录,文本文件

 

serial这个文件中可以初始写入一行记录,包含两个字符01,表示下一个签发的证书采用的序列号是01
接下来生成CA自己的公私钥(public/private key),生成证书签名请求(CSR, Certificate Signing Request)文件并对该请求进行自签名
在openssl的根目录下运行

[html]

openssl genrsa -out ./demoCA/private/cakey.pem 2048

genrsa —- 同时生成public key和private key
很多人将genrsa解释为只生成private key,这是不对的。可以用下面的命令从文件中解出公钥

[html]

openssl rsa -in cakey.pem -pubout > capublickey.pub

 

注意最后的数字2048表示生成的RSA公私钥的长度

JDK7中对证书检查要求公钥的长度最少为1024位,否则会抛出异常

Java.security.cert.CertPathValidatorException: Algorithm constraints check failed
该长度限制是可以配置的,配置文件路径是JAVA_HOME/jre/lib/security/java.security
jdk.certpath.disabledAlgorithms=MD2, RSA keySize < 1024
然后用上面生成的公私钥文件创建一个证书签名请求文件

openssl req -new -key ./demoCA/private/cakey.pem -out careq.pem

req —- 创建CSR或者证书
-key —- openssl从这个文件中读取private key
careq.pem的内容格式是

[html]

—–BEGIN CERTIFICATE REQUEST—–

MIICnzCCAYcCAQAwWjELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlpKMQswCQYDVQQH

… …

ZYu4AZp0VzqnQzCTeYTbC+AsA0RrPVjr95Il46AHvhq2JQpFw8DhrS8Ja1VburI4

ngFK

—–END CERTIFICATE REQUEST—–

 

最后将该请求文件给CA机构做签名,但我们现在是想在本地建CA,因此自己对该文件进行自签名即可。

[html]

openssl ca -selfsign -in careq.pem -out cacert.pem

其实,上面生成CSR然后做自签名的两个步骤可合并到一步完成

[html]

openssl req -new -x509 -key ./demoCA/private/cakey.pem -out cacert.pem

至此,我们已经建立了自己的CA,接下去来分别签发client和server的证书。

创建client和server的证书、key store和trust store

以创建client的证书为例。由于jdk自带的keytool工具可以方便的创建key store和公私钥,因此公私钥和csr的创建直接使用keytool
key store和trust store分别对应于ssl握手证书认证中自己的证书和自己所信任的证书列表,二者的文件格式相同,不同之处是key store里面包含ssl握手一方的公私钥和证书,trust store里面包含ssl握手一方所信任的证书,一般没有这些证书所对应的私钥

生成client的keystore 和key pair

[html]

keytool -genkey -alias client -keyalg RSA -keystore client.keystore -keysize 2048

生成csr

[html]

 

keytool -certreq -alias client -keystore client.keystore -file client.csr

用本地CA对该csr签名
client证书中我们想添加证书的一项扩展,比如client id,用来区分client的身份,因此需要额外的一份扩展文件client.cnf,内容如下

[html]

 

[v3_req]

1.2.3.412=ASN1:UTF8String:0000001444

可以将该csr和client.cnf文件拷贝到openssl根目录下,运行

[html]

openssl ca -in client.csr -out client.pem -config ./openssl.cnf -extensions v3_req -extfile client.cnf

将签过名的client.pem导入到keystore文件中
在导入之前,需要先将CA的证书导入keystore文件

[html]

 

keytool -keystore client.keystore -importcert -alias CA -file cacert.pem

然后导入client自己的证书。注意alias是client,与生产keystore和key pair的必须匹配

[html]

keytool -keystore client.keystore -importcert -alias client -file client.pem

 

keystore文件内容的查看可以使用
keytool -list -v -keystore client.keystore
或者使用可视化工具KeyStore Explorer查看

  1. 创建client的trust store
    由于server的证书也是本地CA签发的,因此client只要信任CA的证书那么自然会信任CA签发出的证书,所以我们只需将CA的证书导入trust store即可

[html]

<span style=”white-space:pre”>    </span>keytool -import -alias cacert -file cacert.pem -keystore clienttruststore.keystore

由于clienttruststore.keystore文件尚不存在,此命令首先创建该文件并将CA的证书导入该trust store

server的证书和key store和trust store可类似创建

[html]

keytool -genkey -alias server -keyalg RSA -keystore server.keystore -keysize 2048

keytool -certreq -alias server -keystore server.keystore -file server.csr

 

openssl ca -in server.csr -out server.pem -config ./openssl.cnf

 

keytool -keystore server.keystore -importcert -alias CA -file cacert.pem

keytool -keystore server.keystore -importcert -alias server -file server.pem

keytool -import -alias ca -file cacert.pem -keystore servertruststore.keystore

 

2. 创建SSL通讯的client和server

由于netty 5现在只有alpha版本,因此保险起见使用4.0.24.final版本的netty。
netty的SSLContext提供了newClientContext来为client创建ssl context,但查看其源码未发现能支持双向认证,即client端的ssl context只接收一个trust store,而不能指定自己的证书以供server端校验。仿照netty example下的securechat的ssl实现但做了修改
首先创建一个能提供client和server的ssl context的工具类,分别加载server和client的key store和trust store里面的证书

[java]

public class SslContextFactory

{

private static final String     PROTOCOL    = “TLS”;    // TODO: which protocols will be adopted?

private static final SSLContext SERVER_CONTEXT;

private static final SSLContext CLIENT_CONTEXT;

 

static

{

SSLContext serverContext = null;

SSLContext clientContext = null;

 

String keyStorePassword = “aerohive”;

try

{

KeyStore ks = KeyStore.getInstance(“JKS”);

ks.load(SslContextFactory.class.getClassLoader().getResourceAsStream(“cert\\server.keystore”), keyStorePassword.toCharArray());

 

// Set up key manager factory to use our key store

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

kmf.init(ks, keyStorePassword.toCharArray());

 

// truststore

KeyStore ts = KeyStore.getInstance(“JKS”);

ts.load(SslContextFactory.class.getClassLoader().getResourceAsStream(“cert\\servertruststore.keystore”), keyStorePassword.toCharArray());

 

// set up trust manager factory to use our trust store

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

tmf.init(ts);

 

// Initialize the SSLContext to work with our key managers.

serverContext = SSLContext.getInstance(PROTOCOL);

serverContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

 

catch (Exception e)

{

throw new Error(“Failed to initialize the server-side SSLContext”, e);

}

 

try

{

// keystore

KeyStore ks = KeyStore.getInstance(“JKS”);

ks.load(SslContextFactory.class.getClassLoader().getResourceAsStream(“cert\\client.keystore”), keyStorePassword.toCharArray());

 

// Set up key manager factory to use our key store

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

kmf.init(ks, keyStorePassword.toCharArray());

 

// truststore

KeyStore ts = KeyStore.getInstance(“JKS”);

ts.load(SslContextFactory.class.getClassLoader().getResourceAsStream(“cert\\clienttruststore.keystore”), keyStorePassword.toCharArray());

 

// set up trust manager factory to use our trust store

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

tmf.init(ts);

clientContext = SSLContext.getInstance(PROTOCOL);

clientContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

catch (Exception e)

{

throw new Error(“Failed to initialize the client-side SSLContext”, e);

}

 

SERVER_CONTEXT = serverContext;

CLIENT_CONTEXT = clientContext;

}

 

public static SSLContext getServerContext()

{

return SERVER_CONTEXT;

}

 

public static SSLContext getClientContext()

{

return CLIENT_CONTEXT;

}

… …

}

 

io.netty.example.securechat.SecureChatClientInitializer类的构造器接收一个io.netty.handler.ssl.SslContext类型的对象,这个SslContext的对象最终被用来创建SslHandler,而上面factory产生的是javax.NET.ssl.SSLContext的对象,因此可以做改动如下

[java]

publicclass ClientInitializer extends ChannelInitializer

{

privatefinal trustauth.cn.ssl.SSLContext  sslCtx;

public ClientInitializer(trustauth.cn.ssl.SSLContext sslCtx)

{

this.sslCtx = sslCtx;

}

 

@Override

public void initChannel(SocketChannel ch) throws Exception

{

ChannelPipeline pipeline = ch.pipeline();

 

SSLEngine sslEngine = sslCtx.createSSLEngine(Client.HOST, Client.PORT);

sslEngine.setUseClientMode(true);

pipeline.addLast(new SslHandler(sslEngine));

 

// On top of the SSL handler, add the text line codec.

pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));

pipeline.addLast(new StringDecoder());

pipeline.addLast(new StringEncoder());

 

// and then business logic.

pipeline.addLast(new ClientHandler());

}

}

 

最后添加jvm参数

[html]

-Dtrustauth.cn.debug=ssl,handshake

SSL证书采用了技术含量比较高的加密技术。日后GDCA(数安时代)将会持续为大家推荐更多关于SSL证书的技术知识。让大家正确认识SSL证书,快速无误部署HTTPS安全协议。更多资讯,请关注GDCA。

上一篇:Openssl生成csr的解决方案

下一篇:关于SSL证书双向认证的原理过程

相关新闻

  • SSL证书对网站访问速度有影响吗
  • 个人隐私数据泄露有哪些危害?如何预防?
  • 部署SSL证书有哪些常见的错误
  • 国际证书、国产证书和国密证书
  • 游戏开发为什么离不开代码签名?
  • 僵尸网络攻击手法与防范方式
  • SSL证书助力保障网络数据安全
  • 网站加密与不加密区别
  • SSL证书有哪些类型和价格差异
  • ca机构颁发的证书包括那些内容呢?
文章版权及转载声明

本文作者:admin 网址:http://news.edns.com/post/112803.html 发布于 2024-11-19
文章转载或复制请以超链接形式并注明出处。

取消
微信二维码
微信二维码
支付宝二维码