introduction
Confidentiality:不被別人竊聽
Integrity: 能完整收到資訊
Authenticity:不接受偽造資訊
Symmetric Encryption
plaintext + KEY====>Encryption Function====>Ciphertext
plaintext<====Encryption Function<====Ciphertext + KEY
OTP: One-Time Pad
每次隨機生成一個key,用這個KEY對明文做XOR操作
Question: 如何獲得這個隨機Key?難道在第一次通訊時初始化seed,然後永遠維護?
KEY的長度同明文一致
Q: Assuming max entropy
兩種密碼學性質:
- Confusion: 描述了對key的微小擾動能夠極大擾動密文,可以抵擋frequency analysis attack等
- Each bit of the ciphertext depends on several parts of the key, obscuring the connections between the two
- Diffusion: 描述了對明文的微小擾動能夠極大擾動密文
- A change in a single bit of plaintext produces a change in about half the bits of ciphertext
Claude Shannon---Communication theory of secrecy systems
而儘管OTP能夠模糊明文的任何統計學特徵,但是OTP長度永遠大於等於明文長度,且金鑰只用一次,因此the relationship between the message M and the ciphertext E is trivial. the relationship between the key K and the ciphertext is also trivial. 並不適用。confusion 和diffusion只適用於non-ideal ciphers using keys of bounded length
https://crypto.stackexchange.com/questions/25860/does-the-one-time-pad-rely-on-confusion-or-diffusion
OTP的perfect secrecy來自於:
1. 使用random one-time key masks any redundancy in the plaintext.
2. the key never reused
!!Shannon never claims that confusion and diffusion would be the only ways to protect a cipher from statistical analysis
AES: Advanced Encryption Standard
Key Size可以是128,192或者256bits
Block Size只能是128 bits
High-level description of the algorithm
- KeyExpansion – round keys are derived from the cipher key using the AES key schedule. AES requires a separate 128-bit round key block for each round plus one more.
- Initial round key addition:
- AddRoundKey – each byte of the state is combined with a byte of the round key using bitwise xor.
- 9, 11 or 13 rounds:
- SubBytes – a non-linear substitution step where each byte is replaced with another according to a lookup table.
- ShiftRows – a transposition step where the last three rows of the state are shifted cyclically a certain number of steps.
- MixColumns – a linear mixing operation which operates on the columns of the state, combining the four bytes in each column.
- AddRoundKey
- Final round (making 10, 12 or 14 rounds in total):
- SubBytes
- ShiftRows
- AddRoundKey
Steps:
- SubBytes: 演算法定義了S-box這樣一張表,在表中找對映。解密時用Inverse S-box.作用是增加Diffusion
- ShiftRows: 第一行不變,第二行迴圈左移1位元組,第三行2位元組,第四行3位元組。以S3,i為例,分別向左移動0,1,2,3位元組,解密時左移
- MixColumns:第一列不變,第二列迴圈上移1位元組,第三行2位元組,第四行3位元組。以Si,3為例,分別向上移動0,1,2,3,位元組。解密時相當於下移
- AddRoundKey: 與這一輪Expansion出的Key異或
- KeyExpansion: 定義函式g為將收到的DWORD迴圈左移1位元組,然後做SubBytes。則對於每一次KeyExpansion(開始輪直接用原始Key),可以看作4個DWORDS,對於第一個DWORD,即i%4==0(這裡從0計數),
W[i] = w[i-4]XOR g(w[i-1])
,其他w[i] = w[i-4] XOR w[i-1]
- 注意KeyExpansion的次數不會超過16次(包括原始KEY)
不足16bytes的padding
如果直接置0,則接收方難以明白到底有多少個padding 0
PKC#7
將padding的長度作為padding,比如13bytes的資訊就以3作為padding, e.g."hello_world!\00\03\03\03"
分塊加密的流程
1. ECB: Electronic Codebooks:每個chunks分開獨立加密
a. 缺點:輸出會顯示出pattern。課件用了一張企鵝的圖作為例子,由於黑白變化單調,加密後仍然看得出企鵝
2. CBC: Cipher Block Chaining: 將上一個block的密文與當前明文異或作為加密輸入
a. 缺點:難以平行計算
3. CTR: Counter mode Encryption: 取一個隨機數作為counter,然後每個塊counter+1,將counter加密,加密後的密文再與明文異或,作為加密輸入
a. 有一點類似OTP
Key Exchange
基本模式:
1. Alice和Bob約定資訊A,
2. Alice, Bob分別生成資訊B,C,定義D=g(A,B), E=g(A,C),D和E都只能反應B和C一小部分資訊
3. Alice和Bob交換D,E
4. 獲得金鑰S=f(A,B,E)=f(A,C,D)
Diffie-Hellman KeyExchange
1. Alice and Bob agree to use a modulus p and base g. where p is prime and g is a primitive root module p(原根,g是整數%m乘法群的一個生成元,此時生成元個數就是其可逆元個數。作為基底能使餘數個數等於p)
2. Alice chooses a secret integer a, then sends Bob A =pow(g, a) % p
3. Bob chooses a secret integer b, then sends Alice B=pow(g, b) % p
4. s=pow(B, a)%p = pow(A,b)%p
Asymmetric Encryption
-
Fermat's Little Theorem:
pow(a, p)==a (mod p)
-
Euler's Theorem:
pow(a, (p-1)(q-1)) == 1(mod pq)
where p, q are prime- 注意在驗證時,
math.pow(2,73) % 91 = 2
, 但是math.pow(10,73) %91==26
,而10 ** 73 %91==10
計算正確
- 注意在驗證時,
-
RSA(Rivest-Shamir-Adleman)
pow(pow(m, e),d) == m(mod n)
, where n=pq, p,q are prime,ed == 1 mod (p-1)(q-1)
<e, n>
is public key,<d, n>
is private key- m is plaintext,
pow(m,e)
is ciphertext
-
RSA Key Generation
- Choose two large prime numbers p and q
- let n = pq
- let phi(n) = (p-1)(q-1)
- find e s.t.
gcd(e, phi(n)) == 1
a. the most common value for e is 0x10001 - compute
d == e ** -1 mod phi(n)
using extended Euclidean algo
-
RSA Encryption:
c=math.pow(m,e) % n
- c is ciphertext
- m is plaintext
- e is public key exponent
- n is key modulus
-
RSA Decryption:
m = math.pow(m, d) % n
- 公鑰加密,私鑰解密
-
RSA Signing:
s = math.pow(m, d) % n
- 注意這裡signature用的是私鑰簽名
Hashing
Avalanche Effect: 區域性敏感
One-Way function:難以推斷原文
Hashing Resistance Properties
- Pre-image resistance: Given a hash value h, it should be difficult to find any input message m such that h = hash(m)
- Second pre-image resistance: Given an input message m1, it should be difficult to find a different input message m2 so hash(m1) = hash(m2)
- Collision resistance: It should be difficult to find two different input messages m1 and m2 s.t. hash(m1) = hash(m2)
e.g.:SHA256 + Password hashing:得到hash值之後可以用字典攻擊
Hash加鹽: 注意salt也是隨機數而且需要存下來
Trust
Certificate Verification
如果M能夠傳送和修改資訊,M可以在Diffie-Hellman交換金鑰時給B傳送自己的公鑰,冒充A的公鑰,然後將A的資訊用A的公鑰解密之後,修改再用自己的公鑰加密
為了避免這一點,可以透過受信任的組織釋出證書,certificate中會包含公鑰和發行者等資訊,便於驗證公鑰。一層層受信任的組織組成了chain of trust,network of trust
先將證書使用hash值轉化為某個固定長的hash,再用受信任的機構的私鑰加密,然後傳送給通訊方
當驗證時,先把證書用hash值轉化為某個固定長度的hash,再由該受信任的機構的公鑰解密
Practices
level2: (bitstring.BitArray(base64.b64decode(x)) ^ bitstring.BitArray(base64.b64decode(y))).bytes
level3:
''.join([chr(x0 ^ y0 ^ 255) for x0, y0 in zip(base64.b64decode(x), base64.b64decode(y))])
level5:
注意當資訊長度不需要padding時, PKC#7
仍然會加長度為16的"\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10"
思路:
1. 先不斷加字首,找到長度突然增長的字首長度,就可以知道secret的長度
a. 第一次多了1,第二次忘了資訊一定是16bytes長度的倍數,把長度16的"\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10"直接減掉了
2. 先用字首長度把目前沒有解出來的最後一位元組推到某個DWORD的開頭(即新位置%16=0),獲得這一DWORD對應的ciphertext block,然後構造這一位元組對應的padded block(加上後面的位元組和理論的padding,湊夠一個DWORD,然後列舉這個位元組
level6:
一開始怎樣也不理解螢幕上的secret是做什麼用的,因為和s的長度不同
後來發現其實是用來異或的,只要異或最後幾位就可
level9:
注意hashlib.sha256
and pycrypto Crypto.Hash.SHA256.SHA256Hash
結果不同
level14:
注意只能用hex輸入大數!!!因為不是直接讀取int!!!
步驟:
1. Diffie-Hellman KeyExchange:
a. 先同意p,q
b. 對方發來A
c. 我方選擇b, 計算B,以base64傳送B
d. 計算s, AES key的值是SHA256(s)而不是s
2. 之後的全部訊息都要經過AES加密+base64加密
3. 獲取root certificate
4. 生成key,傳送user certificate,注意這裡name是由題目生成的而不是自己隨便生成
user_certificate = { "name":name, "signer": root_certificate["name"], "key": { "e": k.e, "n": k.n } }
5. 在這個challenge中,假裝自己是root,簽發自己的certificate
a. 先將user certificate用json轉化為string
b. 用SHA256將string轉化為定長bytes
c. 用root的私鑰加密
d. 用AES+base64加密,然後得到user certificate signature傳送
6. 將username化為左端對齊的256bytes長度的bytes,再加上256bytes的A和256Bytes的B,作為user signature data
a. SHA256
b. user 私鑰加密
c. 用AES+base64加密,然後得到user certificate signature傳送
7. 答案直接用base64+AES解密即可,不用再私鑰解密之類的