iOS逆向 RSA理論

前言

這篇文章將從RSA理論RSA終端操做RSA代碼操做三個方面去了解和使用RSA加密。一到四節是理論部分,以爲看的無趣的小夥伴們能夠直接跳到第五節objective-c

數學小課堂
  1. 質數:又叫素數,在大於1的天然數中,除了1和它自己之外再也不有其餘因數的天然數,如2,3,5,7
  2. 因數:又叫約數,整數a除以整數b(b≠0) 的商正好是整數,則b是a的因數,如2是4的約數
  3. 互質:若是兩個正整數,沒有除1之外的公因數,則稱它們爲互質關係,如7和9互質
  4. 取模運算:又叫時鐘運算,與咱們平時所說的取餘運算略有不一樣(二者區別可自行百度,在RSA運算中二者的運算結果是一致的),取模符號爲 mod,取餘符號爲 %
  5. 同餘定理: 冪運算性質:若是a≡b mod m,那麼a^{n}≡b^{n}modm

1、密碼學發展歷史

  1. 早期:使用密碼本(羅馬字母與數字對應的一張表)算法

  2. 1976年之前:對稱加密算法,加密解密使用同一種規則(密鑰),這種規則的保護就顯得極爲重要,一旦泄露或破解,全部的信息都能被解密出來安全

  3. 1976年:「迪費赫爾曼密鑰交換」算法是由美國兩個計算機學家迪費(W.Diffie)、赫爾曼(M.Hellman)共同提出的構思,能夠在不直接傳遞密鑰的狀況下進行密鑰交換服務器

  4. 1977年:RSA加密問世。RSA是由美國麻省理工學院的數學家羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一塊兒提出並用他們的名字命名的函數


2、RSA中的數學原理

  1. 原根:g^{i} mod p ≠ g^{j} mod p (p爲質數),其中i≠j且i, j介於1至(p-1)之間,則g爲p的原根 如:由於3^1 mod 17 = 3,3^2 mod 17 = 9...3^16 mod 17 = 1,3的1~16次方mod17的值都不相同,因此3爲17的原根編碼

  2. 歐拉函數:在小於正整數n的數中,與n互質的數的個數加密

特色:spa

  • 若是n = A * B,且A、B互質,則Φ(n) = Φ(A) * Φ(B)
  • n爲質數時,Φ(n) = n - 1,如Φ(17) = 16
  1. 歐拉定理:若是兩個正整數m和n互質,那麼m的Φ(n)次方減1能夠被n整除

條件: m與n互質code

公式: m^{Φ(n)} mod n ≡ 1orm

  1. 費馬小定理:是歐拉定理的一種特殊狀況,n自身爲質數時,Φ(n) = n - 1

條件: m與n互質,且n爲質數

公式: m^{n-1}mod n ≡ 1

  1. 模反元素:若是兩個正整數e和x互質,那麼必定能夠找到整數d,使得ed-1被x整除,而d被稱做e對於x的模反元素

條件: e與x互質

公式: e * d mod x ≡ 1

  1. 歐拉函數和模反元素的公式推演

接下來咱們利用已知的數學公式來推演公式:

① 在歐拉定理公式中,m^{Φ(n)} mod n ≡ 1等式兩邊同k次方,根據同餘定理的冪運算性質就能夠獲得m^{k*Φ(n)} mod n ≡ 1

② 而後在等式兩邊同乘m,便可得出m^{k*Φ(n)+1} mod n ≡ m

③ 在模反元素公式中,e * d mod x ≡ 1去掉mod運算符。既然ed-1能夠被x整除,那麼ed必然是x的k倍數+1

④ 在x=φ(n)的狀況下,m^{ed} mod n ≡ n

總結: 歐拉函數和模反元素能夠推出RSA加密的前身,並且根據屢次計算,發現所知足的必要條件與歐拉函數並不一致

條件:

  1. m < n;
  2. d是e對於φ(n)的模反元素;

公式:m^{ed} mod n ≡ n

數學家們花了許多時間和精力都沒有想到繼續拆分這個公式的方法,知道迪費、赫爾曼兩個大佬的出現才解決了這個難題,同時迪費赫爾曼密鑰交換也開創了密碼學的新方向


3、迪費赫爾曼密鑰交換

這裏拿了一張Hank老師的思惟導圖來進行說明:

  1. 服務器生成一個隨機數15,而後根據固定的算法3^{15}mod17獲得加密後的信息6發送給客戶端
  2. 客戶端同時生成一個隨機數13,根據一樣的算法3^{13}mod17獲得信息12發給服務器
  3. 服務器和客戶端根據獲得的信息照着原來的算法再次運算,就能獲得對方發的真實信息,信息交換中也不會涉及到密鑰的交換

注意:

  1. 信息在傳輸過程當中,第三方只能截取到信息6信息12,並不能截取到真實信息
  2. 算法規律是彼此都知道的,就算算法泄露出去了,根據離散對數中的原根概念,已知3^n mod 17=12,想求出n也絕非易事

其實迪費赫爾曼當時的目的只是爲了在密鑰交換的時候更加安全,而以後RSA三兄弟站了出來


4、RSA的誕生

迪費赫爾曼已經成功將m^{ed} mod n ≡ n拆分紅m^{e} mod n= cc^{d} mod n = n,只是沒有提出這一理念

  1. RSA算法 加密算法:m^{e} mod n= c 解密算法:c^{d} mod n = n 其中m是明文,c是密文,n和e是公鑰,n和d是私鑰 **條件:**① m < n;② d是e對於φ(n)的模反元素
  2. RSA說明
    1. n會很是大,長度通常爲1024位
    2. 因爲須要求出φ(n),因此根據歐函數特色,最簡單的方式n由兩個質數相乘獲得: 質數p一、p2
    3. 最終由φ(n)獲得e 和 d,總共生成6個數字:p一、p二、n、φ(n)、e、d
    4. 除了公鑰用到的n和e,其他4個數字是不公開的
  3. RSA的安全性
    1. 想要破解RSA獲得d,因爲e * d = φ(n) * k + 1,就要先知道e和φ(n)
    2. 要獲得φ(n)必須知道質數p一、p2
    3. 因爲n = p1 * p2,只有將n因數分解才能算出
  4. RSA的特色
    1. 相對安全
    2. 加密效率低
    3. 加密數據小(通常用來加密Hash值作對稱加密)

5、RSA終端使用

  1. 生成私鑰 openssl genrsa -out private.pem 1024
  2. 私鑰中提取公鑰 openssl rsa -in private.pem -pubout -out public.pem
  3. 查看公鑰 cat public.pem
  4. 將私鑰轉成文本文件 openssl rsa -in private.pem -text -out private.txt
  5. 用公鑰加密 openssl rsautl -encrypt -in message.txt -inkey public.pem -pubin -out enc.txt
  6. 用私鑰解密 openssl rsautl -decrypt -in enc.txt -inkey private.pem -out dec.txt
  7. 用私鑰簽名 openssl rsautl -sign -in message.txt -inkey private.pem -out enc.bin
  8. 用公鑰驗證 openssl rsautl -verify -in enc.bin -inkey public.pem -pubin -out dec.txt
  9. 查看二進制文件 xxd enc.bin

6、證書生成

  1. 生成請求證書文件,須要填寫國家、省市、組織名 鑰匙串也能夠從證書頒發機構請求證書 openssl req -new -key private.pem -out rsacert.csr
  2. 證書籤名 openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
  3. 生成公鑰 openssl x509 -outform der -in rsacert.crt -out rsacert.der
  4. 生成私鑰 openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt

┭┮﹏┭┮終於不用在生成p12文件時百度代碼了


7、Base64編碼

base64能夠將任意的二進制數據進行編碼,編碼成爲由65個字符組成的文本文件,是二進制數據的一種表現 base64編碼是由(A-Z,a-z,0-9,+ / =)組成的,最少爲24個字符位,從左至右6個爲一組,不足6個則補零,用等號來填補最後的空白 如A的二進制是01000001,補到24位是010000 010000 000000 000000,轉換成base64碼就是QQ==

  1. 終端編碼 base64 xxx.jpeg -o xxx.text
  2. 終端解碼 base64 xxx.text -o xxx.jpeg -D
  3. 代碼編碼
// 對一個字符編碼
- (NSString *)base64Endcode:(NSString *)str {
	NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
	return [data base64EncodedStringWithOptions:0];
}
複製代碼
  1. 代碼解碼
// 對一個編碼解密
- (NSString *)base64Decode:(NSString *)str {
	NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:0];
	return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
複製代碼
相關文章
相關標籤/搜索