前言

感謝偉大的數學家和密碼學家們,讓我們的網絡處於一個相對安全的環境。

最近整理了一下 HTTPS 相關的知識,本文中所有的分析是基於 TLS1.2 版本。

WebTrust

WebTrust 是由全球兩大著名註冊會計師協會 AICPA(美國註冊會計師協會)和 CICA(加拿大註冊會計師協會)共同制定的安全審計標準,主要對互聯網服務商的系統及業務運作邏輯安全性、保密性等共計七項內容進行近乎嚴苛的審查和鑑證。只有通過 WebTrust 國際安全審計認證的根證書才能預裝到主流的瀏覽器中。

CA機構

CA機構定義

證書頒發機構(CA, Certificate Authority)即頒發數字證書的機構。是負責發放和管理數字證書的權威機構,並作爲電子商務交易中受信任的第三方,承擔公鑰體系中公鑰的合法性檢驗的責任。

有哪些CA機構

目前全球主流的 CA 機構有 Comodo 、Symantec、GeoTrust、DigiCert、Thawte、GlobalSign、RapidSSL 等,其中 Symantec、GeoTrust 都是 DigiCert 機構的子公司,目前市場上主流的 SSL 證書品牌是 Comodo 證書、Symantec 證書、GeoTrust 證書、Thawte 證書和 RapidSSL 證書,還有一些不知名的證書機構也是可以頒發數字證書的。

國內的 CA 機構主要有中國金融認證中心(CFCA)、沃通(WoSign)、數安時代(GDCA)和安信證書(AnTruet)等。

對稱加密

定義

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

常用加密算法

DES、AES、RC2、RC4、RC5 等

示例

public class DES {

public static String encrypt(String content, String key) {
try {
byte[] encryptionBytes = content.getBytes("UTF-8");
SecureRandom random = new SecureRandom();
DESKeySpec desKey = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secureKey = keyFactory.generateSecret(desKey);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, secureKey, random);
byte[] encryptionBase64Bytes = Base64.getEncoder().encode(cipher.doFinal(encryptionBytes));
return new String(encryptionBase64Bytes);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

public static String decrypt(String content, String key) {
try {
byte[] decryptionBytes = Base64.getDecoder().decode(content);
SecureRandom random = new SecureRandom();
DESKeySpec desKey = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secureKey = keyFactory.generateSecret(desKey);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, secureKey, random);
return new String(cipher.doFinal(decryptionBytes), "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}

return null;
}

public static void main(String[] args) {

final String key = "this_is_key";
String content = "九點下班";

String encryptStr = DES.encrypt(content, key);
System.out.println("加密:" + encryptStr);

String decryptStr = DES.decrypt(encryptStr, key);
System.out.println("解密:" + decryptStr);
}
}
image.png

1、李雷想要給韓梅梅發送消息,他們約定使用對稱加密的方式把消息進行加密

2、李雷用密鑰把消息加密然後發送給韓梅梅

3、韓梅梅用同一個密鑰解密,然後看到李雷發送給自己的消息

可以看到使用上面的方式,一旦密鑰泄漏,消息就很容易被破解

非對稱加密

定義

對稱加密算法在加密和解密時使用的是同一個祕鑰,非對稱加密算法需要兩個密鑰來進行加密和解密,這兩個密鑰是公開密鑰(public key,簡稱公鑰)和私有密鑰(private key,簡稱私鑰)。

常用加密算法

RSA、ECC 等

示例

public class RSA {

private static Cipher cipher;

static {
try {
cipher = Cipher.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}

public static void generateKeyPair() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
String publicKeyStr = getKeyString(publicKey);
String privateKeyStr = getKeyString(privateKey);

System.out.println("publicKeyStr :" + publicKeyStr);
System.out.println("privateKeyStr :" + privateKeyStr);
} catch (Exception e) {
e.printStackTrace();
}
}

public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes = Base64.decode(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}


public static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes = Base64.decode(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}


public static String getKeyString(Key key) {
byte[] keyBytes = key.getEncoded();
return Base64.encode(keyBytes);
}


public static String encrypt(String publicKey, String content) {
try {
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));
byte[] encryptBytes = cipher.doFinal(content.getBytes());
return Base64.encode(encryptBytes);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}


public static String decrypt(String privateKey, String content) {
try {
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
byte[] decryptBytes = cipher.doFinal(Base64.decode(content));
return new String(decryptBytes);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}


public static void main(String[] args) {

// generateKeyPair();

final String publicKey = "使用generateKeyPair生成";
final String privateKey = "使用generateKeyPair生成";

String content = "九點下班";
String encryptStr = encrypt(publicKey, content);
System.out.println("加密:" + encryptStr);
String decryptStr = decrypt(privateKey, encryptStr);
System.out.println("解密:" + decryptStr);
}
}
image.png

1、李雷想要給韓梅梅發送消息,他們約定使用非對稱加密的方式把消息進行加密

2、李雷首先要得到韓梅梅的公鑰

2、李雷用韓梅梅的公鑰把消息加密然後發送給韓梅梅

3、韓梅梅用自己的私鑰解密,然後看到李雷發送給自己的消息

韓梅梅給李雷發送消息同理。

數字簽名

數字簽名(Digital Signature)是一種功能類似寫在紙上的普通簽名、但是使用了公鑰加密領域的技術,以用於鑑別數字信息的方法。一套數字簽名通常會定義兩種互補的運算,一個用於簽名,另一個用於驗證。通常我們使用公鑰加密,用私鑰解密。而在數字簽名中,我們使用私鑰加密(相當於生成簽名),公鑰解密(相當於驗證簽名)。我們可以直接對消息進行簽名(即使用私鑰加密,此時加密的目的是爲了簽名,而不是保密),驗證者用公鑰正確解密消息,如果和原消息一致,則驗證簽名成功。但通常我們會對消息的散列值簽名,因爲通常散列值的長度遠小於消息原文,使得簽名(非對稱加密)的效率大大提高。注意,計算消息的散列值不是數字簽名的必要步驟。

TLS與SSL

TLS(傳輸層安全性協議:Transport Layer Security)及其前身 SSL(安全套接層:Secure Sockets Layer)是一種安全協議,目的是爲互聯網通信提供安全及數據完整性保障。

我們訪問我的個人博客  https://democome.com/,然後用 WireShark 抓包看下 TLS 握手的過程。

WireShark抓包TLS握手

TLS 握手有 RSA 握手、ECDH 握手。通過我下面的抓包分析,下面的示例中使用的是 ECDH 握手。使用 WireShark 進行 ip 過濾

ip.dst == 185.199.109.153 or ip.src == 185.199.109.153

TLS 握手過程如下圖,我們現在只關注 Protocol 爲 TLSv1.2 的抓包信息:

image.png

通過上面的圖我們可以發現,TLS 的握手過程主要分爲以下幾步。

  • Client Hello

  • Server Hello

  • Certificate

  • Server Key Exchange

  • Client Key Exchange

其中涉及到了 對稱加密、非對稱加密 等算法,我們來對每一步進行分析。

Client Hello

瀏覽器發送給服務器

image.png

我們需要關注以下內容:

  • TLS版本:1.2

  • 隨機數:Radnom

  • 瀏覽器支持的加密套件:Cipher Suites

可以看到瀏覽器支持的 Cipher Suites 有17種,服務器會從中選擇一個。隨機數會在最後計算主密鑰(master key)即對稱加密所使用的密鑰時使用。

Server Hello

服務器發送給瀏覽器

image.png
  • 隨機數:Radnom

  • 服務器選擇的加密套件:Cipher Suite

可以看到服務器選擇的加密套件是: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

我們看下一每一部分的含義

ECDHE:密鑰協商算法

RSA:證書公鑰加密算法

AES_128:對稱加密算法、AES的密碼長度

GCM:AES加密模式

SHA256:驗證消息的消息摘要算法(哈希算法)

Certificate

服務器發送給瀏覽器

在 Server Hello 過程中服務器已經選擇好了加密套件。服務器下發證書,攜帶了 CA 證書鏈和證書的公鑰。在證書鏈最上層有一個根 CA 證書,這個證書存儲在瀏覽器或者操作系統中,由系統直接信任的。

我們先在瀏覽器中看一下證書鏈如下:

image.png

然後再看一下 macOS 系統根證書,可以發現最上層的證書是系統信任的。

image.png

瀏覽器驗證服務器證書的過程如下,首先找到找到 democome.com 證書的中級證書頒發機構 Let's Encrypt Authority X3 ,然後再往上找直到根證書,這裏就是 DST Root CA X3。

然後從根證書開始往下去驗證數字簽名。在這個例子中用 DST Root CA X3 的公鑰驗證 Let's Encrypt Authority X3 證書的數字簽名。再用 Let's Encrypt Authority X3 證書的公鑰驗證服務器證書 democome.com 的數字簽名。如果在驗證過程中任何一個環節失敗,那麼這個證書就是不合法的。

Certificate這一步驟信息如下

image.png

證書的公鑰如下圖:

image.png

證書籤名如下圖:

證書的簽名用來確保證書沒有被篡改過。

image.png

Server Key Exchange

服務器發送給瀏覽器

服務器選擇的加密套件爲: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 其中 ECDHE(Elliptic Curve Diffie Hellman Ephemeral)用於密鑰協商。這裏涉及到了橢圓曲線加密。橢圓曲線密碼(Elliptic Curve Cryptography,縮寫:ECC)是一種基於橢圓曲線數學的公開密鑰加密算法。ECC 的主要優勢是在某些情況下它比其他的算法(比如 RSA 加密算法)使用更小的密鑰並提供相當的或更高等級的安全。

image.png

以上 Server Key Exchange 內容我們重點關注 EC Diffie-Hellman Server Params,可以看到 Named Curve 這裏選擇的是 x25519 這條曲線。它的原理可以簡單理解如下:

還是李雷和韓梅梅要寫信

1、李雷用自己的私鑰算出橢圓曲線上點,然後把基點和發送給韓梅梅

2、韓梅梅用自己的私鑰算出橢圓曲線上點發送給李雷

3、根據橢圓曲線計算規則雙方共同計算出的是相同的。

這樣就可以進行對稱加密了,並且加密的密鑰沒有在網絡上傳遞過。其實這個計算出來的也不是最終對稱加密的密鑰這裏可以理解爲 premaster key ,最終還會用瀏覽器和服務器雙方的隨機數再進行一個計算(PRF)得到真正的對稱加密密鑰 master key。

image.png

上圖中的 Pubkey 就可以理解爲服務器計算的橢圓上一點。

以下內容主要是橢圓曲線加密算法的一些數學原理,不感興趣可以忽略,直接到 Client Key Exchange 這一步驟。

DH 算法

DH(Diffie–Hellman key exchange)它可以讓雙方在完全沒有對方任何預先信息的條件下通過不安全信道創建起一個密鑰。這個密鑰可以在後續的通訊中作爲對稱密鑰來加密通訊內容。

image.png

簡單解釋一下,假如通信的雙方是 李雷 和 韓梅梅

前提條件:

  • 是 李雷 的私鑰,是 韓梅梅 的私鑰。

  • 是一個質數,是公開的

  • 是的一個原根,是公開的

協商過程:

第一步:李雷 根據自己的私鑰計算出自己的 公鑰

第二步:李雷 將、和發送給 韓梅梅

第三步:韓梅梅 根據自己的私鑰計算出自己的 公鑰

第四步:韓梅梅 把自己的公鑰發送給 李雷

第五步:李雷 計算對稱加密的密鑰

第六步:韓梅梅 計算對稱加密的密鑰

由上圖的推導可知最終計算的是相同的。

具體例子:

李雷 與 韓梅梅 協定使用以及。 李雷 的私鑰, 計算併發送給 韓梅梅。韓梅梅 的私鑰, 計算併發送給 李雷。李雷 計算韓梅梅 計算

可以看到對稱加密的密鑰並沒有在 李雷 和 韓梅梅 之間傳輸,但是計算出來的結果是一樣的。

ECC算法

橢圓曲線密碼(Elliptic Curve Cryptography,縮寫:ECC)是一種基於橢圓曲線數學的公開密鑰加密算法。ECC的主要優勢是在某些情況下它比其他的算法(比如RSA加密算法)使用更小的密鑰並提供相當的或更高等級的安全。

橢圓曲線的方程如下:

橢圓曲線的函數圖像如下:

image.png
image.png

可以看到是關於 X 軸對稱的。

橢圓曲線運算

過曲線上 A、B 兩點與橢圓曲線交與點 C,點 C 關於 A 軸做對稱,與橢圓曲線的交點定義爲 A+B。

image.png

考慮加法的一種特殊情況,如果 A = B,也就A(B)是橢圓曲線的切點,這個時候在重複上面的運算得到 A+A = 2A。

image.png

A 關於 X 軸做對稱得到的點定義爲 -A。

image.png

下面有兩張動態圖,描述了這一過程:

A+B = C

A+C = D

A+D = E

img

A 和 B 重合演示如下:

img

有了以上和的運算,如果已知橢圓曲線上一點,我們可以求出、、、、...  ,但是反過來如果我們已知,要想求出是非常困難的。

橢圓曲線的有限域

橢圓曲線加密算法並非使用實數域,而是使用有限域,那麼我們把橢圓曲線定義在有限域上。

用表示橢圓曲線方程,在有限域中,表示所有在同餘()意義上滿足該方程的點。

舉例:加入我們的曲線是即。那麼。

點滿足,

所以點在曲線上。

以上是離散化之後的點。利用橢圓曲線進行加密通信的過程如下(這裏給出推理過程,涉及到的運算比較複雜,需要的數學知識比較多,我還在研究中):

1、李雷選擇一條曲線,取橢圓曲線上一點作爲基點。

2、李雷選擇一個私鑰,然後生成公鑰

3、李雷把、公鑰和 基點傳給韓梅梅

4、韓梅梅得到以上信息,把明文編碼到上一點,併產生一個隨機數

5、韓梅梅計算和

6、韓梅梅把傳給李雷

7、李雷收到信息後,計算結果就是點

因爲

數學概念

有限域

在數學中,有限域(finite field)是包含有限個元素的域。與其他域一樣,有限域是進行加減乘除運算都有定義並且滿足特定規則的集合。有限域最常見的例子是當爲素數時,整數對取模。有限域的元素個數稱爲它的

數學裏面的羣是一類定義了二元運算(我們稱之爲加法,用符號+表示)的集合。如果想讓集合變成一個羣,我們必須定義滿足如下四條性質的加法:

1、封閉性:如果和屬於,那麼也屬於;

2、結合律:;

3、存在單位元(注:在二元運算中,單位元指與任意元素運算不改變其值的元素,以實數爲例,乘法單位元爲1,加法單位元爲0)使得;

4、每個元素都存在逆元素,也即對於任意元素存在使得;

如果我們添加第五條要求:

5、交換律:

那麼這個羣就是阿貝爾羣。

Curve25519

在密碼學中,Curve25519 是一種橢圓曲線,被設計用於橢圓曲線迪菲-赫爾曼(ECDH)密鑰交換方法。它是不被任何已知專利覆蓋的最快 ECC 曲線之一。

Curve25519 橢圓曲線方程爲:,使用基點

ECDH

還以 李雷 和 韓梅梅 爲例,把 DH 的交換內容改爲曲線上的點

image.png

當我們選擇 Curve25519 是一種橢圓曲線時,參數是確定的,G 也是確定的,所以只交換雙方的公鑰即可。

Client Key Exchange

瀏覽器發送給服務器

同理,這裏的 Pubkey 就可以理解爲瀏覽器計算的橢圓上一點。這一步和 Server Key Exchange 類似,都是爲了計算對稱加密的密鑰。

image.png

對稱加密通信

有了上面的基礎,瀏覽器可以計算出一個對稱加密密鑰,服務器可以計算出一個對稱加密密鑰,儘管這兩個密鑰沒有在網絡上傳輸,但是可以保證這兩個密鑰是相同的。這樣使用這個密鑰進行加密就可以在網絡上進行傳輸了。

以上就是關於 TLS 握手的基本過程,保證了數據在網絡上傳遞的安全性。

X.509

X.509 是密碼學裏公鑰證書的格式標準。X.509 證書已應用在包括 TLS/SSL 在內的衆多網絡協議裏,同時它也用在很多非在線應用場景裏,比如電子簽名服務。X.509 證書裏含有公鑰、身份信息(比如網絡主機名,組織的名稱或個體名稱等)和簽名信息(可以是證書籤發機構 CA 的簽名,也可以是自簽名)。對於一份經由可信的證書籤發機構簽名或者可以通過其它方式驗證的證書,證書的擁有者就可以用證書及相應的私鑰來創建安全的通信,對文檔進行數字簽名。

工具

在線畫圖工具:https://www.desmos.com/calculator/ialhd71we3

參考文章

SSL證書CA機構:https://ssl.idcspy.net/5687.html

數字證書與網絡安全:http://www.cac.gov.cn/2015-06/02/c_1115480021.htm

數字簽名是什麼?https://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html

橢圓曲線加密:https://zh.wikipedia.org/wiki/橢圓曲線密碼學

Curve25519

橢圓曲線密碼學的簡單介紹:https://zh.wikipedia.org/wiki/Curve25519

TLS的握手流程:https://zhuanlan.zhihu.com/p/37636276

再談HTTPS:https://zhuanlan.zhihu.com/p/75461564

ECC橢圓曲線加解密原理詳解(配圖):https://blog.csdn.net/sitebus/article/details/82835492

ECC橢圓曲線加密算法:介紹:https://zhuanlan.zhihu.com/p/36326221

新手上路:實數上的橢圓曲線和羣論:https://zhuanlan.zhihu.com/p/34363494

密碼學基礎2:橢圓曲線密碼學原理分析:https://www.jianshu.com/p/3b810faff3ba

HTTPS 溫故知新(五) —— TLS 中的密鑰計算:https://halfrost.com/https-key-cipher/

有限域:https://zh.wikipedia.org/wiki/有限域

瞭解更多,請關注公衆號: 九點下班

相關文章