HTTPS那些事 用java實現HTTPS工做原理


         今天被問到關於https原理的問題,結果因爲知識掌握不牢靠,停留於表面,不少細節都沒法回答清楚,因而決定把https的原理弄個明白,廢話很少說,咱們先看看https的定義java

 (因爲好久未寫博客,排版有些凌亂,請諒解)git

一:什麼是https協議

     在說HTTPS以前先說說什麼是HTTP,HTTP就是咱們平時瀏覽網頁時候使用的一種協議。HTTP協議傳輸的數據都是未加密的,也就是明文的,所以使 用HTTP協議傳輸隱私信息很是不安全。爲了保證這些隱私數據能加密傳輸,因而網景公司設計了SSL(Secure Sockets Layer)協議用於對HTTP協議傳輸的數據進行加密,從而就誕生了HTTPS。SSL目前的版本是3.0,被IETF(Internet Engineering Task Force)定義在RFC 6101中,以後IETF對SSL 3.0進行了升級,因而出現了TLS(Transport Layer Security) 1.0,定義在RFC 2246。實際上咱們如今的HTTPS都是用的TLS協議,可是因爲SSL出現的時間比較早,而且依舊被如今瀏覽器所支持,所以SSL依然是HTTPS的 代名詞,但不管是TLS仍是SSL都是上個世紀的事情,SSL最後一個版本是3.0,從此TLS將會繼承SSL優良血統繼續爲咱們進行加密服務。目前 TLS的版本是1.2,定義在RFC 5246中,暫時尚未被普遍的使用。對歷史感興趣的朋友能夠參考http://en.wikipedia.org/wiki/Transport_Layer_Security,這裏有對TLS/SSL詳盡的敘述。算法

 

二:https的工做原理是什麼

     HTTPS在傳輸數據以前須要客戶端(瀏覽器)與服務端(網站)之間進行一次握手,在握 手過程當中將確立雙方加密傳輸數據的密碼信息,一般狀況下會配合數字證書實現。apache

TLS/SSL協議不只僅是一套加密傳輸的協議,更是一件通過藝術家精心設計的藝術品,TLS/SSL中使用 非對稱加密,對稱加密以及HASH算法。編程

這裏咱們先看看這上面提到的幾種技術(若是你對這些技術已經很是瞭解,那麼請跳過該段落,直接到段落三)瀏覽器

  1. 數字證書

        數字證書是一種權威性的電子文檔,由權威公正的第三方機構,即CA中心簽發的證書。它以數字證書爲核心的加密技術能夠對網絡上傳輸的信息進行加密和解密、數字簽名和簽名驗證,確保網上傳遞信息的機密性、完整性。 使用了數字證書,即便您發送的信息在網上被他人截獲,甚至您丟失了我的的帳戶、密碼等信息,仍能夠保證您的帳戶、資金安全。 

     它能提供在Internet上進行身份驗證的一種權威性電子文檔,人們能夠在互聯網交往中用它來證實本身的身份和識別對方的身份。固然在數字證書認證的過程當中證書認證中心(CA)做爲權威的、公正的、可信賴的第三方,其做用是相當重要的.如何判斷數字認證中心公正第三方的地位是權威可信的。VeriSign、GeoTrust、Thawte 是國際權威數字證書頒發認證機構的「三巨頭」,其中,應用最廣的爲VerSign簽發的電子商務數字證書。

CER(Canonical Encoding Rules,規範編碼格式) 是數字證書的一種編碼格式,它是BER(Basic Encoding Rules 基本編碼格式) 的一個變種,比BER 規定得更嚴格。後綴的證書文件有兩種編碼:

DER(Distinguished Encoding Rule 卓越編碼格式) 一樣是BER的一個變種,DER使用定長模式。

PKCS(Public-Key Cryptography Standards,公鑰加密標準) 由RSA實驗室和其餘安全系統開發商爲公鑰密碼的發展而制定的一系列標準。

pfx是指以pkcs#12格式存儲的證書和相應私鑰。 

在Security編程中,有幾種典型的密碼交換信息文件格式: 
DER-encoded certificate: .cer, .crt 
PEM-encoded message: .pem 
PKCS#12 Personal Information Exchange: .pfx, .p12 
PKCS#10 Certification Request: .p10 .csr
PKCS#7 cert request response: .p7r 
PKCS#7 binary message: .p7b .p7c .spc

cer/.crt 是用於存放證書,它是2進制形式存放

pem 跟crt/cer的區別是它以Ascii來表示

pfx/p12 用於存放我的證書/私鑰,他一般包含保護密碼,2進制方式 

p10 .csr 是證書請求 

p7r是CA對證書請求的回覆,只用於導入 

p7b .p7c .spc 以樹狀展現證書鏈(certificate chain),同時也支持單個證書,不含私鑰
安全

 

 

  1. 非對稱加密算法

          1976年,美國學者Dime和Henman爲解決信息公開傳送和密鑰管理問題,提出一種新的密鑰交換協議,容許在不安全的媒體上的通信雙方交換信息,安全地達成一致的密鑰,這就是"公開密鑰系統"。相對於"對稱加密算法"這種方法也叫作"非對稱加密算法"。與對稱加密算法不一樣,非對稱加密算法須要兩個密鑰:公開密鑰(publickey)和私有密(privatekey)。公開密鑰與私有密鑰是一對,若是用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;若是用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。由於加密和解密使用的是兩個不一樣的密鑰,因此這種算法叫做非對稱加密算法。服務器

       非對稱加密算法實現機密信息交換的基本過程是:甲方生成一對密鑰並將其中的一把做爲公用密鑰向其它方公開;獲得該公用密鑰的乙方使用該密鑰對機密信息進行加密後再發送給甲方;甲方再用本身保存的另外一把專用密鑰對加密後的信息進行解密。甲方只能用其專用密鑰解密由其公用密鑰加密後的任何信息。非對稱加密算法的保密性比較好,它消除了最終用戶交換密鑰的須要,但加密和解密花費時間長、速度慢,它不適合於對文件加密而只適用於對少許數據進行加密。 經典的非對稱加密算法如RSA算法等安全性都至關高. 非對稱加密的典型應用是數字簽名。採用雙鑰密碼系統的加密方法,在一個過程當中使用兩個密鑰,一個用於加密,另外一個用於解密,這種加密方法稱爲非對稱加密,也稱爲公鑰加密,由於其中一個密鑰是公開的(另外一個則須要保密)。網絡

DH (Diffie-Hellman)
       Diffie-Hellman算法(D-H算法),密鑰一致協議。是由公開密鑰密碼體制的奠定人Diffie和Hellman所提出的一種思想。簡單的說就是容許兩名用戶在公開媒體上交換信息以生成"一致"的、能夠共享的密鑰。換句話說,就是由甲方產出一對密鑰(公鑰、私鑰),乙方依照甲方公鑰產生乙方密鑰對(公鑰、私鑰)。以此爲基線,做爲數據傳輸保密基礎,同時雙方使用同一種對稱加密算法構建本地密鑰(SecretKey)對數據加密。這樣,在互通了本地密鑰(SecretKey)算法後,甲乙雙方公開本身的公鑰,使用對方的公鑰和剛纔產生的私鑰加密數據,同時可使用對方的公鑰和本身的私鑰對數據解密。不僅僅是甲乙雙方兩方,能夠擴展爲多方共享數據通信,這樣就完成了網絡交互數據的安全通信!該算法源於中國的同餘定理——中國餘數定理。app

RSA
       RSA公鑰加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美國麻省理工學院)開發的。RSA取名來自開發他們三者的名字。RSA是目前最有影響力的公鑰加密算法,它可以抵抗到目前爲止已知的全部密碼攻擊,已被ISO推薦爲公鑰數據加密標準。RSA算法基於一個十分簡單的數論事實:將兩個大素數相乘十分容易,但那時想要對其乘積進行因式分解卻極其困難,所以能夠將乘積公開做爲加密密鑰。

EL Gamal
         EL Gamal算法是公鑰密碼體制中的一種 ,在密碼學中佔有重要的地位。但該算法所採用的冪剩餘計算耗時太多的問題 ,一直是制約其普遍應用的瓶頸問題。提出一種經過建表 ,以及對傳統二進制算法進行改進 ,即將指數進行 2 k進制化 ,減小原 BR算法迭代次數 ,提升加密解密速度的算法。

ECC 
ECC (Elliptical Curve Cryptography,橢圓曲線加密)算法不橢圓曲線理論爲基礎,在建立密鑰時能夠更快,更小,而且更有效,它是用大質數的積來產生。

目前Java 6公提供了DH和RSA兩種算法實現,經過Bouncy Castle能夠實現Elmal算法支持,另ECC加密算法,目前沒有開源組件提支持

  1. 對稱加密算法

        對加密和解密使用相同密鑰的加密算法。因爲其速度,對稱性加密一般在消息發送方須要加密大量數據時使用。對稱性加密也稱爲密鑰加密。對稱式數據加密的方式的工做原理如圖。所謂對稱,就是採用這種加密方法的雙方使用方式用一樣的密鑰進行加密和解密。密鑰其實是一種算法,通訊發送方使用這種算法加密數據,接收方再以一樣的算法解密數據。所以對稱式加密自己不是安全的。經常使用的對稱加密有: 

DES、IDEA、RC二、RC四、SKIPJACK算法等 。

採用單鑰密碼系統的加密方法,同一個密鑰能夠同時用做信息的加密和解密,這種加密方法稱爲對稱加密,也稱爲單密鑰加密。

 

  1. HASH算法

經常使用的摘要算法包括MD5,SHA1,SHA256

消息摘要算法的特色:

① 不管輸入的消息有多長,計算出來的消息摘要的長度老是固定的。
② 消息摘要看起來是「隨機的」。這些比特看上去是胡亂的雜湊在一塊兒的。
③ 通常地,只要輸入的消息不一樣,對其進行摘要之後產生的摘要消息也必不相同;但相同的輸入必會產生相同的輸出。
④ 消息摘要函數是無陷門的單向函數,即只能進行正向的信息摘要,而沒法從摘要中恢復出任何的消息,甚至根本就找不到任何與原信息相關的信息。
⑤ 好的摘要算法,沒法找到兩條消息,是它們的摘要相同。

 

消息摘要(Message Digest)又稱爲數字摘要(Digital Digest)。它是一個惟一對應一個消息或文本的固定長度的值,它由一個單向Hash加密函數對消息進行做用而產生。若是消息在途中改變了,則接收者經過對收到消息的新產生的摘要與原摘要比較,就可知道消息是否被改變了。所以消息摘要保證了消息的完整性。消息摘要採用單向Hash 函數將需加密 的明文"摘要"成一串128bit的密文,這一串密文亦稱爲數字指紋(Finger Print),它有固定的長度,且不一樣的明文摘要成密文,其結果老是不一樣的,而一樣的明文其摘要一定一致 。這樣這串摘要即可成爲驗證實文是不是"真身"的"指紋"了。


       HASH函數的抗衝突性使得若是一段明文稍有變化,哪怕只更改該段落的一個字母,經過哈希算法做用後都將產生不一樣的值。而HASH算法的單向性使得要找到到哈希值相同的兩個不 同的輸入消息,在計算上是不可能的。因此數據的哈希值,即消息摘要,能夠檢驗數據的完整性。哈希函數的這種對不一樣的輸入可以生成不一樣的值的特性使得沒法找到兩個具備相同哈希值的輸入。所以,若是兩個文檔經哈希轉換後成爲相同的值,就能夠確定它們是同一文檔。 因此,當但願有效地比較兩個數據塊時,就能夠比較它們的哈希值。例如,能夠經過比較郵件發送前和發送後的哈希值來驗證該郵件在傳遞時是否修改


      消息摘要算法的主要特徵是加密過程不須要密鑰,而且通過加密的數據沒法被解密,只有輸入相同的明文數據通過相同的消息摘要算法才能獲得相同的密文。消息摘要算法不存在 密鑰的管理與分發問題,適合於分佈式網絡相同上使用。因爲其加密計算的工做量至關可觀,因此之前的這種算法一般只用於數據量有限的狀況下的加密,例如計算機的口令就是 用不可逆加密算法加密的。

 

   三 https握手的過程詳細描述

1.瀏覽器將本身支持的一套加密規則發送給網站,如RSA加密算法,DES對稱加密算法,SHA1摘要算法
2.網站從中選出一組加密算法與HASH算法,並將本身的身份信息以證書的形式發回給瀏覽器。證書裏面包含了網站地址,加密公鑰,以及證書的頒發機構等信息(證書中的私鑰只能用於服務器端進行解密,在握手的整個過程當中,都用到了證書中的公鑰和瀏覽器發送給服務器的隨機密碼以及對稱加密算法)


3.得到網站證書以後瀏覽器要作如下工做:
    a) 驗證證書的合法性(頒發證書的機構是否合法,證書中包含的網站地址是否與正在訪問的地址一致等),若是證書受信任,則瀏覽器欄裏面會顯示一個小鎖頭,不然會給出證書不受信的提示。
    b) 若是證書受信任,或者是用戶接受了不受信的證書,瀏覽器會生成一串隨機數的密碼,並用證書中提供的公鑰加密。
    c) 使用約定好的HASH算法計算握手消息(如SHA1),並使用生成的隨機數對消息進行加密,最後將以前生成的被公鑰加密的隨機數密碼,HASH摘要值一塊兒發送給服務器


4.網站接收瀏覽器發來的數據以後要作如下的操做:
    a) 使用本身的私鑰將信息解密並取出瀏覽器發送給服務器的隨機密碼,使用密碼解密瀏覽器發來的握手消息,並驗證HASH是否與瀏覽器發來的一致。
    b) 使用隨機密碼加密一段握手消息,發送給瀏覽器。
    5.瀏覽器解密並計算握手消息的HASH,若是與服務端發來的HASH一致,此時握手過程結束,以後全部的通訊數據將由以前瀏覽器生成的隨機密碼並利用對稱加密算法進行加密。

 

從上面的4個大的步驟能夠看到,握手的整個過程使用到了數字證書、對稱加密、HASH摘要算法,接下來咱們用實際代碼來實現整個過程

 

   四 使用java代碼模擬整個握手過程

          一:準備工做

                          一、建立java證書,

                               C:\> keytool -genkey -alias wangyi -keypass wangyi -keyalg RSA -keysize 1024 -keystore https.keystore -storepass wangyi

                              

                           二、將建立的證書保存到C盤(爲了方便演示)

                             C:\>keytool -export -keystore https.keystore -alias wangyi -file https.crt -storepass wangyi

                             
                           
 

          二:代碼實現

                          代碼包含6個類,分別爲:

名稱 說明
CertifcateUtils 證書操做類
DesCoder Des對稱加密和解密工具類
HttpsMockBase https父類
HttpsMockClient client類
HttpsMockServer 服務器類
SocketUtils socket工具類

                        

Java代碼   收藏代碼
  1. package httpsmock;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.FileInputStream;  
  5. import java.io.InputStream;  
  6. import java.security.KeyStore;  
  7. import java.security.PrivateKey;  
  8. import java.security.PublicKey;  
  9. import java.security.cert.CertificateFactory;  
  10. /** 
  11.  * Created by kingj on 2014/8/13. 
  12.  */  
  13. public class CertifcateUtils {  
  14.     public static byte[] readCertifacates() throws Exception{  
  15.         CertificateFactory factory=CertificateFactory.getInstance("X.509");  
  16.         InputStream in=new FileInputStream("c:/https.crt");  
  17.         java.security.cert.Certificate cate=factory.generateCertificate(in);  
  18.         return cate.getEncoded();  
  19.     }  
  20.   
  21.     public static byte[] readPrivateKey() throws  Exception{  
  22.         KeyStore store=KeyStore.getInstance("JKS");  
  23.         InputStream in=new FileInputStream("c:/https.keystore");  
  24.         store.load(in,"wangyi".toCharArray());  
  25.         PrivateKey pk=(PrivateKey)store.getKey("wangyi","wangyi".toCharArray());  
  26.         return pk.getEncoded();  
  27.     }  
  28.   
  29.     public static PrivateKey readPrivateKeys() throws  Exception{  
  30.         KeyStore store=KeyStore.getInstance("JKS");  
  31.         InputStream in=new FileInputStream("c:/https.keystore");  
  32.         store.load(in,"wangyi".toCharArray());  
  33.         PrivateKey pk=(PrivateKey)store.getKey("wangyi","wangyi".toCharArray());  
  34.         return pk;  
  35.     }  
  36.   
  37.     public static PublicKey readPublicKeys() throws  Exception{  
  38.         CertificateFactory factory=CertificateFactory.getInstance("X.509");  
  39.         InputStream in=new FileInputStream("c:/https.crt");  
  40.         java.security.cert.Certificate cate=factory.generateCertificate(in);  
  41.         return cate.getPublicKey();  
  42.     }  
  43.   
  44.     public static  java.security.cert.Certificate createCertiface(byte b[]) throws Exception{  
  45.         CertificateFactory factory=CertificateFactory.getInstance("X.509");  
  46.         InputStream in=new ByteArrayInputStream(b);  
  47.         java.security.cert.Certificate cate=factory.generateCertificate(in);  
  48.         return cate;  
  49.     }  
  50.   
  51.     public static String byte2hex(byte[] b) {  
  52.         String hs = "";  
  53.         String stmp = "";  
  54.         for (int n = 0; n < b.length; n++) {  
  55.             stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));  
  56.             if (stmp.length() == 1) {  
  57.                 hs = hs + "0" + stmp;  
  58.             } else {  
  59.                 hs = hs + stmp;  
  60.             }  
  61.         }  
  62.         return hs.toUpperCase();  
  63.     }  
  64. }  

     

Java代碼   收藏代碼
  1. package httpsmock;  
  2.   
  3. /** 
  4.  * Created by kingj on 2014/8/13. 
  5.  */  
  6. import org.apache.commons.codec.binary.Hex;  
  7.   
  8. import java.security.Key;  
  9. import java.security.SecureRandom;  
  10.   
  11. import javax.crypto.Cipher;  
  12. import javax.crypto.KeyGenerator;  
  13. import javax.crypto.SecretKey;  
  14. import javax.crypto.SecretKeyFactory;  
  15. import javax.crypto.spec.DESKeySpec;  
  16.   
  17. /** 
  18.  * DES Coder<br/> 
  19.  * secret key length:   56 bit, default:    56 bit<br/> 
  20.  * mode:    ECB/CBC/PCBC/CTR/CTS/CFB/CFB8 to CFB128/OFB/OBF8 to OFB128<br/> 
  21.  * padding: Nopadding/PKCS5Padding/ISO10126Padding/ 
  22.  * @author Aub 
  23.  * 
  24.  */  
  25. public class DesCoder {  
  26.   
  27.     /** 
  28.      * 密鑰算法 
  29.      */  
  30.     private static final String KEY_ALGORITHM = "DES";  
  31.   
  32.     private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";  
  33. //  private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/ISO10126Padding";  
  34.   
  35.   
  36.     /** 
  37.      * 初始化密鑰 
  38.      * 
  39.      * @return byte[] 密鑰 
  40.      * @throws Exception 
  41.      */  
  42.     public static byte[] initSecretKey(SecureRandom random) throws Exception{  
  43.         //返回生成指定算法的祕密密鑰的 KeyGenerator 對象  
  44.         KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);  
  45.         //初始化此密鑰生成器,使其具備肯定的密鑰大小  
  46.         kg.init(random);  
  47.         //生成一個密鑰  
  48.         SecretKey  secretKey = kg.generateKey();  
  49.         return secretKey.getEncoded();  
  50.     }  
  51.   
  52.     /** 
  53.      * 轉換密鑰 
  54.      * 
  55.      * @param key   二進制密鑰 
  56.      * @return Key  密鑰 
  57.      * @throws Exception 
  58.      */  
  59.     public static Key toKey(byte[] key) throws Exception{  
  60.         //實例化DES密鑰規則  
  61.         DESKeySpec dks = new DESKeySpec(key);  
  62.         //實例化密鑰工廠  
  63.         SecretKeyFactory skf = SecretKeyFactory.getInstance(KEY_ALGORITHM);  
  64.         //生成密鑰  
  65.         SecretKey  secretKey = skf.generateSecret(dks);  
  66.         return secretKey;  
  67.     }  
  68.   
  69.     /** 
  70.      * 加密 
  71.      * 
  72.      * @param data  待加密數據 
  73.      * @param key   密鑰 
  74.      * @return byte[]   加密數據 
  75.      * @throws Exception 
  76.      */  
  77.     public static byte[] encrypt(byte[] data,Key key) throws Exception{  
  78.         return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);  
  79.     }  
  80.   
  81.     /** 
  82.      * 加密 
  83.      * 
  84.      * @param data  待加密數據 
  85.      * @param key   二進制密鑰 
  86.      * @return byte[]   加密數據 
  87.      * @throws Exception 
  88.      */  
  89.     public static byte[] encrypt(byte[] data,byte[] key) throws Exception{  
  90.         return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);  
  91.     }  
  92.   
  93.   
  94.     /** 
  95.      * 加密 
  96.      * 
  97.      * @param data  待加密數據 
  98.      * @param key   二進制密鑰 
  99.      * @param cipherAlgorithm   加密算法/工做模式/填充方式 
  100.      * @return byte[]   加密數據 
  101.      * @throws Exception 
  102.      */  
  103.     public static byte[] encrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{  
  104.         //還原密鑰  
  105.         Key k = toKey(key);  
  106.         return encrypt(data, k, cipherAlgorithm);  
  107.     }  
  108.   
  109.     /** 
  110.      * 加密 
  111.      * 
  112.      * @param data  待加密數據 
  113.      * @param key   密鑰 
  114.      * @param cipherAlgorithm   加密算法/工做模式/填充方式 
  115.      * @return byte[]   加密數據 
  116.      * @throws Exception 
  117.      */  
  118.     public static byte[] encrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{  
  119.         //實例化  
  120.         Cipher cipher = Cipher.getInstance(cipherAlgorithm);  
  121.         //使用密鑰初始化,設置爲加密模式  
  122.         cipher.init(Cipher.ENCRYPT_MODE, key);  
  123.         //執行操做  
  124.         return cipher.doFinal(data);  
  125.     }  
  126.   
  127.   
  128.   
  129.     /** 
  130.      * 解密 
  131.      * 
  132.      * @param data  待解密數據 
  133.      * @param key   二進制密鑰 
  134.      * @return byte[]   解密數據 
  135.      * @throws Exception 
  136.      */  
  137.     public static byte[] decrypt(byte[] data,byte[] key) throws Exception{  
  138.         return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);  
  139.     }  
  140.   
  141.     /** 
  142.      * 解密 
  143.      * 
  144.      * @param data  待解密數據 
  145.      * @param key   密鑰 
  146.      * @return byte[]   解密數據 
  147.      * @throws Exception 
  148.      */  
  149.     public static byte[] decrypt(byte[] data,Key key) throws Exception{  
  150.         return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);  
  151.     }  
  152.   
  153.     /** 
  154.      * 解密 
  155.      * 
  156.      * @param data  待解密數據 
  157.      * @param key   二進制密鑰 
  158.      * @param cipherAlgorithm   加密算法/工做模式/填充方式 
  159.      * @return byte[]   解密數據 
  160.      * @throws Exception 
  161.      */  
  162.     public static byte[] decrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{  
  163.         //還原密鑰  
  164.         Key k = toKey(key);  
  165.         return decrypt(data, k, cipherAlgorithm);  
  166.     }  
  167.   
  168.     /** 
  169.      * 解密 
  170.      * 
  171.      * @param data  待解密數據 
  172.      * @param key   密鑰 
  173.      * @param cipherAlgorithm   加密算法/工做模式/填充方式 
  174.      * @return byte[]   解密數據 
  175.      * @throws Exception 
  176.      */  
  177.     public static byte[] decrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{  
  178.         //實例化  
  179.         Cipher cipher = Cipher.getInstance(cipherAlgorithm);  
  180.         //使用密鑰初始化,設置爲解密模式  
  181.         cipher.init(Cipher.DECRYPT_MODE, key);  
  182.         //執行操做  
  183.         return cipher.doFinal(data);  
  184.     }  
  185.   
  186.     private static String  showByteArray(byte[] data){  
  187.         if(null == data){  
  188.             return null;  
  189.         }  
  190.         StringBuilder sb = new StringBuilder("{");  
  191.         for(byte b:data){  
  192.             sb.append(b).append(",");  
  193.         }  
  194.         sb.deleteCharAt(sb.length()-1);  
  195.         sb.append("}");  
  196.         return sb.toString();  
  197.     }  
  198.   
  199. }  

 

  

Java代碼   收藏代碼
  1. package httpsmock;  
  2.   
  3. import com.sun.org.apache.bcel.internal.generic.NEW;  
  4.   
  5. import javax.crypto.*;  
  6. import javax.crypto.spec.DESKeySpec;  
  7. import java.security.*;  
  8. import java.security.spec.InvalidKeySpecException;  
  9. import java.util.Random;  
  10.   
  11. /** 
  12.  * Created by kingj on 2014/8/13. 
  13.  */  
  14. public class HttpsMockBase {  
  15.     static PrivateKey privateKey;  
  16.     static PublicKey publicKey;  
  17.   
  18.   
  19.     public static boolean byteEquals(byte a[],byte[] b){  
  20.         boolean equals=true;  
  21.         if(a==null || b==null){  
  22.             equals=false;  
  23.         }  
  24.   
  25.         if(a!=null && b!=null){  
  26.             if(a.length!=b.length){  
  27.                 equals=false;  
  28.             }else{  
  29.                 for(int i=0;i<a.length;i++){  
  30.                     if(a[i]!=b[i]){  
  31.                         equals=false;  
  32.                         break;  
  33.                     }  
  34.                 }  
  35.             }  
  36.   
  37.         }  
  38.         return equals;  
  39.     }  
  40.   
  41.     public static byte[] decrypt(byte data[]) throws Exception{  
  42.         // 對數據解密  
  43.         Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());  
  44.         cipher.init(Cipher.DECRYPT_MODE, privateKey);  
  45.         return cipher.doFinal(data);  
  46.     }  
  47.   
  48.     public static byte[] decrypt(byte data[],SecureRandom seed) throws Exception{  
  49.         // 對數據解密  
  50.         Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());  
  51.         cipher.init(Cipher.DECRYPT_MODE, privateKey,seed);  
  52.         return cipher.doFinal(data);  
  53.     }  
  54.   
  55.     public static byte[] decryptByPublicKey(byte data[],SecureRandom seed) throws Exception{  
  56.         if(publicKey==null){  
  57.             publicKey=CertifcateUtils.readPublicKeys();  
  58.         }  
  59.         // 對數據解密  
  60.         Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());  
  61.         if(seed==null){  
  62.             cipher.init(Cipher.DECRYPT_MODE, publicKey);  
  63.         }else{  
  64.             cipher.init(Cipher.DECRYPT_MODE, publicKey,seed);  
  65.         }  
  66.   
  67.         return cipher.doFinal(data);  
  68.     }  
  69.   
  70.     public static byte[] decryptByDes(byte data[],SecureRandom seed) throws Exception{  
  71.         if(publicKey==null){  
  72.             publicKey=CertifcateUtils.readPublicKeys();  
  73.         }  
  74.         // 對數據解密  
  75.         Cipher cipher = Cipher.getInstance("DES");  
  76.         if(seed==null){  
  77.             cipher.init(Cipher.DECRYPT_MODE, publicKey);  
  78.         }else{  
  79.             cipher.init(Cipher.DECRYPT_MODE, publicKey,seed);  
  80.         }  
  81.   
  82.         return cipher.doFinal(data);  
  83.     }  
  84.   
  85.   
  86.   
  87.   
  88.     public static byte[] encryptByPublicKey(byte[] data, SecureRandom seed)  
  89.             throws Exception {  
  90.         if(publicKey==null){  
  91.             publicKey=CertifcateUtils.readPublicKeys();  
  92.         }  
  93.         // 對數據加密  
  94.         Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());  
  95.         if(seed==null){  
  96.             cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
  97.         }else{  
  98.             cipher.init(Cipher.ENCRYPT_MODE, publicKey,seed);  
  99.         }  
  100.   
  101.         return cipher.doFinal(data);  
  102.     }  
  103.   
  104.     public static String byte2hex(byte[] b) {  
  105.         String hs = "";  
  106.         String stmp = "";  
  107.         for (int n = 0; n < b.length; n++) {  
  108.             stmp = (Integer.toHexString(b[n] & 0XFF));  
  109.             if (stmp.length() == 1) {  
  110.                 hs = hs + "0" + stmp;  
  111.             } else {  
  112.                 hs = hs +"  " + stmp;  
  113.             }  
  114.         }  
  115.         return hs.toUpperCase();  
  116.     }  
  117.   
  118.     public static byte[] cactHash(byte[] bytes) {  
  119.         byte[] _bytes = null;  
  120.         try {  
  121.             MessageDigest md = MessageDigest.getInstance("SHA1");  
  122.             md.update(bytes);  
  123.             _bytes = md.digest();  
  124.         } catch (NoSuchAlgorithmException ex) {  
  125.             ex.printStackTrace();  
  126.         }  
  127.         return _bytes;  
  128.     }  
  129.   
  130.   
  131.   
  132.     static String random(){  
  133.         StringBuilder builder=new StringBuilder();  
  134.         Random random=new Random();  
  135.         int seedLength=10;  
  136.         for(int i=0;i<seedLength;i++){  
  137.             builder.append(digits[random.nextInt(seedLength)]);  
  138.         }  
  139.   
  140.         return builder.toString();  
  141.     }  
  142.   
  143.     static char[] digits={  
  144.             '0','1','2','3','4',  
  145.             '5','6','7','8','9',  
  146.             'a','b','c','d','e',  
  147.             'f','g','h','i','j'  
  148.     };  
  149.   
  150. }  

    

Java代碼   收藏代碼
  1. package httpsmock;  
  2.   
  3. import java.io.DataInputStream;  
  4. import java.io.DataOutputStream;  
  5. import java.net.Socket;  
  6. import java.security.Key;  
  7. import java.security.SecureRandom;  
  8.   
  9. /** 
  10.  * Created by kingj on 2014/8/13. 
  11.  */  
  12. public class HttpsMockClient extends  HttpsMockBase {  
  13.     static DataInputStream in;  
  14.     static DataOutputStream out;  
  15.     static Key key;  
  16.     public static void main(String args[]) throws  Exception{  
  17.         int port=80;  
  18.         Socket s=new Socket("localhost",port);  
  19.         s.setReceiveBufferSize(102400);  
  20.         s.setKeepAlive(true);  
  21.         in=new DataInputStream(s.getInputStream());  
  22.         out=new DataOutputStream(s.getOutputStream());  
  23.         shakeHands();  
  24.   
  25.         System.out.println("------------------------------------------------------------------");  
  26.         String name="duck";  
  27.         writeBytes(name.getBytes());  
  28.   
  29.         int len=in.readInt();  
  30.         byte[] msg=readBytes(len);  
  31.         System.out.println("服務器反饋消息:"+byte2hex(msg));  
  32.         Thread.sleep(1000*100);  
  33.   
  34.   
  35.     }  
  36.   
  37.     private static void shakeHands() throws Exception {  
  38.         //第一步 客戶端發送本身支持的hash算法  
  39.         String supportHash="SHA1";  
  40.         int length=supportHash.getBytes().length;  
  41.         out.writeInt(length);  
  42.         SocketUtils.writeBytes(out, supportHash.getBytes(), length);  
  43.   
  44.         //第二步 客戶端驗證服務器端證書是否合法  
  45.         int skip=in.readInt();  
  46.         byte[] certificate=SocketUtils.readBytes(in,skip);  
  47.         java.security.cert.Certificate cc= CertifcateUtils.createCertiface(certificate);  
  48.   
  49.         publicKey=cc.getPublicKey();  
  50.         cc.verify(publicKey);  
  51.         System.out.println("客戶端校驗服務器端證書是否合法:" +true);  
  52.   
  53.         //第三步  客戶端校驗服務器端發送過來的證書成功,生成隨機數並用公鑰加密  
  54.         System.out.println("客戶端校驗服務器端發送過來的證書成功,生成隨機數並用公鑰加密");  
  55.         SecureRandom seed=new SecureRandom();  
  56.         int seedLength=2;  
  57.         byte seedBytes[]=seed.generateSeed(seedLength);  
  58.         System.out.println("生成的隨機數爲 : " + byte2hex(seedBytes));  
  59.         System.out.println("將隨機數用公鑰加密後發送到服務器");  
  60.         byte[] encrptedSeed=encryptByPublicKey(seedBytes, null);  
  61.         SocketUtils.writeBytes(out,encrptedSeed,encrptedSeed.length);  
  62.   
  63.         System.out.println("加密後的seed值爲 :" + byte2hex(encrptedSeed));  
  64.   
  65.         String message=random();  
  66.         System.out.println("客戶端生成消息爲:"+message);  
  67.   
  68.         System.out.println("使用隨機數並用公鑰對消息加密");  
  69.         byte[] encrpt=encryptByPublicKey(message.getBytes(),seed);  
  70.         System.out.println("加密後消息位數爲 : " +encrpt.length);  
  71.         SocketUtils.writeBytes(out,encrpt,encrpt.length);  
  72.   
  73.         System.out.println("客戶端使用SHA1計算消息摘要");  
  74.         byte hash[]=cactHash(message.getBytes());  
  75.         System.out.println("摘要信息爲:"+byte2hex(hash));  
  76.   
  77.         System.out.println("消息加密完成,摘要計算完成,發送服務器");  
  78.         SocketUtils.writeBytes(out,hash,hash.length);  
  79.   
  80.   
  81.         System.out.println("客戶端向服務器發送消息完成,開始接受服務器端發送回來的消息和摘要");  
  82.         System.out.println("接受服務器端發送的消息");  
  83.         int serverMessageLength=in.readInt();  
  84.         byte[] serverMessage=SocketUtils.readBytes(in,serverMessageLength);  
  85.         System.out.println("服務器端的消息內容爲 :" + byte2hex(serverMessage));  
  86.   
  87.         System.out.println("開始用以前生成的隨機密碼和DES算法解密消息,密碼爲:"+byte2hex(seedBytes));  
  88.         byte[] desKey= DesCoder.initSecretKey(new SecureRandom(seedBytes));  
  89.         key=DesCoder.toKey(desKey);  
  90.   
  91.         byte[] decrpytedServerMsg=DesCoder.decrypt(serverMessage, key);  
  92.         System.out.println("解密後的消息爲:"+byte2hex(decrpytedServerMsg));  
  93.   
  94.         int serverHashLength=in.readInt();  
  95.         byte[] serverHash=SocketUtils.readBytes(in,serverHashLength);  
  96.         System.out.println("開始接受服務器端的摘要消息:"+byte2hex(serverHash));  
  97.   
  98.         byte[] serverHashValues=cactHash(decrpytedServerMsg);  
  99.         System.out.println("計算服務器端發送過來的消息的摘要 : " +byte2hex(serverHashValues));  
  100.   
  101.         System.out.println("判斷服務器端發送過來的hash摘要是否和計算出的摘要一致");  
  102.         boolean isHashEquals=byteEquals(serverHashValues,serverHash);  
  103.   
  104.         if(isHashEquals){  
  105.             System.out.println("驗證完成,握手成功");  
  106.         }else{  
  107.             System.out.println("驗證失敗,握手失敗");  
  108.         }  
  109.     }  
  110.   
  111.   
  112.     public static byte[] readBytes(int length) throws  Exception{  
  113.         byte[] undecrpty=SocketUtils.readBytes(in,length);  
  114.         System.out.println("讀取未解密消息:"+byte2hex(undecrpty));  
  115.         return DesCoder.decrypt(undecrpty,key);  
  116.     }  
  117.   
  118.     public static void writeBytes(byte[] data) throws  Exception{  
  119.         byte[] encrpted=DesCoder.encrypt(data,key);  
  120.         System.out.println("寫入加密後消息:"+byte2hex(encrpted));  
  121.         SocketUtils.writeBytes(out,encrpted,encrpted.length);  
  122.     }  
  123. }  

   

Java代碼   收藏代碼
  1. package httpsmock;  
  2.   
  3. import javax.net.ServerSocketFactory;  
  4. import java.io.DataInputStream;  
  5. import java.io.DataOutputStream;  
  6. import java.net.ServerSocket;  
  7. import java.net.Socket;  
  8. import java.security.Key;  
  9. import java.security.SecureRandom;  
  10. import java.util.concurrent.ExecutorService;  
  11. import java.util.concurrent.Executors;  
  12.   
  13. /** 
  14.  * Created by kingj on 2014/8/13. 
  15.  */  
  16. public class HttpsMockServer extends HttpsMockBase {  
  17.     static DataInputStream in;  
  18.     static DataOutputStream out;  
  19.     static String hash;  
  20.     static Key key;  
  21.     static ExecutorService executorService= Executors.newFixedThreadPool(20);  
  22.     public static void main(String args[]) throws Exception{  
  23.         int port=80;  
  24.         ServerSocket ss= ServerSocketFactory.getDefault().createServerSocket(port);  
  25.         ss.setReceiveBufferSize(102400);  
  26.         ss.setReuseAddress(false);  
  27.         while(true){  
  28.             try {  
  29.                 final Socket s = ss.accept();  
  30.                 doHttpsShakeHands(s);  
  31.                 executorService.execute(new Runnable() {  
  32.                     @Override  
  33.                     public void run() {  
  34.                         doSocketTransport(s);  
  35.                     }  
  36.                 });  
  37.   
  38.             }catch (Exception e){  
  39.                 e.printStackTrace();  
  40.             }  
  41.         }  
  42.     }  
  43.   
  44.     private static void doSocketTransport(Socket s){  
  45.         try{  
  46.             System.out.println("--------------------------------------------------------");  
  47.             int length=in.readInt();  
  48.             byte[] clientMsg=readBytes(length);  
  49.             System.out.println("客戶端指令內容爲:" + byte2hex(clientMsg));  
  50.   
  51.             writeBytes("服務器已經接受請求".getBytes());  
  52.         }catch (Exception ex){  
  53.             ex.printStackTrace();  
  54.         }  
  55.     }  
  56.   
  57.     public static byte[] readBytes(int length) throws  Exception{  
  58.         byte[] undecrpty=SocketUtils.readBytes(in,length);  
  59.         System.out.println("讀取未解密消息:"+byte2hex(undecrpty));  
  60.         return DesCoder.decrypt(undecrpty,key);  
  61.     }  
  62.   
  63.     public static void writeBytes(byte[] data) throws  Exception{  
  64.         byte[] encrpted=DesCoder.encrypt(data,key);  
  65.         System.out.println("寫入加密後消息:"+byte2hex(encrpted));  
  66.         SocketUtils.writeBytes(out,encrpted,encrpted.length);  
  67.     }  
  68.   
  69.     private static void doHttpsShakeHands(Socket s) throws Exception {  
  70.          in=new DataInputStream(s.getInputStream());  
  71.          out=new DataOutputStream(s.getOutputStream());  
  72.   
  73.         //第一步 獲取客戶端發送的支持的驗證規則,包括hash算法,這裏選用SHA1做爲hash  
  74.         int length=in.readInt();  
  75.         in.skipBytes(4);  
  76.         byte[] clientSupportHash=SocketUtils.readBytes(in,length);  
  77.         String clientHash=new String(clientSupportHash);  
  78.         hash=clientHash;  
  79.         System.out.println("客戶端發送了hash算法爲:"+clientHash);  
  80.   
  81.         //第二步,發送服務器證書到客戶端  
  82.         byte[] certificateBytes=CertifcateUtils.readCertifacates();  
  83.         privateKey=CertifcateUtils.readPrivateKeys();  
  84.         System.out.println("發送證書給客戶端,字節長度爲:"+certificateBytes.length);  
  85.         System.out.println("證書內容爲:" + byte2hex(certificateBytes));  
  86.         SocketUtils.writeBytes(out, certificateBytes, certificateBytes.length);  
  87.   
  88.         System.out.println("獲取客戶端經過公鑰加密後的隨機數");  
  89.         int secureByteLength=in.readInt();  
  90.         byte[] secureBytes=SocketUtils.readBytes(in, secureByteLength);  
  91.   
  92.         System.out.println("讀取到的客戶端的隨機數爲:"+byte2hex(secureBytes));  
  93.         byte secureSeed[]=decrypt(secureBytes);  
  94.         System.out.println("解密後的隨機數密碼爲:" +byte2hex(secureSeed));  
  95.   
  96.         //第三步 獲取客戶端加密字符串  
  97.         int skip=in.readInt();  
  98.         System.out.println("第三步 獲取客戶端加密消息,消息長度爲 :" +skip);  
  99.         byte[] data=SocketUtils.readBytes(in,skip);  
  100.   
  101.         System.out.println("客戶端發送的加密消息爲 : " +byte2hex(data));  
  102.         System.out.println("用私鑰對消息解密,並計算SHA1的hash值");  
  103.         byte message[] =decrypt(data,new SecureRandom(secureBytes));  
  104.         byte serverHash[]=cactHash(message);  
  105.   
  106.   
  107.         System.out.println("獲取客戶端計算的SHA1摘要");  
  108.         int hashSkip=in.readInt();  
  109.         byte[] clientHashBytes=SocketUtils.readBytes(in,hashSkip);  
  110.         System.out.println("客戶端SHA1摘要爲 : " + byte2hex(clientHashBytes));  
  111.   
  112.         System.out.println("開始比較客戶端hash和服務器端從消息中計算的hash值是否一致");  
  113.         boolean isHashEquals=byteEquals(serverHash,clientHashBytes);  
  114.         System.out.println("是否一致結果爲 : " + isHashEquals);  
  115.   
  116.   
  117.   
  118.         System.out.println("第一次校驗客戶端發送過來的消息和摘譯一致,服務器開始向客戶端發送消息和摘要");  
  119.         System.out.println("生成密碼用於加密服務器端消息,secureRandom : "+byte2hex(secureSeed));  
  120.         SecureRandom secureRandom=new SecureRandom(secureSeed);  
  121.   
  122.         String randomMessage=random();  
  123.         System.out.println("服務器端生成的隨機消息爲 : "+randomMessage);  
  124.   
  125.         System.out.println("用DES算法並使用客戶端生成的隨機密碼對消息加密");  
  126.         byte[] desKey=DesCoder.initSecretKey(secureRandom);  
  127.         key=DesCoder.toKey(desKey);  
  128.   
  129.         byte serverMessage[]=DesCoder.encrypt(randomMessage.getBytes(), key);  
  130.         SocketUtils.writeBytes(out,serverMessage,serverMessage.length);  
  131.         System.out.println("服務器端發送的機密後的消息爲:"+byte2hex(serverMessage)+",加密密碼爲:"+byte2hex(secureSeed));  
  132.   
  133.         System.out.println("服務器端開始計算hash摘要值");  
  134.         byte serverMessageHash[]=cactHash(randomMessage.getBytes());  
  135.         System.out.println("服務器端計算的hash摘要值爲 :" +byte2hex(serverMessageHash));  
  136.         SocketUtils.writeBytes(out,serverMessageHash,serverMessageHash.length);  
  137.   
  138.         System.out.println("握手成功,以後全部通訊都將使用DES加密算法進行加密");  
  139.     }  
  140.   
  141. }  

   

Java代碼   收藏代碼
  1. package httpsmock;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.DataInputStream;  
  5. import java.io.DataOutputStream;  
  6. import java.io.IOException;  
  7. import java.net.Socket;  
  8. import java.util.Arrays;  
  9.   
  10. /** 
  11.  * Created by kingj on 2014/8/13. 
  12.  */  
  13. public class SocketUtils {  
  14.     public static void close(Socket s){  
  15.         try {  
  16.             s.shutdownInput();  
  17.             s.shutdownOutput();  
  18.         } catch (IOException e) {  
  19.             e.printStackTrace();  
  20.         }  
  21.     }  
  22.   
  23.   
  24.   
  25.     public static byte[] readBytes(DataInputStream in,int length) throws IOException {  
  26.         int r=0;  
  27.         byte[] data=new byte[length];  
  28.         while(r<length){  
  29.             r+=in.read(data,r,length-r);  
  30.         }  
  31.   
  32.         return data;  
  33.     }  
  34.   
  35.     public static void writeBytes(DataOutputStream out,byte[] bytes,int length) throws IOException{  
  36.         out.writeInt(length);  
  37.         out.write(bytes,0,length);  
  38.         out.flush();  
  39.     }  
  40. }  

 

 

    經過運行上述代碼,咱們能夠看看服務器端和客戶端控制檯打印的消息記錄(https握手完成後,整個過程數據傳輸都須要客戶端和服務端使用約定的DES算法對數據進行加密和解密)

    一、服務端消息記錄

客戶端發送了hash算法爲:SHA1
發送證書給客戶端,字節長度爲:618
證書內容爲:  30  8202  66  30  8201  CF  A0030201020204  51  84  FA  AF  300D0609  2A  86  48  86  F70D01010B0500  30  66  310F  300D0603  550406  1306  77  61  6E  67  79  69  310F  300D0603  550408  1306  77  61  6E  67  79  69  310F  300D0603  550407  1306  77  61  6E  67  79  69  310F  300D0603  55040A  1306  77  61  6E  67  79  69  310F  300D0603  55040B  1306  77  61  6E  67  79  69  310F  300D0603  550403  1306  77  61  6E  67  79  69  30  1E  170D  31  34  30  38  31  33  30  35  32  30  35  34  5A  170D  31  34  31  31  31  31  30  35  32  30  35  34  5A  30  66  310F  300D0603  550406  1306  77  61  6E  67  79  69  310F  300D0603  550408  1306  77  61  6E  67  79  69  310F  300D0603  550407  1306  77  61  6E  67  79  69  310F  300D0603  55040A  1306  77  61  6E  67  79  69  310F  300D0603  55040B  1306  77  61  6E  67  79  69  310F  300D0603  550403  1306  77  61  6E  67  79  69  30  81  9F  300D0609  2A  86  48  86  F70D010101050003  81  8D00  30  81  8902  81  8100  89  20  2A  F6  BF  1E  F9  95  F8  E5  E2  C2  C6  14  22  DB  23  10  2F  44  E0  AD0B  FB  89  62  8C  A6  E2  14  52  E7  5D  FE  7B  CC  A4  D2  F4  F9  C5  8E  E0  75  CC  F3  71  E9  29  85  A9  DA  D2  BD  93  73  12  74  2B  4C  D2  74  1A  13  82  64  20  E0  8B  68  FF  9A  F0  6F0C  880F  91  A5  FE  42  44  DE  81  F0  47  C7  67  2001  C7  7E  8B  36  87  E8  1B  7E  6907  D0  39  77  DE  53  D4  F5  67  57  BD  15  8E  51  E5  44  10  CD  BE  81  EB  E3  86  E8  73  B5  1D  1F  FF0203010001  A3  21  30  1F  30  1D0603  55  1D0E04  1604  14  E2  81  F2  3E  81  92  8B  DE  7A  1D  93  A9  28  23  A7  5D  E7  65  63  EB  300D0609  2A  86  48  86  F70D01010B050003  81  810002  E6  BF00  FB  CE  3A  4A  AC  9E  5F  10  6C  4F  FE  44  93  A4  6D  89  BC  4F  CB  25  30  1F  B4  C7  67  E3  E6  A1  1D  66  4B  DA  E4  6D  D8  90  CC  D2  74  34  48  6C  9B  33  2E  C2  4E  9E  AA  470B  9B  4000  7A  59  67  3E  C2  75  1A  A0  7A  48  16  53  D6  C4  53  97080B  F4  23  49  2E06  60  DF  9D  B4  5B  76  B2  AC  35  CF  2E  3C  CA  E3  B6  25  7D  F7  BA  69  6F  15  CE  AF  B4  9D  83  94  2E  5E  37  6E  C5  C2  B9  94  54  DB06  5D  7F  B6  70  1C  91  E6  E3
獲取客戶端經過公鑰加密後的隨機數
讀取到的客戶端的隨機數爲:  86  16  A9  65  F6  EC  A3  57  D6  23  A2  43  8F  F4  52  F5  37  14  F9  5B  27  6F  75  A3  25  C9  9E  D4  DD  CC  68  BA03  A2  1B  E6  8D  74  61  3B  28  28  9F  1F  5A  AD  5F  32  4B  40  81  98  54  AC0F  840B  80  BF  53  80  50  1E  A7  24  16  10  2A  2B  6A  8709  86  7C  20  75  20  14  7E  38  F3  FA  76  6207  D1  E1  37  28  93  D9  C1  2F  D4  9B  6E  9A  5205  9A  6D  54  8B  DD  1D  8205  DF  BC  AE  BB  6C  24  F5  6E  BC  F2  DE  26  AB  B1  87  1F  DA  DE  3B  25  1E
解密後的隨機數密碼爲:  5B  D4
第三步 獲取客戶端加密消息,消息長度爲 :128
客戶端發送的加密消息爲 :   32  76  EB  3E  93  E7  F1  590E  67  EB  FA  29  24  5D  F4  A2  3E  78  BE  61  49  B1  4C  91  1A  450A  B7  D7  E0  71  A1  30  C0  12  F905  9C  CF  B9  C9  75  6B  C4  39  3C  EF  5F  1005  75  AD  50  9A09  6F  8A  7F  C0  F4  20  E0  BC  DF  74  90  F3  6A  46  5E  6C  47  FC  16  EC  4D  DD  10  F9  87  ED  E4  47  83  37  B8  6A  5B  5B  B2  17  9306  7707  72  8E  3008  73  59  89  F5  F7  E6  66  89  4F  F7  B6  2B  41  7B  3B  1B  29  63  D0  11  D4  52  60  4A  3B  74  CA  1E
用私鑰對消息解密,並計算SHA1的hash值
獲取客戶端計算的SHA1摘要
客戶端SHA1摘要爲 : 01  56  CB  DF  D3  EF  5A  8F  BB  85  BE  15  FB  83  D9  10  1F  64  F6  D8
開始比較客戶端hash和服務器端從消息中計算的hash值是否一致
是否一致結果爲 : true
第一次校驗客戶端發送過來的消息和摘譯一致,服務器開始向客戶端發送消息和摘要
生成密碼用於加密服務器端消息,secureRandom :   5B  D4  (使用客戶端第一次傳過來的密碼)
服務器端生成的隨機消息爲 : 2355384499
用DES算法並使用客戶端生成的隨機密碼對消息加密
服務器端發送的機密後的消息爲:  34  DE  39  CE  7A  280D  4F  44  83  51  2D  C3  EB  4F  1B,加密密碼爲:  5B  D4   (使用客戶端第一次傳過來的密碼)
服務器端開始計算hash摘要值
服務器端計算的hash摘要值爲 :  DD  3D  66  B5  C8  B6  A2  36  5E  D1  55  9A  B6  F7  C0  39  3C  97  1402
握手成功,以後全部通訊都將使用DES加密算法進行加密
--------------------------------------------------------
讀取未解密消息:  9D  2D  C2  D7  5D  2F  3C  F5
客戶端指令內容爲:  64  75  63  6B
寫入加密後消息:  52  91  2C  62  E3  B9  5E  80  CF  3D  39  B4  7D  55  B7  3A  97  46  34  98  5603  DA  FC  A9  E1  D1  61  8F  24  64  D8

  

    二、客戶端消息記錄

 

客戶端校驗服務器端證書是否合法:true (校驗證書)
客戶端校驗服務器端發送過來的證書成功,生成隨機數並用公鑰加密
生成的隨機數爲 :   5B  D4  (客戶端生成了隨機密碼,用於整個握手過程當中)
將隨機數用公鑰加密後發送到服務器
加密後的seed值爲 :  86  16  A9  65  F6  EC  A3  57  D6  23  A2  43  8F  F4  52  F5  37  14  F9  5B  27  6F  75  A3  25  C9  9E  D4  DD  CC  68  BA03  A2  1B  E6  8D  74  61  3B  28  28  9F  1F  5A  AD  5F  32  4B  40  81  98  54  AC0F  840B  80  BF  53  80  50  1E  A7  24  16  10  2A  2B  6A  8709  86  7C  20  75  20  14  7E  38  F3  FA  76  6207  D1  E1  37  28  93  D9  C1  2F  D4  9B  6E  9A  5205  9A  6D  54  8B  DD  1D  8205  DF  BC  AE  BB  6C  24  F5  6E  BC  F2  DE  26  AB  B1  87  1F  DA  DE  3B  25  1E
客戶端生成消息爲:9080292229
使用隨機數並用公鑰對消息加密
加密後消息位數爲 : 128
客戶端使用SHA1計算消息摘要
摘要信息爲:01  56  CB  DF  D3  EF  5A  8F  BB  85  BE  15  FB  83  D9  10  1F  64  F6  D8
消息加密完成,摘要計算完成,發送服務器
客戶端向服務器發送消息完成,開始接受服務器端發送回來的消息和摘要
接受服務器端發送的消息
服務器端的消息內容爲 :  34  DE  39  CE  7A  280D  4F  44  83  51  2D  C3  EB  4F  1B
開始用以前生成的隨機密碼和DES算法解密消息,密碼爲:  5B  D4
解密後的消息爲:  32  33  35  35  33  38  34  34  39  39
開始接受服務器端的摘要消息:  DD  3D  66  B5  C8  B6  A2  36  5E  D1  55  9A  B6  F7  C0  39  3C  97  1402
計算服務器端發送過來的消息的摘要 :   DD  3D  66  B5  C8  B6  A2  36  5E  D1  55  9A  B6  F7  C0  39  3C  97  1402
判斷服務器端發送過來的hash摘要是否和計算出的摘要一致
驗證完成,握手成功
------------------------------------------------------------------
寫入加密後消息:  9D  2D  C2  D7  5D  2F  3C  F5
讀取未解密消息:  52  91  2C  62  E3  B9  5E  80  CF  3D  39  B4  7D  55  B7  3A  97  46  34  98  5603  DA  FC  A9  E1  D1  61  8F  24  64  D8
服務器反饋消息:  E6  9C  8D  E5  8A  A1  E5  99  A8  E5  B7  B2  E7  BB  8F  E6  8E  A5  E5  8F  97  E8  AF  B7  E6  B1  82

相關文章
相關標籤/搜索