android +j2ee实现JSSE的通信

JSSE(JAVA安全套接字扩展,JAVA Secure Socket Extension)是SSL和TLS的纯Java实现,,通过它可以透明地提供数据加密、服务器认证、信息完整性等功能,就像使用普通的套接字一样使用安全套接字。

开始前的准备

密钥格式

SSL/TLS协议通信就必须涉及到密钥和数字证书。
在Java支持JKS,JCEKS和PKCS#12格式的密钥。但是android不支持JKS,如果入到JKS文件,我们可以把他转换为BKS文件。

JKS文件(通常为.jks或.keystore,扩展名无关)可以通过Java原生工具——KeyTool生成;
JCKES文件也是JAVA中常用的密钥格式。JKS的Provider是SUN,在每个版本的JDK中都有,JCEKS的Provider是SUNJCE,1.4后我们都能够直接使用它。
PKCS#12文件(通常为.p12或.pfx,意味个人信息交换文件),可以通过OpenSSL工具产生。
BKS文件是android单独支持的文件。可以和JKS文件转换。

文件之间的关系


.cer格式文件俗称证书,但这个证书中没有私钥,只包含了公钥;
.pfx格式文件不仅包含了公钥,还包含了私钥,当然这个私钥是加密的,不输入密码是解不了密的;
.jks格式文件表示java密钥存储器(javakey store),它可以同时容纳N个公钥跟私钥,是一个密钥库;
.keystore格式文件其实跟.jks基本是一样的;
.truststore格式文件表示信任证书存储库,它和.keystore是一样的。仅仅包含了通信对方的公钥,当然你可以直接把通信对方的jks作为信任库。

使用SSL/TLS协议通信,如果是双向认证的话,则需要客户端和服务端各自有一组自己的密钥(keyStore)以及信任文件(trustStore),当然可以使用keyStore代替trustStore免去证书相互导入的麻烦。java中的类图如下(这里的keyStore是JDK中的keyStore。android内部也有一个keyStore,这里不去管它)

UML

  • 通信核心类——SSLSocket和SSLServerSocket。对于使用过socket进行通信开发的朋友比较好理解,它们对应的就是Socket与ServerSocket,只是表示实现了SSL协议的Socket和ServerSocket,同时它们也是Socket与ServerSocket的子类。SSLSocket负责的事情包括设置加密套件、管理SSL会话、处理握手结束时间、设置客户端模式或服务器模式。
  • 客户端与服务器端Socket工厂——SSLSocketFactory和SSLServerSocketFactory。在设计模式中工厂模式是专门用于生产出需要的实例,这里也是把SSLSocket、SSLServerSocket对象创建的工作交给这两个工厂类。
  • SSL会话——SSLSession。安全通信握手过程需要一个会话,为了提高通信的效率,SSL协议允许多个SSLSocket共享同一个SSL会话,在同一个会话中,只有第一个打开的SSLSocket需要进行SSL握手,负责生成密钥及交换密钥,其余SSLSocket都共享密钥信息。
  • SSL上下文——SSLContext。它是对整个SSL/TLS协议的封装,表示了安全套接字协议的实现。主要负责设置安全通信过程中的各种信息,例如跟证书相关的信息。并且负责构建SSLSocketFactory、SSLServerSocketFactory和SSLEngine等工厂类。
  • SSL非阻塞引擎——SSLEngine。假如你要进行NIO通信,那么将使用这个类,它让通过过程支持非阻塞的安全通信。
  • 密钥管理器——KeyManager。此接口负责选择用于证实自己身份的安全证书,发给通信另一方。KeyManager对象由KeyManagerFactory工厂类生成。
  • 信任管理器——TrustManager。此接口负责判断决定是否信任对方的安全证书,TrustManager对象由TrustManagerFactory工厂类生成。

证书

  • 生成服务器证书库
    这里的地址需要改为服务器的ip,否则容易出错
keytool -validity 365 -genkey -v -alias server -keyalg RSA -keystore E:\test1\T1\server.keystore -dname "CN=192.168.0.036,OU=rongyiwang,O=rongyiwang,L=Shanghai,ST=Shanghai,c=cn" -storepass 123456 -keypass 123456
  • 生成客户端证书库
keytool -validity 365 -genkeypair -v -alias client -keyalg RSA -storetype PKCS12 -keystore E:\test1\T1\client.p12 -dname "CN=client,OU=rongyiwang,O=rongyiwang,L=Shanghai,ST=Shanghai,c=cn" -storepass 123456 -keypass 123456
  • 从客户端证书库中导出客户端证书
keytool -export -v -alias client -keystore E:\test1\T1\client.p12 -storetype PKCS12 -storepass 123456 -rfc -file E:\test1\T1\client.cer
  • 从服务器证书库中导出服务器证书
keytool -export -v -alias server -keystore E:\test1\T1\server.keystore -storepass 123456 -rfc -file E:\test1\T1\server.cer
  • 生成客户端信任证书库(由服务端证书生成的证书库)
    这里我直接生产的bks类型的文件
keytool -import -v -alias server -file E:\test1\T1\server.cer -keystore E:\test1\T1\client.truststore -storepass 123456 -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
  • 将客户端证书导入到服务器证书库(使得服务器信任客户端证书)
keytool -import -v -alias client -file E:\test1\T1\client.cer -keystore E:\test1\T1\serverytrust.keystore -storepass 123456
  • 查看证书库中的全部证书
keytool -list -keystore E:\test1\T1\server.keystore -storepass 123456

服务端

首先加载自己的密钥和信任密钥
1.keyStore


           KeyStore serverKeyStore = KeyStore.getInstance("JKS");  
           serverKeyStore.load(new FileInputStream(serverKeyStoreFile), serverKeyStorePwd.toCharArray());  

2.trustStore


           KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS");  
           serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray());  

3.建立SSLServerSocket

           KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
           kmf.init(serverKeyStore, catServerKeyPwd.toCharArray());  
     
           TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());  
           tmf.init(serverTrustKeyStore);  
     
           SSLContext sslContext = SSLContext.getInstance("TLSv1.2");  
           sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);  
     
           SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();  
           SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(18080);  
           sslServerSocket.setNeedClientAuth(true);  

4.到了这里基本就和不同Socket编程差不多了,监听SSLServerSocket即可

 while (true){
        SSLSocket s = (SSLSocket) sslServerSocket.accept();
         if(s!=null){
            // do something
         }
}

客户端

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容