<!-- 注意上面三行 --> # 現代密碼學 序章 ### by AlanHacker --- ![image](https://hackmd.io/_uploads/r1lrSbGET.png) ### [前測](https://forms.gle/x9yDKSaJpv9fgAYL6) --- ![image](https://hackmd.io/_uploads/rkHeUWMEp.png =50%x) ## [Slido #5400 108](https://app.sli.do/event/nEvRRwkowafmzDYM2BKoY9) --- ## [練習題平台](https://ctf.hackersir.org/challenges) --- ## Before Start ---- ### 環境建置(1) * 創建資料夾 * 開啟 VScode * 開啟資料夾->(選到創建的資料夾) * (Ctrl + ~) 開啟命令列 ---- ### 環境建置(2) ```= pip install pwntools pip install pycryptodome ``` ---- ### 環境建置(3) * 沒報錯代表安裝成功 ``` > python >>>import Crypto >>>from pwn import * ``` --- ## Outline * 基本知識 * 雜湊函數 * 對稱式加密 * Block Cipher * Stream Cipher --- # 基本知識 ---- ### ASCII 編碼轉換 ---- * 大小 1 byte、使用 7 bits 編碼 * 用於表示英文字母與常見字符 ![p1](https://hackmd.io/_uploads/BkJNTpgET.jpg =75%x) ---- ### ASCII in Python ```python= chr() # 將數字轉成字元 ord() # 將字元轉成數字 ``` ---- ### 小練習 ``` # 請嘗試解碼 secret secret = [99, 114, 121, 112, 116, 111, 123, 105, 95, 67, 52, 78, 95, 99, 111, 78, 118, 51, 114, 116, 95, 64, 115, 99, 105, 105, 95, 33, 78, 95, 112, 121, 84, 72, 79, 78, 125] ``` ---- <font size=6>加密後可能會有非 ascii 可顯示字元出現 如:0 ~ 31、128 ~ 255 就是如此</font> ![p1](https://hackmd.io/_uploads/ryl8dyb4a.jpg =75%x) ---- 所以需要將密文編碼為較友善、較易傳輸的形式 Crypto CTF 中較常見的有: * Hex String * base64 ---- ### Hex String * 16 進制字串 * 字串 => (10) 數字 => (16) 數字 => 字串 * e.g. `"ABC"` => `65 66 67` => `41 42 43` => `"414243"` * 反過來做就是解碼 ---- ### 進位轉換 ```python= [1-7|3|4-5] number = 123 h = hex(number) # '0x7b' # 使用 int() 時,有如 0b、0x、0 這種前綴沒關係 int(h, 16) # 123 ``` ---- ### Hex String 轉換(1) ```python= [1-14|1-8|10-14] my_string = "Attack on Titan" hex_string = "" for c in my_string: hex_string += hex(ord(c))[2:] print(hex_string) # 41747461636b206f6e20546974616e original_string = "" for i in range(0, len(hex_string), 2): original_string += chr(int(hex_string[i : i + 2], 16)) print(original_string) # Attack on Titan ``` ---- ### Hex String 轉換 (2) ```python= [1-14|1-6|7-10|12-14] """ Python 中的字串型別有兩種:str(Unicode 字串)、bytes(二進制字串) 它們之間轉換必須透過 encode()、decode() str.encode() -> bytes bytes.decode() -> str """ my_string = "Attack on Titan" hex_string = my_string.encode().hex() print(hex_string) # 41747461636b206f6e20546974616e # fromhex 接收 str original_string = bytes.fromhex(hex_string) print(original_string.decode()) # Attack on Titan ``` ---- ### 小練習 ```python= # 小提醒: str、bytes 轉換要做什麼? # 請嘗試解碼 secret secret = "63727970746f7b6845783f68656b3f4b65583f4b454b3f5730575f755f525f615f4865584572217d" ``` ---- ### Base64 * 以 64 個字元編碼 * 因 $2^6=64$ ,所以 6 bits => 一個字元 * ~~16 進位是一種 base16~~ * 常用於網路傳輸、如圖片等二進位資料 ---- ```python= [1-8|4-5|6-8] from base64 import b64encode, b64decode my_data = "[粛聖!!ロリ神レクイエム☆](https://www.youtube.com/watch?v=Ci_zad39Uhw)" # 因為是處理二進制資料的編碼 # 所以必須用 bytes 操作 b64_string = b64encode(my_data.encode()) print(b64_string) # b'W+eym+iBliEh44Ot44Oq56We44Os44Kv44Kk44Ko44Og4piGXShodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PUNpX3phZDM5VWh3KQ==' print(b64decode(b64_string).decode()) # [粛聖!!ロリ神レクイエム☆](https://www.youtube.com/watch?v=Ci_zad39Uhw) ``` ---- ### 小練習 ```python= # 小提醒: str、bytes 轉換要做什麼? # 請嘗試解碼 secret secret = "Y3J5cHRveyFTX0I0c0U2NF9BX251TWIzcl9zWXNURW19" ``` ---- ### Python 檔案讀寫(1) ```py= # filename 為你的檔案名稱、mode 為對檔案做的操作 with open(filename, mode) as f: f.read() f.write() ``` ---- ### Python 檔案讀寫(2) ```python= [1-13|3-6|8-13] # 寫檔範例 # 假設把字串 "abc" 寫入一個叫 myfile2.txt 的檔案 with open("myfile2.txt", "w") as f: f.write("abc") # myfile2.txt 內容:"abc" # 假設把二進位資料 b'\x01\x02\x03\x04\x05' # 寫入一個叫 myfile2.txt 的檔案 with open("myfile2", "wb") as f: f.write(b'\x01\x02\x03\x04\x05') # myfile2.txt 內容:b'\x01\x02\x03\x04\x05' # 因為是二進位資料,所以會是亂碼 ``` ---- ### Python 檔案讀寫(3) ```python= [1-10|3-5|7-10] # 讀檔範例 # 假設有一個 myfile.txt 的文字檔案,裡面的內容是 "abc" with open("myfile.txt", "r") as f: print(f.read()) # 'abc' # 假設有一個 myfile 的二進位檔案 # 裡面的內容用十六進位看是 01 02 03 04 05 with open("myfile", "rb") as f: print(f.read()) # b'\x01\x02\x03\x04\x05' ``` ---- ## [Lab: Image Decode](https://ctf.hackersir.org/challenges#Image%20Decode-63) ---- * 我們加密的對象已經不一樣了 * 純文字資料 => 二進制資料 * 像[上次社課](https://hackmd.io/@ClubSlide/H1bkHKPZa#/14/2)用加法加密對人類來說好算 * 但對電腦不太好算! * 因此要找一個讓電腦好算的方式! ---- ### 異或 Exclusive or * a.k.a XOR, [互斥或](https://zh.wikipedia.org/zh-tw/%E9%80%BB%E8%BE%91%E5%BC%82%E6%88%96) * 電腦運算速度很快 * 二進位運算 * 有很多類似加法的性質 * 可以當作「加法」的替代 ---- $\oplus$ 代表 XOR * $0 \oplus 0=0$ * $0 \oplus 1=1$ * $1 \oplus 0=1$ * $1 \oplus 1=0$ ---- ### bitwise XOR * 對於字串或二進位資料 * 在二進位下逐位元分開進行 XOR ---- * `"a"` XOR `"b"` => `97` XOR `98` => `01100001` XOR `01100010` | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | |---|---|---|---|---|---|---|---| | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | => `00000011` ---- ### XOR in Python(1) ```python= # 大多數程式語言都用 ^ 代表 XOR,Python 也不例外 print(97 ^ 98) # 3 ``` ---- ### XOR in Python(2) ```python= # 對字串 XOR 有兩種做法 plain = "wink" key = 11 # 方法一 result = "" for c in plain: result += chr(ord(c) ^ 11) print(result) # {ebg ``` ---- ### XOR in Python(3) ```python= # 對字串 XOR 有兩種做法 plain = "wink" key = 11 # 方法二 # 對 bytes 進行 XOR # 這個方法較通用 from pwn import xor print(xor(plain.encode(), 11)) # b'{ebg' ``` ---- ### XOR 的美好性質 <font size = 5>前三個跟加法很像</font> * 交換律 $a\oplus b=b\oplus a$ * 結合律 $(a\oplus b)\oplus c=a\oplus (b\oplus c)$ * 單位元素 $a\oplus 0=a$ * 自反性 $a\oplus a=0$ ---- 所以可以知道三個重點: 1. 運算順序什麼的不重要 2. 括號可以隨便括 3. 同一個數字算兩次會被"取消"掉 * $a\oplus b\oplus b=a\oplus0=a$ 4. 可以移項 * $a\oplus b=c\Rightarrow a\oplus b\oplus b=c\oplus b$ $\Rightarrow a=c\oplus b$ ---- ## [Lab: XOR property](https://ctf.hackersir.org/challenges#XOR%20property-64) ---- ## [Lab: XOR Decryption](https://ctf.hackersir.org/challenges#XOR%20decryption-65) --- # 雜湊函數 ---- ### 雜湊函數 * 又稱哈希函數 * 如同[上次社課](https://hackmd.io/@ClubSlide/H1bkHKPZa#/8/8)所提到的幾個性質 * 不可逆函數 * 一對一函數 * 單向函數 * 資訊摘要 * 被拿來簽章、驗證 * 不定長度輸入、固定長度輸出 ---- * 多對一出現代表內容有被偽造的風險 * 這種狀況叫做「碰撞」 ![Hash_table_4_1_1_0_0_1_0_LL](https://hackmd.io/_uploads/S1WbA-Rm6.jpg =55%x) ---- ### MD5 * 輸出長度:128 bits * 已被找出碰撞 ---- ### SHA 家族 * Secure Hash Algorithm,縮寫為 SHA * 美國國家安全局(NSA)設計 * 美國國家標準與技術研究院(NIST)發佈 ---- ### SHA1 * 輸出長度:160 bits * 已被找出碰撞 ---- ### SHA2 * 輸出長度:224、256、384、512 bits * 尚未被找出碰撞 ---- ### SHA3 * 輸出長度:224、256、384、512 bits * 尚未被找出碰撞 * 因為 SHA1 被破解,因而設計上與 SHA1、SHA2 截然不同 ---- ![image](https://hackmd.io/_uploads/SkqVUzR7p.png =80%x) <small>[source: wikipedia](https://zh.wikipedia.org/zh-tw/SHA%E5%AE%B6%E6%97%8F#SHA%E5%87%BD%E6%95%B0%E5%AF%B9%E6%AF%94)</small> ---- ### Hash in Python ```py= from hashlib import md5 from hashlib import sha1 from hashlib import sha224, sha256, sha384 from hashlib import sha3_224, sha3_256, sha3_384 print(md5(b"jojo").digest()) # b'u\x10\xd4\x98\xf2?X\x15\xd37n\xa7\xba\xd6N)' print(md5(b"jojo").hexdigest()) # "7510d498f23f5815d3376ea7bad64e29" ``` ---- ## [Lab: Hash Cipher](https://ctf.hackersir.org/challenges#Hash%20Cipher-66) --- # 對稱式加密 ---- ### 對稱式加密 * 加解密使用同一把 key * ~~所以理論上古典加密都是對稱式加密~~ ![image](https://hackmd.io/_uploads/BJi6qzA76.png) --- ## Block Cipher ---- ### Block Cipher * 區塊加密法 * 將明文分成多個等長的區塊(block) * 對每區塊分別加密解密 ---- ![image](https://hackmd.io/_uploads/SJXQv70QT.png) ---- ### AES * 進階加密標準(Advanced Encryption Standard) * Block Cipher * 16 bytes 一個區塊 * 不足 16 bytes 遵照 [PKCS#7](https://stackoverflow.com/questions/34865313/bouncy-castle-pkcs7-padding) Padding 填充 * 已知攻擊方法只有社交工程和旁道攻擊 ---- ### PKCS#7 Padding * 區塊長度 $\neq$ 16 的倍數 -> 補到變 16 倍數 * 區塊長度 $=$ 16 的倍數 -> 額外再補 16 bytes ```py= from Crypto.Util.Padding import pad pad(b"0123456789", 16) # b'0123456789\x06\x06\x06\x06\x06\x06' pad(b"0123" * 4, 16) # b'0123012301230123\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10' ``` ---- ### Mode of operation * 區塊加密法工作模式 * 定義 key 如何為多個區塊進行加密 * 常見的工作模式有 * ECB * CBC * CTR * OFB * CFB ---- ### ECB Mode * 電子密碼本(Electronic codebook) ![image](https://hackmd.io/_uploads/HkRDiXCXT.png =150%x) ---- ### 缺點 * 因為各區塊單獨加密 * 所以相同區塊加密結果相同 ---- ![image](https://hackmd.io/_uploads/B10TsQA7a.png) ---- ### AES-ECB in Python ```python= from Crypto.Cipher import AES from Crypto.Util.Padding import pad key = pad(b'key', 16) aes = AES.new(key = key, mode = AES.MODE_ECB) print(aes.encrypt(pad(b"test", 16)).hex()) # 8e0d95a9f720c6eaa1cab10e44ce50e8 ``` ---- ### 常見弱點 * Cut-Paste Attack ---- ### Cut-Paste Attack * 研究表明:漢字的序順並不定一能影響閱讀 * ECB 也是一樣 * 因此可以用拼接已知區塊的方式竄改內容 ---- ### 範例 ```py= [1-15|1-6|8-15] plain = b"username=Sandra&deposit=1000000;username=Daniel&deposit=0000000;" block_1 = "username=Sandra&"; block_2 = "deposit=1000000;"; block_3 = "username=Daniel&"; block_4 = "deposit=0000000;"; # after AES-ECB encryption cipher_1 = "aaaaaaaaaaaaaaaa"; cipher_2 = "bbbbbbbbbbbbbbbb"; cipher_3 = "cccccccccccccccc"; cipher_4 = "dddddddddddddddd"; cipher = "aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccdddddddddddddddd"; ``` ---- ### Daniel 很窮,他要怎麼財富自由? ---- ### 和 Sandra 交換存款! ---- ```py= [1-15|1-6|8-15] hacked_cipher = "aaaaaaaaaaaaaaaaddddddddddddddddccccccccccccccccbbbbbbbbbbbbbbbb"; hacked_cipher_1 = "aaaaaaaaaaaaaaaa"; hacked_cipher_2 = "dddddddddddddddd"; hacked_cipher_3 = "cccccccccccccccc"; hacked_cipher_4 = "bbbbbbbbbbbbbbbb"; # After AES-ECB decryption hacked_block_1 = "username=Sandra&"; hacked_block_2 = "deposit=0000000;"; hacked_block_3 = "username=Daniel&"; hacked_block_4 = "deposit=1000000;"; hacked_plain = "username=Sandra&deposit=0000000;username=Daniel&deposit=1000000;" ``` ---- ### demo in Python ```python= from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from os import urandom key = urandom(16) # 16 bytes aes = AES.new(key = key, mode = AES.MODE_ECB) plain = b"username=Sandra&deposit=1000000;username=Daniel&deposit=0000000;" cipher = aes.encrypt(pad(plain, 16)) block_1, block_2, block_3, block_4, padding = cipher[:16], cipher[16:32], cipher[32:48], cipher[48:64], cipher[64:80] hacked_cipher = block_1 + block_4 + block_3 + block_2 + padding hacked_plain = unpad(aes.decrypt(hacked_cipher), 16) print(hacked_plain) ``` ---- ## [Lab: ECB](https://ctf.hackersir.org/challenges#ECB-68) --- ## Stream Cipher ---- ### Stream Cipher * 串流加密法 * 使用**某種方式**無限產生 key stream * 明文與對應位置的 key stream 加密 ---- ### OTP * 一次性密碼本(One Time Pad) * 理論中絕對安全,牢不可破 * 但條件太嚴苛,難以實現 ---- ### 加密方法 1. key 與明文等長 2. key 為完全隨機的序列 3. key 用完即丟,且只有通訊雙方能知道 4. 加密的方式可以用傳統的加法;也可用 XOR ---- ### 範例 <font size=5>使用 XOR</font> * $\text{明文} = [1, 2, 3]$ * $\text{key} \,\, = [5, 2, 1]$ * $\text{密文} = [4, 0, 2]$ ---- ### 困難 * key 與明文等長,難以傳遞 ---- ### 常見弱點 * key 重複使用(變 Many Time Pad) * key 洩漏 ---- ## [Lab: Many Time Pad](https://ctf.hackersir.org/challenges#Many%20Time%20Pad-67) --- ![image](https://hackmd.io/_uploads/r10PSZz4T.png) ### [後測](https://forms.gle/ZdUYxvTx2oWDuuaU7)
{"title":"Cryptography 02","contributors":"[{\"id\":\"b700cab6-685f-4ba8-87b8-088044d9367d\",\"add\":16569,\"del\":5542}]","description":"image"}
    403 views
   Owned this note