Android開發(fā)之基于Netty的TCP連接中使用SSL加密

1 Introduction

數(shù)據(jù)安全在網(wǎng)絡(luò)通信中是非常重要的一個方面。為了支持 SSL/TLS,Java 提供了 javax.net.ssl包下的類SslContext 和 SslEngine 。在Netty框架下,I/O數(shù)據(jù)在ChannelPipeline中被管道中的ChannelHandler處理并轉(zhuǎn)發(fā)給下一個ChannelHandler。自然而然地,Netty也提供了ChannelHandler的實現(xiàn)SslHandler來支持SSL, 有一個內(nèi)部 SslEngine 做實際的工作。

2 Steps

首先看看SslHandler的構(gòu)造函數(shù):

  public SslHandler(SSLEngine engine) {
        this(engine, false);
    }

    public SslHandler(SSLEngine engine, boolean startTls) {
        this(engine, startTls, ImmediateExecutor.INSTANCE);
    }

不難發(fā)現(xiàn),我們需要一個SSLEngine對象來構(gòu)建SslHandler。根據(jù)資料可以知道,需要根據(jù)已初始化的 SSLContext 來調(diào)用 SSLContext.createSSLEngine() 即可創(chuàng)建 SSLEngine
所以基于Netty框架的在TCP連接中使用SSL/TLS加密的流程如下:

  1. 在代碼中導(dǎo)入證書,并使用該證書構(gòu)造SSLContext
  2. 調(diào)用SSLContext對象的createSSLEngine()創(chuàng)建 SSLEngine
  3. SSLEngine對象去初始化Netty的SslHandler
  4. 在Netty的ChannelInitializer.initChannel()中,往管道(pipeline)中安裝SslHandler。

3 Usage

3.1 導(dǎo)入證書

public SSLContext getClientSSLContext(){
  KeyStore trustKeyStore= KeyStore.getInstance("JKS");// 訪問Java密鑰庫,JKS是keytool創(chuàng)建的Java密鑰庫
  InputStream keyStream = MyApplication.getAppContext().getAssets().open("key.jks");//打開證書文件(.jks格式)
  char keyStorePass[]="12345678".toCharArray();  //證書密碼
  keyStore .load(trustKeyStore,keyStorePass);


  TrustManagerFactory trustManagerFactory =   TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore );//保存服務(wù)端的授權(quán)證書

SSLContext   clientContext = SSLContext.getInstance( "TLS");
  clientContext.init(null, trustManagerFactory.getTrustManagers(), null);

  return clientContext;
}

在上述代碼,只是實現(xiàn)了client采用trustKeyStore中的key.jks證書(包含了server的公鑰)對數(shù)據(jù)解密,如果解密成功,證明消息來自server,進(jìn)行邏輯處理。
僅僅是server->client單向的SSL認(rèn)證。
如果要實現(xiàn)server和client之間雙向的身份認(rèn)證,需要模仿trustManagerFactory的初始化來構(gòu)建一個KeyManagerFactory其中保存客戶端的私鑰,并傳入

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

具體參照 SSL雙向認(rèn)證java實現(xiàn)

3.2 添加 SslHandler

ChannelHandler在應(yīng)該初始化(ChannelInitializer.initChannel()被調(diào)用時)階段被安裝在ChannelPipeline中。

Bootstrap的介紹參考Android開發(fā)之使用Netty進(jìn)行Socket編程(二)
Boostrap的初始化參考Android開發(fā)之使用Netty進(jìn)行Socket編程(三)

  bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                SSLEngine engine = getClientSSLContext().createSSLEngine();
                engine.setUseClientMode(true);
                pipeline.addFirst("ssl", new SslHandler(engine));
                
                //....再添加其他的ChannelHandler
                pipeline.addLast(nettyChannelHandler);
            }
        });

在大多數(shù)情況下,SslHandler 將成為 ChannelPipeline 中的第一個 ChannelHandler,所以調(diào)用了pipeline.addFirst() 。這將確保所有其他 ChannelHandler 應(yīng)用他們的邏輯到數(shù)據(jù)后加密后才發(fā)生,從而確保他們的變化是安全的。

Relative

  1. essential netty in action--使用 SSL/TLS 加密 Netty 程序
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容