2023-08-23 17:09:04 +00:00
|
|
|
# Real World Crypto 101
|
|
|
|
|
|
|
|
My notes when reading
|
|
|
|
[Real-World Cryptography](https://www.manning.com/books/real-world-cryptography)
|
|
|
|
|
2024-07-23 16:53:22 +00:00
|
|
|
## **Hash** function
|
|
|
|
|
|
|
|
... convert from input to digest
|
2023-08-23 17:09:04 +00:00
|
|
|
|
|
|
|
- Pre-image resistance: Given digest, can not find input
|
|
|
|
- Second pre-image resistance: Given input, digest, can not find another input
|
|
|
|
produce same digest. Small change to input make digest big change.
|
|
|
|
- Collision resistance: Can not find 2 input produce same digest.
|
|
|
|
|
2024-07-23 16:53:22 +00:00
|
|
|
## **MAC** aka Message Authentication Code
|
|
|
|
|
|
|
|
... produce from key, message to authentication tag.
|
2023-08-24 04:44:53 +00:00
|
|
|
|
|
|
|
- A send B message with MAC (generate from message and A key).
|
|
|
|
- B double check message with MAC (generate from receive message and B key).
|
|
|
|
- A and B use same key.
|
2023-09-10 16:39:41 +00:00
|
|
|
|
2023-09-10 18:03:48 +00:00
|
|
|
```mermaid
|
|
|
|
sequenceDiagram
|
|
|
|
participant alice
|
|
|
|
participant bob
|
|
|
|
|
|
|
|
alice ->> bob: send alice, mac(secret_key_alice, alice)
|
|
|
|
bob ->> bob: compare mac(secret_key_alice, alice) with mac(secret_key_bob, alice)
|
|
|
|
```
|
|
|
|
|
|
|
|
- Prevent forgery: without secret_key, can not generate MAC even if knowing **a
|
|
|
|
lot of** alice and mac(secret_key, alice),
|
|
|
|
- Prevent collisions: keep MAC long enough (256-bit),
|
|
|
|
- Replay attacks: send transaction 2 times with perfectly MAC and u know why ->
|
|
|
|
instead of mac(secret_key, alice), use **counter** as mac(secret_key, counter,
|
|
|
|
alice).
|
2024-07-22 11:32:39 +00:00
|
|
|
- Verify must be done in **constant time**: if not, probably return error the
|
2023-09-10 18:03:48 +00:00
|
|
|
moment the bytes differ -> attacker recreate byte by byte by measuring how
|
|
|
|
long -> timing attacks
|
|
|
|
|
2024-07-22 11:32:39 +00:00
|
|
|
Constant time comparison:
|
2023-09-10 18:03:48 +00:00
|
|
|
|
|
|
|
```go
|
|
|
|
for i := 0; i < len(x); i++ {
|
|
|
|
// Use XOR instead of compare x[i] == y[i]
|
|
|
|
// If x[i] == y[i] -> XOR is 1
|
|
|
|
// Otherwise XOR is 0
|
|
|
|
v |= x[i] ^ y[i]
|
|
|
|
}
|
|
|
|
|
|
|
|
// v == 1 means all XOR is 1 means x == y
|
|
|
|
```
|
|
|
|
|
|
|
|
Use for:
|
|
|
|
|
|
|
|
- Integrity: because MAC ensure no one can tamper with message without noticing
|
|
|
|
|
2023-09-10 16:41:21 +00:00
|
|
|
```mermaid
|
2023-09-10 16:39:41 +00:00
|
|
|
sequenceDiagram
|
|
|
|
participant alice
|
|
|
|
participant bob
|
|
|
|
|
|
|
|
alice ->> bob: send username, password
|
2023-09-10 18:03:48 +00:00
|
|
|
bob -->> alice: return alice|mac(secret_key, alice)
|
|
|
|
alice ->> bob: send alice|mac(secret_key, alice)
|
2023-09-10 16:39:41 +00:00
|
|
|
bob -->> alice: return OK
|
2023-09-10 18:03:48 +00:00
|
|
|
alice ->> bob: send bob|mac(secret_key, alice)
|
2023-09-10 16:39:41 +00:00
|
|
|
bob -->> alice: return ERROR
|
|
|
|
```
|
2023-09-10 18:03:48 +00:00
|
|
|
|
|
|
|
**HMAC** is MAC using hash
|
2023-11-07 17:56:37 +00:00
|
|
|
|
2023-12-08 17:47:17 +00:00
|
|
|
## AES (Advanced Encryption Standard)
|
2023-11-07 17:56:37 +00:00
|
|
|
|
2023-12-08 17:47:17 +00:00
|
|
|
Currently (2023) the world using AES-128 which take a key 128 bits == 16 bytes
|
2023-11-07 17:56:37 +00:00
|
|
|
|
|
|
|
- Take a variable-length key
|
|
|
|
- Take plaintext of 128 bits
|
|
|
|
- Give ciphertext of 128 bits
|
|
|
|
|
|
|
|
AES is kind of cipher, handle fixed-size plaintext so we called **block
|
2023-12-08 17:47:17 +00:00
|
|
|
cipher**. AES is deterministic so we can encrypt and decrypt.
|
|
|
|
|
|
|
|
## AES-CBC (Cipher Block Chaining)
|
|
|
|
|
2024-07-23 16:53:22 +00:00
|
|
|
What if text you want to encrypt is longer than 128 bytes ? We add **padding**
|
|
|
|
for text to become multi block which has 128 bytes, then encrypt each block.
|
2023-12-08 17:47:17 +00:00
|
|
|
|
|
|
|
Adding padding bytes is easy, remove it after decrypt is hard. How do you know
|
|
|
|
which is padding bytes you add if you use random bytes ?
|
|
|
|
|
|
|
|
Just use **PKCS#7 padding**. Example AES-128 use block of 16 bytes but only have
|
|
|
|
9 bytes, should add 7 bytes padding. Just fill all padding bytes with padding
|
|
|
|
length aka value `07`.
|
|
|
|
|
|
|
|
```txt
|
|
|
|
XX XX XX XX XX XX XX XX XX 07 07 07 07 07 07 07
|
|
|
|
```
|
|
|
|
|
|
|
|
So to know how much padding bytes should we remove -> read last bytes (`07`) to
|
|
|
|
know the length to remove trailing padding bytes.
|
|
|
|
|
|
|
|
The problem with naive way to split text, add padding bytes then encrypt each
|
|
|
|
block using AES-128 is repeated text. Because it leaks information if text is
|
2024-07-23 16:53:22 +00:00
|
|
|
made up from many repeated text (See
|
|
|
|
[The ECB penguin](https://words.filippo.io/the-ecb-penguin/)).
|
2023-12-08 17:47:17 +00:00
|
|
|
|
|
|
|
CBC = deterministic block cipher + IV (initialization vector)
|
|
|
|
|
|
|
|
AES-CBC encrypt:
|
|
|
|
|
2024-07-23 16:53:22 +00:00
|
|
|
- IV XOR first plaintext -> AES encrypt -> first ciphertext.
|
2023-12-08 17:47:17 +00:00
|
|
|
- Use first ciphertext as IV to second ciphertext and so on.
|
|
|
|
|
|
|
|
AES-CBC decrypt:
|
|
|
|
|
|
|
|
- AES decrypt first ciphertext -> XOR IV -> first plaintext.
|
|
|
|
- Use first ciphertext as IV to second block and so on.
|
|
|
|
|
|
|
|
Because IV, same plaintext can encrypt to different ciphertext.
|
|
|
|
|
|
|
|
**WARNING** If IV become predictable, AES-CBC become deterministic -> BEAST
|
|
|
|
attack (Browser Exploit Against SSL/TLS).
|
|
|
|
|
|
|
|
## AEAD (Authenticated Encryption with Associated Data)
|
|
|
|
|
|
|
|
Because AES-CBC requires IV which shows public -> attacker can change IV -> lack
|
|
|
|
of authenticity -> use AES-CBC-HMAC or AEAD.
|
|
|
|
|
|
|
|
AEAD provides a way to authenticate **associated data**.
|
|
|
|
|
2024-07-23 16:53:22 +00:00
|
|
|
## AES-GCM (Galois/Counter Mode)
|
|
|
|
|
|
|
|
... is one of AEAD implementation.
|
2023-12-08 17:47:17 +00:00
|
|
|
|
|
|
|
AES-GCM = AES-CTR (Counter) + GMAC message authentication code
|
|
|
|
|
|
|
|
AES-CTR encrypt:
|
|
|
|
|
|
|
|
- Create nonce 12 bytes (same purpose as IV).
|
|
|
|
- Concatenate nonce with counter 4 bytes: 1, 2, 3, ...
|
|
|
|
- Encrypt AES from concatenated none with counter to **keystream**.
|
|
|
|
- XOR keystream with plaintext -> ciphertext.
|
|
|
|
|
|
|
|
Limit is counter only up to 4 bytes so only handle plaintext of 2^32 - 1 blocks
|
|
|
|
of 16 bytes aka 69 GBs.
|
|
|
|
|
|
|
|
AES-CTR no need padding because if keystream is longer than plaintext, it is
|
|
|
|
truncated to plaintext length before XOR.
|
|
|
|
|
2024-07-23 16:53:22 +00:00
|
|
|
This is stream cipher, differ from block cipher
|
|
|
|
|
|
|
|
- No need padding.
|
|
|
|
- Ciphertext is same length as plaintext.
|
2023-12-08 17:47:17 +00:00
|
|
|
|
|
|
|
GMAC is MAC with GHASH. GHASH resembles CBC mode.
|
|
|
|
|
2024-07-23 16:53:22 +00:00
|
|
|
## ChaCha20-Poly1305
|
|
|
|
|
|
|
|
... is one of AEAD implementation.
|
2023-12-08 17:47:17 +00:00
|
|
|
|
|
|
|
ChaCha20-Poly1305 = ChaCha20 stream cipher + Poly1305 MAC
|
2024-07-23 16:53:22 +00:00
|
|
|
|
|
|
|
## Key exchange
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
sequenceDiagram
|
|
|
|
participant alice
|
|
|
|
participant bob
|
|
|
|
|
|
|
|
alice ->> alice: generate key pair: public_key, secret_key
|
|
|
|
bob ->> bob: generate key pair: public_key, secret_key
|
|
|
|
alice ->> bob: send public_key
|
|
|
|
bob ->> alice: send public_key
|
|
|
|
alice ->> alice: generate shared_secret(secret_key, bob_public_key)
|
|
|
|
bob ->> bob: generate shared_secret(secret_key, alice_public_key)
|
|
|
|
```
|
|
|
|
|
|
|
|
Prevent MITM (Man In The Middle) passive attack. If attacker can intercept
|
|
|
|
public_key then it's over.
|
|
|
|
|
|
|
|
## Diffie-Hellman
|
|
|
|
|
|
|
|
... is key exchange algorithm.
|
|
|
|
|
|
|
|
- Alice and Bob agree on prime number `p` and generator `g`.
|
|
|
|
- Alice generate secret `a` and public `A = g^a mod p`.
|
|
|
|
- Bob generate secret `b` and public `B = g^b mod p`.
|
|
|
|
- Alice and Bob exchange `A` and `B`
|
2024-07-29 18:36:21 +00:00
|
|
|
- Same secret `A^b mod p == B^a mod p == g^(ab) mod p`
|
|
|
|
|
|
|
|
Diffie-Hellman is based on group theory.
|
|
|
|
|
|
|
|
## Elliptic Curve Diffie-Hellman (ECDH)
|
|
|
|
|
|
|
|
Instead of prime number, use elliptic curve.
|
|
|
|
|
|
|
|
- Alice and Bob agree on elliptic curve `E` and generator `G`.
|
|
|
|
- Alice generate secret `a` and public `A = [a]G`.
|
|
|
|
- Bob generate secret `b` and public `B = [b]G`.
|
|
|
|
- Alice and Bob exchange `A` and `B`
|
|
|
|
- Same secret `[a]B == [b]A == [ab]G`
|