密碼學概述
密碼學是指研究信息加密,破解密碼的技術科學。密碼學的起源可追溯到2000
年前。而當今的密碼學是以數學為基礎的。
發展歷史
密碼學的歷史大致可以追溯到兩千年前,相傳古羅馬名將凱撒大帝為了防止敵方截獲情報,用密碼傳送情報。凱撒的做法很簡單,就是對二十幾個羅馬字母建立一張對應表。這樣,如果不知道密碼本,即使截獲一段信息也看不懂
凱撒密碼(
Caesar cipher
):
從凱撒大帝時代到上世紀
70
年代這段很長的時間里,密碼學的發展非常的緩慢,因為設計者基本上靠經驗,沒有運用數學原理這種加密方式的弊端
- 密碼本泄露,密碼將被破解
- 獲取足夠多的情報,通過大數據分析,統計字母出現頻率,也能找到其中的規則
在
1976年
以前,所有的加密方法都是同一種模式:加密、解密使用同一種算法。在交互數據的時候,彼此通信的雙方就必須將規則告訴對方,否則沒法解密。那么加密和解密的規則(簡稱密鑰
),它保護就顯得尤其重要。傳遞密鑰就成為了最大的隱患。這種加密方式被成為對稱加密算法
(symmetric encryption algorithm
)
1976年
,兩位美國計算機學家迪菲
(W.Diffie
)、赫爾曼
(M.Hellman
) 提出了一種嶄新構思,可以在不直接傳遞密鑰的情況下,完成密鑰交換。這被稱為“迪菲赫爾曼密鑰交換
”算法。開創了密碼學研究的新方向
1977
年,三位麻省理工學院的數學家羅納德·李維斯特
(Ron Rivest
)、阿迪·薩莫爾
(Adi Shamir
)和倫納德·阿德曼
(Leonard Adleman
)一起設計了一種算法,可以實現非對稱加密
。這個算法用他們三個人的名字命名,叫做RSA
算法
RSA數學原理
上世紀70
年代產生的一種加密算法。其加密方式比較特殊,需要兩個密鑰:公開密鑰簡稱公鑰(publickey
)和私有密鑰簡稱私鑰(privatekey
)。公鑰加密,私鑰解密;私鑰加密,公鑰解密。這個加密算法就是偉大的RSA
取模算法
通過數學進行加密,必須滿足一個算法,加密容易,但通過加密結果反算原始內容一定要很難
早期的
取模算法
,在西方稱為時鐘算數
- 環,即:取模,或者可將取模運算理解是環上的運算
- 環即是取模,也是周期,取模即是周期
質數
質數又稱素數。一個大于
1
的自然數,除了1
和它自身外,不能被其他自然數整除的數叫做質數;否則稱為合數。規定1
既不是質數也不是合數質數
2
,是一個特殊的質數
- 是最小的質數
- 是質數中唯一的偶數
- 是偶數中唯一的質數
- 假如兩個或偶數個質數之和為奇數,則其中必定有一個是
2
- 假如兩個或偶數個質數只差為奇數,則其中必定有一個是
2
- 假如三個或奇數個質數之和為偶數,則其中必定有一個是
2
- 假如三個或奇數個質數之差為偶數,則其中必定有一個是
2
- 假如若干個質數之積為偶數,則其中必定有一個是
2
原根
原根是一種數學符號,設
n
是正整數,m
是整數,若m
模n
的階等于φ(n)
,則稱m
為模n
的一個原根原根存在的條件有以下幾個:
- 設
n
是奇質數,則模n
的原根存在- 設
m
是模n
的原根,則m
或m + n
是模n ^ 2
的原根- 設
n
是奇質數,則對任意e
,模n ^ e
的原根存在- 設
e >= 1
,若m
是模n ^ e
的一個原根,則m
與m + n ^ e
中的奇數是模2 * n ^ e
的一個原根例如:使用質數
17
作為模數,再使用一個比17
小的質數3
模以17
3 % 17
,此時3
的1-16
次方模以17
,得到的如下結果:
3
的1-16
次方,模擬17
的結果都不一樣。3
的17
次方,模以17
的結果為3
,和3
的1
次方模以17
的結果一樣。3
的18
次方和2
次方的結果一樣...上述規律,稱之為
3
是17
的原根
離散對數問題
如果使用上述規律作為算法,
3
的x
次方的結果,一定是1-16
之間的數字,但是通過結果反算x
很難當模數的質數越大,反算的難度就會越大,這種情況被稱之為
離散對數問題
歐拉函數φ
互質關系:如果兩個正整數,除了
1
以外,沒有其他公因數,我們就稱這兩個數是互質關系(coprime
)任意給定正整數
n
,在小于等于n
的正整數之中,有多少個數
可以與n
構成互質關系?計算這個值的公式叫做歐拉函數,使用:
φ(n)
表示
案例1:
計算
8
的歐拉函數,和8
互質的1
、2、3
、4、5
、6、7
、8
φ(8) = 4
案例2:
計算
7
的歐拉函數,和7
互質的1
、2
、3
、4
、5
、6
、7
φ(7) = 6
歐拉函數特點:
當
n
是質數的時候,φ(n) = n - 1
如果
n
可以分解成兩個互質的整數之積
n = p1 * p2
φ(p1 * p2) = φ(p1) * φ(p2)
根據以上兩點得到:
- 如果
n
是兩個質數p1
和p2
的乘積,且p1
和p2
互質φ(n) = φ(p1) * φ(p2) = (p1 - 1) * (p2 - 1)
案例3:
計算
56
的歐拉函數
φ(56) = φ(8) * φ(7) = 4 * 6 = 24
歐拉定理
- 如果兩個正整數
m
和n
互質,那么m
的φ(n)
次方減去1
,可以被n
整除m ^ φ(n) - 1 % n ≡ 0
↓m ^ φ(n) % n ≡ 1
例如:
m = 5
,n = 8
,φ(8) = 4
5 ** 4 % 8 ------------------------- 1
費馬小定理
- 歐拉定理的特殊情況:如果兩個正整數
m
和n
互質,而且n
為質數φ(n)
結果就是n - 1
m ^ (n - 1) % n ≡ 1
例如:
m = 6
,n = 5
6 ** (5 - 1) % 5 ------------------------- 1
公式轉換
①
費馬小定理
m ^ φ(n) % n ≡ 1
②
由于1 ^ k ≡ 1
- 將
m ^ φ(n) % n
看作一個整體x
x ≡ m ^ φ(n) % n ≡ 1
↓x ^ k ≡ 1 ^ k
當
m
和n
互質
x ^ k ≡ m ^ (k * φ(n)) % n
↓m ^ (k * φ(n)) % n ≡ 1
例如:
m = 6
,n = 5
,k = 3
6 ** (3 * (5 - 1) ) % 5 ------------------------- 1
③
由于1 * m ≡ m
m ^ (k * φ(n) + 1) % n ≡ m
例如:
m = 6
,n = 7
,k = 3
6 ** (3 * (7 - 1) + 1) % 7 ------------------------- 6
- 注:必須
m
小于n
,此公式才成立
模反元素
④
如果兩個正整數e
和x
互質,那么一定可以找到整數d
,使得ed - 1
被x
整除。d
就是e
對于x
的“模反元素
”
e * d - 1 % x ≡ 0
↓e * d % x ≡ 1
⑤
由公式④
推導
e * d - 1 % x ≡ 0
↓e * d - 1 / x ≡ k
↓e * d - 1 ≡ k * x
↓e * d ≡ k * x + 1
⑥
由公式③
推導,如果x = φ(n)
:
m ^ (k * φ(n) + 1) % n ≡ m
↓m ^ (k * x + 1) % n ≡ m
由公式
⑤
推導,e
和x
(φ(n)
)互質,得到以下公式:
e * d ≡ k * x + 1
↓m ^ (e * d) % n ≡ m
案例:
m = 4
,n = 15
,當x
的值等于φ(n)
x = φ(n) = φ(15) = φ(3) * φ(5) = 2 * 4 = 8
e
和x
互質,e = 3
e * d - 1 / x ≡ k
↓e * d - 1 = x * k
↓d = (x * k + 1) / e
計算
d
的值
k = 4
,(8 * 4 + 1) / 3
,d = 11
k = 7
,(8 * 7 + 1) / 3
,d = 19
d = 11
,代入公式:m ^ (e * d) % n ≡ m
4 ** (3 * 11) % 15 ------------------------- 4
d = 19
,代入公式:m ^ (e * d) % n ≡ m
4 ** (3 * 19) % 15 ------------------------- 4
迪菲赫爾曼密鑰交換
迪菲赫爾曼密鑰交換
是一種安全協議。它可以讓雙方在完全沒有對方任何預先信息的條件下通過不安全信道創建起一個密鑰。這個密鑰可以在后續的通訊中作為對稱密鑰
來加密通訊內容使用對稱加密,假設
10
為密鑰
- 服務端與客戶端加解密,需要服務端傳遞
密鑰
給客戶端。如果密鑰
被第三方竊取,加密則不再安全使用
迪菲赫爾曼密鑰交換
,假設一個傳遞密鑰
的場景,算法是3
的n
次方模以17
- 服務端和客戶端,分別通過算法計算出兩個隨機數,
15
和13
- 兩端使用相同的算法,計算出
6
和12
- 兩端將結果
6
和12
傳遞給對方- 兩端再次使用相同的算法,都計算出結果
10
- 案例中,
10
才是對稱加密
真正使用的密鑰
。在數據傳輸中,第三方只能竊取到6
和12
兩個數字。即便知道算法,再得不到15
和13
的情況下,也無法計算出密鑰
迪菲赫爾曼密鑰交換
公式原理:
- 公式成立的條件在于,
3
是17
的原根- 公式
3 ^ (13 * 15) % 17
就是模反元素公式⑥
的m ^ (e * d) % n ≡ m
,相當于將其拆分成兩步
RSA算法
RSA
公開密鑰密碼體制的原理是:根據數論,尋求兩個大質數比較簡單,而將它們的乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰
n
會非常大,長度一般為1024
個二進制位。目前人類已經分解的最大整數,232
個十進制位,768
個二進制位- 由于需要求出
φ(n)
,所以根據歐函數特點,最簡單的方式n
由兩個質數相乘得到。質數:p1
、p2
φ(n) = (p1 - 1) * (p2 - 1)
- 最終由
φ(n)
得到e
和d
總共生成
6個
數字:p1
、p2
、n
、φ(n)
、e
、d
- 公鑰:
n
和e
- 私鑰:
n
和d
- 明文:
m
- 密文:
c
案例:
m = 12,n = 15,φ(n) = 8,e = 3,d = 11
加密:
m ^ e % n = c
12 ** 3 % 15 ------------------------- 3
解密:
c ^ d % n = m
3 ** 11 % 15 ------------------------- 12
RSA
的安全:
- 除了公鑰用到了
n
和e
,其余的4
個數字是不公開的目前破解
RSA
得到d
的方式如下:
- 要想求出私鑰
d
,由于e * d = φ(n) * k + 1
。需要知道e
和φ(n)
e
是知道的,但是要得到φ(n)
,就必須知道p1
和p2
- 由于
n = p1 * p2
。只有將n
因數分解才能算出
運算速度
- 由于進行的都是大數計算,使得
RSA
最快的情況也比DES
慢上好幾倍RSA
的速度比對應同樣安全級別的對稱密碼算法要慢1000
倍左右- 速度一直是
RSA
的缺陷,所以大量數據
并不適合RSA
,一般來說只用于少量數據
加密- 日常開發中,大數據采用
對稱加密
,例如:DES
。而對稱加密
使用的密鑰
,則通過RSA
進行加密
終端命令
Mac
的終端可以直接使用OpenSSL
進行RSA
的命令運行。
OpenSSL
由于
Mac
系統內置開源加密庫OpenSSL
,所以在終端上可以直接使用命令運行RSA
,OpenSSL
中RSA
算法常用指令主要有三個:
命令 含義 genrsa
生成并輸入一個 RSA
私鑰result
使用 RSA
密鑰進行加密、解密、簽名和驗證等運算rsa
處理 RSA
密鑰的格式轉換等問題
案例1:
生成
RSA
私鑰,密鑰長度為1024bit
openssl genrsa -out private.pem 1024 ------------------------- Generating RSA private key, 1024 bit long modulus (2 primes) ...........+++++ ..+++++ e is 65537 (0x010001)
從
私鑰
中提取公鑰
openssl rsa -in private.pem -pubout -out public.pem ------------------------- writing RSA key
生成
私鑰
和公鑰
的證書文件
使用
cat private.pem
命令,查看private.pem
內容-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQCzxKp3IKq2SHTqJXgZ0aU0lCHJl/f6VWZs5PXsB26yoe6kwqDN HJWba8hPY7eewAq9/HUyH1MhQUUKwOj8+etwrdfwd0aPwYsRdtT2QzC2LRT1y43A +IUR0uUbGE1kMROPheyWcBmTA/zcXAINKhGF/Z/pUCzouoUbNh950VHfQQIDAQAB AoGASMhpVA4Pz/mKDHrbI2j0AFOxUlOK/PmynIge4U8pDH3vhxmdzS2zjNeYpDv1 Tfrm3oDmWkLAf4hTkcUFD9eH8MsNsnORUnn+PbHGIysrArDdwbOtj4LE66YHfQxN lf/Gi4Zpao4p5wBcsiZYaOWtor5oUsLOf1kKlIqt5/8szZkCQQDjmpVebA34lZFj 7dqXqZsYEB4HWHOnbtnV12UM77BqzPoAZjapAEa2Ofn/ct3RIqvXWrmY3pH6PiQQ KJUk1+DfAkEAyjJD8vBoUiWH8ktNmHE5ua/H1Vmk6to5MenjKRNj9ACB/BvopfaS xSr2PuVeQU9AOZNEGduadxaTOLJPCsmj3wJAdJ+n++roOcEB769X+7B3fRv9Fwx2 rot5aT5mU/uZbRA85el6BpzSntsUQ5VrHZdjcATX5wHc0Nn4hqMU0P0hBwJBAJC7 6me8LvCebPHDdYfphKimayUNRj/WdZqFEVYVyzaeJm2QjLhACE+asSnUheO6Fv8f q1/XEnqsbjXnbS0LqYECQQCi+amvIpqvCUJeFDM9A9noPTEkAHWClBuCmBCeHl8+ RJdYx9ZJj3w81013xir06pX3YTKQvbzWpEUcNMBPl4N/ -----END RSA PRIVATE KEY-----
- 二進制文件,以
Base64
編碼格式展示,占887字節
使用
cat public.pem
命令,查看public.pem
內容-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzxKp3IKq2SHTqJXgZ0aU0lCHJ l/f6VWZs5PXsB26yoe6kwqDNHJWba8hPY7eewAq9/HUyH1MhQUUKwOj8+etwrdfw d0aPwYsRdtT2QzC2LRT1y43A+IUR0uUbGE1kMROPheyWcBmTA/zcXAINKhGF/Z/p UCzouoUbNh950VHfQQIDAQAB -----END PUBLIC KEY-----
- 二進制文件,以
Base64
編碼格式展示,占272字節
公鑰
比私鑰
小很多
案例2:
創建
message.txt
文件,寫入以下內容:ha ha ha ~
通過
公鑰
加密openssl rsautl -encrypt -in message.txt -inkey public.pem -pubin -out enc.txt
使用
cat enc.txt
命令,查看加密內容
enc.txt
為二進制文件,顯示亂碼通過
私鑰
加密openssl rsautl -decrypt -in enc.txt -inkey private.pem -out dec.txt
使用
cat dec.txt
命令,查看解密內容ha ha ha ~
- 原文
11字節
,密文128字節
,使用RSA
加密,數據增大很多
案例3:
通過
私鑰
簽名openssl rsautl -sign -in message.txt -inkey private.pem -out enc.txt
使用
cat enc.txt
命令,查看加密內容
- 二進制文件, 無法直接查看
通過
公鑰
驗證openssl rsautl -verify -in enc.txt -inkey public.pem -pubin -out dec.txt
使用
cat dec.txt
命令,查看解密內容ha ha ha ~
案例4:
將
私鑰
轉換成為明文openssl rsa -in private.pem -text -out private.txt ------------------------- writing RSA key
使用
cat private.txt
命令,查看明文內容RSA Private-Key: (1024 bit, 2 primes) modulus: 00:b3:c4:aa:77:20:aa:b6:48:74:ea:25:78:19:d1: a5:34:94:21:c9:97:f7:fa:55:66:6c:e4:f5:ec:07: 6e:b2:a1:ee:a4:c2:a0:cd:1c:95:9b:6b:c8:4f:63: b7:9e:c0:0a:bd:fc:75:32:1f:53:21:41:45:0a:c0: e8:fc:f9:eb:70:ad:d7:f0:77:46:8f:c1:8b:11:76: d4:f6:43:30:b6:2d:14:f5:cb:8d:c0:f8:85:11:d2: e5:1b:18:4d:64:31:13:8f:85:ec:96:70:19:93:03: fc:dc:5c:02:0d:2a:11:85:fd:9f:e9:50:2c:e8:ba: 85:1b:36:1f:79:d1:51:df:41 publicExponent: 65537 (0x10001) privateExponent: 48:c8:69:54:0e:0f:cf:f9:8a:0c:7a:db:23:68:f4: 00:53:b1:52:53:8a:fc:f9:b2:9c:88:1e:e1:4f:29: 0c:7d:ef:87:19:9d:cd:2d:b3:8c:d7:98:a4:3b:f5: 4d:fa:e6:de:80:e6:5a:42:c0:7f:88:53:91:c5:05: 0f:d7:87:f0:cb:0d:b2:73:91:52:79:fe:3d:b1:c6: 23:2b:2b:02:b0:dd:c1:b3:ad:8f:82:c4:eb:a6:07: 7d:0c:4d:95:ff:c6:8b:86:69:6a:8e:29:e7:00:5c: b2:26:58:68:e5:ad:a2:be:68:52:c2:ce:7f:59:0a: 94:8a:ad:e7:ff:2c:cd:99 prime1: 00:e3:9a:95:5e:6c:0d:f8:95:91:63:ed:da:97:a9: 9b:18:10:1e:07:58:73:a7:6e:d9:d5:d7:65:0c:ef: b0:6a:cc:fa:00:66:36:a9:00:46:b6:39:f9:ff:72: dd:d1:22:ab:d7:5a:b9:98:de:91:fa:3e:24:10:28: 95:24:d7:e0:df prime2: 00:ca:32:43:f2:f0:68:52:25:87:f2:4b:4d:98:71: 39:b9:af:c7:d5:59:a4:ea:da:39:31:e9:e3:29:13: 63:f4:00:81:fc:1b:e8:a5:f6:92:c5:2a:f6:3e:e5: 5e:41:4f:40:39:93:44:19:db:9a:77:16:93:38:b2: 4f:0a:c9:a3:df exponent1: 74:9f:a7:fb:ea:e8:39:c1:01:ef:af:57:fb:b0:77: 7d:1b:fd:17:0c:76:ae:8b:79:69:3e:66:53:fb:99: 6d:10:3c:e5:e9:7a:06:9c:d2:9e:db:14:43:95:6b: 1d:97:63:70:04:d7:e7:01:dc:d0:d9:f8:86:a3:14: d0:fd:21:07 exponent2: 00:90:bb:ea:67:bc:2e:f0:9e:6c:f1:c3:75:87:e9: 84:a8:a6:6b:25:0d:46:3f:d6:75:9a:85:11:56:15: cb:36:9e:26:6d:90:8c:b8:40:08:4f:9a:b1:29:d4: 85:e3:ba:16:ff:1f:ab:5f:d7:12:7a:ac:6e:35:e7: 6d:2d:0b:a9:81 coefficient: 00:a2:f9:a9:af:22:9a:af:09:42:5e:14:33:3d:03: d9:e8:3d:31:24:00:75:82:94:1b:82:98:10:9e:1e: 5f:3e:44:97:58:c7:d6:49:8f:7c:3c:d7:4d:77:c6: 2a:f4:ea:95:f7:61:32:90:bd:bc:d6:a4:45:1c:34: c0:4f:97:83:7f -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQCzxKp3IKq2SHTqJXgZ0aU0lCHJl/f6VWZs5PXsB26yoe6kwqDN HJWba8hPY7eewAq9/HUyH1MhQUUKwOj8+etwrdfwd0aPwYsRdtT2QzC2LRT1y43A +IUR0uUbGE1kMROPheyWcBmTA/zcXAINKhGF/Z/pUCzouoUbNh950VHfQQIDAQAB AoGASMhpVA4Pz/mKDHrbI2j0AFOxUlOK/PmynIge4U8pDH3vhxmdzS2zjNeYpDv1 Tfrm3oDmWkLAf4hTkcUFD9eH8MsNsnORUnn+PbHGIysrArDdwbOtj4LE66YHfQxN lf/Gi4Zpao4p5wBcsiZYaOWtor5oUsLOf1kKlIqt5/8szZkCQQDjmpVebA34lZFj 7dqXqZsYEB4HWHOnbtnV12UM77BqzPoAZjapAEa2Ofn/ct3RIqvXWrmY3pH6PiQQ KJUk1+DfAkEAyjJD8vBoUiWH8ktNmHE5ua/H1Vmk6to5MenjKRNj9ACB/BvopfaS xSr2PuVeQU9AOZNEGduadxaTOLJPCsmj3wJAdJ+n++roOcEB769X+7B3fRv9Fwx2 rot5aT5mU/uZbRA85el6BpzSntsUQ5VrHZdjcATX5wHc0Nn4hqMU0P0hBwJBAJC7 6me8LvCebPHDdYfphKimayUNRj/WdZqFEVYVyzaeJm2QjLhACE+asSnUheO6Fv8f q1/XEnqsbjXnbS0LqYECQQCi+amvIpqvCUJeFDM9A9noPTEkAHWClBuCmBCeHl8+ RJdYx9ZJj3w81013xir06pX3YTKQvbzWpEUcNMBPl4N/ -----END RSA PRIVATE KEY-----
- 上面是二進制數據,最后面的是
私鑰
- 其中
publicExponent: 65537 (0x10001)
就是e
公鑰
和e
,在私鑰
中已經存在。公鑰
是通過私鑰
計算得到的
代碼演示
RSA
代碼加解密,iOS
無法直接使用.pem
證書,需要使用p12
和der
案例1:
通過
私鑰
生成.csr
請求文件openssl req -new -key private.pem -out rsacert.csr
- 按提示輸入信息
目錄下生成
rsacert.csr
文件
- 通過
私鑰
生成.csr
請求文件,將其發給頒發證書的機構進行簽名,證明此證書的合法性。例如:https
使用的ssl
證書
案例2:
對
.csr
文件自簽名,生成.crt
證書openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt ------------------------- Signature ok subject=C = CN, ST = BJ, L = BJ, O = LG, OU = LG, CN = LG, emailAddress = Zang@163.com Getting Private key
- 自簽名證書是未經認證的,不受各類瀏覽器信任。僅用來案例演示,自娛自樂
目錄下生成
rsacert.crt
證書文件
- 例如:使用
https
協議,需要將.crt
證書放在服務器上,供客戶端接收使用
cat rsacert.crt
命令,查看證書內容-----BEGIN CERTIFICATE----- MIICWDCCAcECFGuo1neUJVorMs1aHTn7m+JM79dwMA0GCSqGSIb3DQEBCwUAMGsx CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJCSjELMAkGA1UEBwwCQkoxCzAJBgNVBAoM AkxHMQswCQYDVQQLDAJMRzELMAkGA1UEAwwCTEcxGzAZBgkqhkiG9w0BCQEWDFph bmdAMTYzLmNvbTAeFw0yMTA0MTMxMDM5MTNaFw0zMTA0MTExMDM5MTNaMGsxCzAJ BgNVBAYTAkNOMQswCQYDVQQIDAJCSjELMAkGA1UEBwwCQkoxCzAJBgNVBAoMAkxH MQswCQYDVQQLDAJMRzELMAkGA1UEAwwCTEcxGzAZBgkqhkiG9w0BCQEWDFphbmdA MTYzLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs8SqdyCqtkh06iV4 GdGlNJQhyZf3+lVmbOT17AdusqHupMKgzRyVm2vIT2O3nsAKvfx1Mh9TIUFFCsDo /PnrcK3X8HdGj8GLEXbU9kMwti0U9cuNwPiFEdLlGxhNZDETj4XslnAZkwP83FwC DSoRhf2f6VAs6LqFGzYfedFR30ECAwEAATANBgkqhkiG9w0BAQsFAAOBgQAnuiB9 lxiV8ZIzElUx0JMxGXdhdxeKGouTpXysbVpqsppYe258bt9pYddU19ZedGgmOPT3 GVd60CoHCMWAJhMdVNpW+09bC+5hqNLGrAHM38bMEJkhHxAA5NUSwfC594K8j5bT Plqei6QtutsTZ9FYLiuWhk5EufYgZJMsD9t/TA== -----END CERTIFICATE-----
- 二進制文件,直接查看是亂碼,所以使用
Base64
編碼
案例3:
通過
.crt
證書,生成.der
證書openssl x509 -outform der -in rsacert.crt -out rsacert.der
.der
就是公鑰
目錄下生成
rsacert.der
證書文件
案例4:
通過
私鑰
和.crt
證書,導出.p12
證書openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt ------------------------- Enter Export Password: Verifying - Enter Export Password:
- 需要對
.p12
設置密碼.p12
就是私鑰
目錄下生成
p.p12
證書文件
.p12
和.der
證書是一對,分別對應私鑰
和公鑰
案例5:
使用
RSA
代碼加解密打開
RSADemo
項目,將.p12
和.der
證書拖進項目中
- 勾選
Add to targets
選項使用
RSACryptor
庫,提供以下方法:#import <Foundation/Foundation.h> @interface RSACryptor : NSObject + (instancetype)sharedRSACryptor; //生成密鑰對 - (void)generateKeyPair:(NSUInteger)keySize; //加載公鑰 - (void)loadPublicKey:(NSString *)publicKeyPath; //加載私鑰 - (void)loadPrivateKey:(NSString *)privateKeyPath password:(NSString >*)password; //加密數據 - (NSData *)encryptData:(NSData *)plainData; //解密數據 - (NSData *)decryptData:(NSData *)cipherData; @end
打開
ViewController.m
文件,加載公鑰
和私鑰
#import "ViewController.h" #import "RSACryptor.h" @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [[RSACryptor sharedRSACryptor] loadPublicKey:[[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil]]; [[RSACryptor sharedRSACryptor] loadPrivateKey:[[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil] password:@"123456"]; } @end
在
touchesBegan
方法中,實現RSA
加解密代碼-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSString *strText = @"hello"; NSData *dataEncrypt = [[RSACryptor sharedRSACryptor] encryptData:[strText dataUsingEncoding:NSUTF8StringEncoding]]; NSString *strEncrypt = [dataEncrypt base64EncodedStringWithOptions:0]; NSLog(@"加密:%@", strEncrypt); NSData *dataDecrypt = [[RSACryptor sharedRSACryptor] decryptData:dataEncrypt]; NSString *strDecrypt = [[NSString alloc] initWithData:dataDecrypt encoding:NSUTF8StringEncoding]; NSLog(@"解密:%@", strDecrypt); }
- 加密和解密,返回的都是二進制數據,無法直接查看
運行項目,點擊屏幕,輸出以下內容:
加密:Lw+Qvesbk1QfSyXh/dGoGmGuUngZQVUhnsLA+zFFaAqF8U2NJY/lAArzH2RZ2mdIGA5+ty2SHS+lWUshTsJebteC9JR7lydw31mIlWac4EtEue4ZaJZAYOALBVSGVKlW9q8Ra4hW9KRBFdDfzFa+0BFn0d6P7Xfv5M15IwOuDfc= 解密:hello
- 將加密后二進制數據,進行
Base64
編碼,可查看編碼后內容- 將解密后二進制信息,進行
UTF8
編碼,可查看原文內容
案例6:
RSA
加密的填充方式上述案例,每次點擊屏幕,輸出的加密結果都不同,但都能解密成原文
hello
加密:NL64/eVWYq7VRS/dqLDTw5WvH1kdLj/ODE5lbeA5C9pT7dDFz2f3hDVN3YjiY6/grMH2QgVvV6sX7mkb+YpmBXHakT13+vtyIw35YJcYb4w9gMzUwyWj6qynS1w3Mg8NioVzFO0diiP5Z/eIPNGS3TX2oeaY7imPSm2awuajO2k= 加密:ajIiKWwXi9OkykqE4nBW8G/hQ1LzyT0+aUqTdiSlQt40Svgj/10mn/gC1OM0Xom6HDX+5R8M9+rHFEK9eM4UrifYKDr+AKsP+rlNFmGEHTyZ5FZwUVVsM7rcNymbCSVvC3S6TPQY3i/G1IuLbiV7rffYufz4ew1b08fnR+tmRHU= 加密:AHth9iyax8banLC7yUJMWxLAZMRY2z/2v7flXoZu/TroPZybT+UzkrSV/haLJDOesqa514BgAnNq7s6vni9uA1yTO0UP2gaTWjvv7CB/TYCPVcALPdd+2FklBvMfXZCcWXpvXZBYQKtt8Fx59REiIKBoVz5tzNR5vz6+5Qj9DPY=
這種現象,和代碼中
RSA
加密的填充方式有關#define kTypeOfWrapPadding kSecPaddingPKCS1
RSA
加密的三種填充方式
kSecPaddingNone
:不填充,每次生成的加密結果都一樣kSecPaddingPKCS1
:最常用的填充方式,默認項kSecPaddingOAEP
:PKCS#1
推出的新的填充方式,安全性是最高
假如密鑰長度為
1024bit
,即:128Byte
:
- 當客戶端選擇
kSecPaddingNone
填充模式時,如果明文不夠128字節
,加密時會在明文前面,前向填充零,每次生成的加密結果都一樣。服務端在解密后,用相同的方式把前向填充的零去掉,才能得到真正的明文- 當選擇
kSecPaddingPKCS1
填充模式時,如果明文不夠128字節
,會在明文中隨機填充一些數據,所以會導致對同樣的明文每次加密后的結果都不一樣。對加密后的密文,服務端使用相同的填充方式解密kSecPaddingOAEP
填充模式, 是PKCS#1
推出的新的填充方式,安全性是最高的,和前面kSecPaddingPKCS1
的區別就是加密前的編碼方式不一樣
總結
密碼學概述
- 加密算法,都是數學知識
- 對稱加密是傳統加密算法
RSA
非對稱加密是現代加密算法RSA
是三位數學家的名字
RSA
數學原理
- 質數
- 原根
- 歐拉函數
- 歐拉定理
- 費馬小定理(正向計算容易,反算難)
- 模反元素:
m ^ (e * d) % n = m
,目的找出e
和d
- 迪菲赫爾曼密鑰交換
RSA
算法
RSA
拆解兩個大質數的乘積很難,所以相對安全- 加密:
m ^ e % n = c
- 解密:
c ^ d % n = m
- 公鑰:
n
和e
- 私鑰:
n
和d
- 明文:
m
- 密文:
c
RSA
成立條件
m
必須小于n
n
是由兩個質數相乘,得到一個很大的數。目的是方便求出φ(n)
d
是e
相對φ(n)
的模反元素n
可以公開,但無法計算組成n
的兩個質數p1
和p2
,找不出p1
和p2
就無法計算φ(n)
,找不出φ(n)
就無法計算e
和d
e
在使用OpenSSL
生成私鑰
時,設定為65537
RSA
的特點
- 加密安全系數非常高
- 加密效率低
- 不適合加密大數據
- 僅用于加密關鍵數據
- 配合對稱加密使用
RSA
算法常用指令
genrsa
:生成并輸入一個RSA
私鑰result
:使用RSA
密鑰進行加密、解密、簽名和驗證等運算rsa
:處理RSA
密鑰的格式轉換等問題代碼演示
私鑰
和公鑰
使用p12
和der
格式
RSA
加密的填充方式
kSecPaddingNone
:不填充,每次生成的加密結果都一樣kSecPaddingPKCS1
:最常用的填充方式,默認項kSecPaddingOAEP
:PKCS#1
推出的新的填充方式,安全性是最高