├── .gitignore
├── matasano
├── 15-pksc7_validation.go
├── 02-singlekey_xor_test.go
├── 03-break_singlekey_xor_test.go
├── 16-cbc_bitflipping_test.go
├── 04-find_xor_line.go
├── 04-find_xor_line_test.go
├── 05-repeatedkey_xor.go
├── 05-repeatedkey_xor_test.go
├── 02-singlekey_xor.go
├── 15-pksc7_validation_test.go
├── 08-detect_aes_ecb_test.go
├── 08-detect_aes_ecb.go
├── 17-cbc_padding_oracle_test.go
├── 09-pkcs7.go
├── 12-break_aes_ecb_test.go
├── 14.5-break_ecb_moderate_test.go
├── 16-cbc_bitflipping.go
├── 06-break_repeatedkey_xor_test.go
├── 14-break_aes_ecb_hard_test.go
├── 09-pkcs7_test.go
├── 11-ecb_cbc_oracle_test.go
├── 03-break_singlekey_xor.go
├── 06-break_repeatedkey_xor.go
├── 01-hextobase64_test.go
├── 18-aes_ctr.go
├── 13-ecb_cut_paste_test.go
├── 12-break_aes_ecb.go
├── 07-aes_ecb.go
├── 10-aes_cbc.go
├── 17-cbc_padding_oracle.go
├── 18-aes_ctr_test.go
├── 11-ecb_cbc_oracle.go
├── 14.5-break_ecb_moderate.go
├── 13-ecb_cut_paste.go
├── 06-data.txt
├── 07-data.txt
├── 10-data.txt
├── 14-break_aes_ecb_hard.go
├── 01-hextobase64.go
├── 07-aes_ecb_test.go
└── 10-aes_cbc_test.go
├── stanford
├── readme.md
├── 6.3-unifying-theme.md
├── 6-public-key-encryption.md
├── 0-discrete-probability.md
├── 6.2-public-key-encryption-diffie-hellman.md
├── 5-basic-key-exchange.md
├── 5.5-number-theory.md
├── 6.1-public-key-encryption-trapdoor.md
├── 4.5-odds-and-ends.md
├── 4-authenticated-encryption.md
└── 1-stream-ciphers.md
├── Readme.md
└── aes
├── aes_util.go
├── perf_test.go
├── aes_test.go
├── aes.go
├── readme.md
└── const.go
/.gitignore:
--------------------------------------------------------------------------------
1 | stanford/*.go
2 | *.mp4
3 |
--------------------------------------------------------------------------------
/matasano/15-pksc7_validation.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | // ValidatePKCS7 checks if the padding on a slice of bytes is PKCS7
4 | // If the padding isn't valid, the function panics
5 | // This solves http://cryptopals.com/sets/2/challenges/15
6 | func ValidatePKCS7(b []byte) {
7 | _, err := StripPKCS7(b)
8 | if err != nil {
9 | panic("Not valid padding")
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/stanford/readme.md:
--------------------------------------------------------------------------------
1 | Notes
2 | ===
3 |
4 | These are the notes for [Crypto I](https://www.coursera.org/course/crypto) course on Coursera, conducted by Prof. Dan Boneh of Stanford. When [Crypto II](https://www.coursera.org/course/crypto2) takes place, the notes will be uploaded here as well.
5 |
6 | The notes are collated into a single PDF which you can find in the [Releases](https://github.com/nindalf/crypto/releases) section.
7 |
--------------------------------------------------------------------------------
/matasano/02-singlekey_xor_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "testing"
4 |
5 | func TestXor(t *testing.T) {
6 | in1 := []byte("1c0111001f010100061a024b53535009181c")
7 | in2 := []byte("686974207468652062756c6c277320657965")
8 | expected := "746865206b696420646f6e277420706c6179"
9 | actual := string(Xor(in1, in2))
10 | if expected != actual {
11 | t.Fatalf("Input - %s\t%s\nExptected - %s\nActual - %s", string(in1), string(in2), expected, actual)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/matasano/03-break_singlekey_xor_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "testing"
4 |
5 | func TestBreakSingleXor(t *testing.T) {
6 | input := []byte("1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736")
7 | expected := "Cooking MC's like a pound of bacon"
8 | decrypted, rank, key := BreakSingleXor(StringFromHex(input))
9 | if expected != string(decrypted) {
10 | t.Logf("Expected - %s\nFound - %sRank - %f, Key - %s", expected, string(decrypted), rank, string(key))
11 | t.Fail()
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/matasano/16-cbc_bitflipping_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "testing"
4 |
5 | func TestFlipCBC(t *testing.T) {
6 | //input of length 6+16 so that the length of the plaintext is a multiple of 16
7 | input := "123456admin=true7890123"
8 | b, iv := encrypt16(input)
9 | if decrypt16(b, iv) == true {
10 | t.Fatalf("Found string %s in the plaintext", "admin=true")
11 | }
12 | b, iv = encrypt16(input)
13 | FlipCBC(b)
14 | if decrypt16(b, iv) == false {
15 | t.Fatalf("Did not find string %s in the plaintext", "admin=true")
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/matasano/04-find_xor_line.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | // FindXORLine finds line that has been XOR-ed with some byte
4 | // This solves http://cryptopals.com/sets/1/challenges/4/
5 | func FindXORLine(lines [][]byte) ([]byte, []byte, byte) {
6 | var result, line []byte
7 | var rkey byte
8 | var currank float64
9 | for _, l := range lines {
10 | decrypted, rank, key := BreakSingleXor(StringFromHex(l))
11 | if currank < rank {
12 | currank = rank
13 | result = decrypted
14 | line = l
15 | rkey = key
16 | }
17 | }
18 | return result, line, rkey
19 | }
20 |
--------------------------------------------------------------------------------
/matasano/04-find_xor_line_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "io/ioutil"
6 | "testing"
7 | )
8 |
9 | const datafile04 = "04-data.txt"
10 |
11 | func TestFindXORLine(t *testing.T) {
12 | b, err := ioutil.ReadFile(datafile04)
13 | if err != nil {
14 | t.Fatal(err)
15 | }
16 |
17 | lines := bytes.Split(b, []byte("\n"))
18 | decrypted, line, key := FindXORLine(lines)
19 | expected := "Now that the party is jumping\n"
20 | if expected != string(decrypted) {
21 | t.Fatalf("Expected - %s\nFound - %s from %s, Key - %s", expected, string(decrypted), string(line), string(key))
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/matasano/05-repeatedkey_xor.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | // EncryptRepeatedXor encrypts the plaintext using repeating-key XOR
4 | // This solves http://cryptopals.com/sets/1/challenges/5/
5 | func EncryptRepeatedXor(plaintext, key []byte) []byte {
6 | for i := range plaintext {
7 | keybyte := key[i%len(key)]
8 | plaintext[i] = plaintext[i] ^ keybyte
9 | }
10 | return HexFromString(plaintext)
11 | }
12 |
13 | func decryptRepeatedXor(ciphertext, key []byte) []byte {
14 | for i := range ciphertext {
15 | keybyte := key[i%len(key)]
16 | ciphertext[i] = ciphertext[i] ^ keybyte
17 | }
18 | return ciphertext
19 | }
20 |
--------------------------------------------------------------------------------
/matasano/05-repeatedkey_xor_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "testing"
4 |
5 | func TestEncryptRepeatedXor(t *testing.T) {
6 | plaintext := []byte("Burning 'em, if you ain't quick and nimble\nI go crazy when I hear a cymbal")
7 | key := []byte("ICE")
8 | expcipher := "0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f"
9 | actcipher := string(EncryptRepeatedXor(plaintext, key))
10 | if expcipher != actcipher {
11 | t.Fatalf("Plaintext - %s\nKey - %s\nExpected ciphertext - %s\nActual ciphertext - %s", string(plaintext), string(key), expcipher, actcipher)
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | Crypto code and notes
2 | ---
3 |
4 | I keep all the code and notes related to cryptography in this repo. They're classified under
5 |
6 | * stanford - Notes for the Coursera [course on cryptography](https://class.coursera.org/crypto-015).
7 | * matasano - Code for the [Matasano crypto challenges](http://cryptopals.com).
8 | * aes - Implementation of the Advanced Encryption Standard
9 |
10 | If you're interested in crypto, I'd recommend checking the first two out.
11 |
12 | The code for the challenges are WIP, I have finished 16 out of 56 problems in total. In case you'd like to learn more about them, here's a [good intro](https://blog.pinboard.in/2013/04/the_matasano_crypto_challenges/).
13 |
14 |
--------------------------------------------------------------------------------
/matasano/02-singlekey_xor.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | // Xor takes two equal-length buffers and produces their XOR combination.
4 | // This solves http://cryptopals.com/sets/1/challenges/2/
5 | func Xor(in1, in2 []byte) []byte {
6 | in1 = StringFromHex(in1)
7 | in2 = StringFromHex(in2)
8 | out := make([]byte, len(in1))
9 |
10 | for i := 0; i < len(in1); i++ {
11 | out[i] = in1[i] ^ in2[i]
12 | }
13 |
14 | return HexFromString(out)
15 | }
16 |
17 | // XorOne takes a buffer and XORs it with a single byte
18 | // This function is used in subsequent challenges
19 | func XorOne(in []byte, key byte) []byte {
20 | out := make([]byte, len(in))
21 |
22 | for i := 0; i < len(in); i++ {
23 | out[i] = in[i] ^ key
24 | }
25 | return out
26 | }
27 |
--------------------------------------------------------------------------------
/matasano/15-pksc7_validation_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "testing"
4 |
5 | func TestValidatePKCS7(t *testing.T) {
6 | input := []string{"ICE ICE BABY\x04\x04\x04\x04", "ICE ICE BABY\x05\x05\x05\x05", "ICE ICE BABY\x01\x02\x03\x04"}
7 | expected := []bool{false, true, true}
8 | for i := range input {
9 | safelyCheck(t, input[i], expected[i])
10 | }
11 | }
12 |
13 | func safelyCheck(t *testing.T, input string, expected bool) {
14 | defer func() {
15 | err := recover()
16 | if err != nil && expected == false {
17 | t.Fatalf("Input - %s\nExpected to panic - %v", input, expected)
18 | }
19 | if err == nil && expected == true {
20 | t.Fatalf("Input - %s\nExpected to panic - %v", input, expected)
21 | }
22 | }()
23 | ValidatePKCS7([]byte(input))
24 | }
25 |
--------------------------------------------------------------------------------
/aes/aes_util.go:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | // pack moves bytes from src (16 bytes) to dst ([]uint32 of len 4)
4 | // 4 uint32s correspond to 16 bytes in this manner:
5 | // dst[0] = 0 4 8 12
6 | // dst[1] = 1 5 9 13
7 | // dst[2] = 2 6 10 14
8 | // dst[3] = 3 7 11 15
9 | func pack(dst []uint32, src []byte) {
10 | for i := 0; i < 4; i++ {
11 | dst[i] = uint32(src[i])<<24 | uint32(src[4+i])<<16 | uint32(src[8+i])<<8 | uint32(src[12+i])
12 | }
13 | }
14 |
15 | // unpack moves bytes from src (state) to dst (bytes)
16 | // It is assumed that len(dst) >= 16
17 | func unpack(dst []byte, src []uint32) {
18 | for i := 0; i < 4; i++ {
19 | dst[i] = byte(src[i] >> 24)
20 | dst[4+i] = byte((src[i] >> 16) & 0xff)
21 | dst[8+i] = byte((src[i] >> 8) & 0xff)
22 | dst[12+i] = byte((src[i]) & 0xff)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/matasano/08-detect_aes_ecb_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "io/ioutil"
5 | "strings"
6 | "testing"
7 | )
8 |
9 | const datafile08 = "08-data.txt"
10 |
11 | func TestDetectAES(t *testing.T) {
12 | text, err := ioutil.ReadFile(datafile08)
13 | if err != nil {
14 | t.Fatal(err)
15 | }
16 | lines := strings.Split(string(text), "\n")
17 | actual := DetectAESECB(lines)
18 | expected := "d880619740a8a19b7840a8a31c810a3d08649af70dc06f4fd5d2d69c744cd283e2dd052f6b641dbf9d11b0348542bb5708649af70dc06f4fd5d2d69c744cd2839475c9dfdbc1d46597949d9c7e82bf5a08649af70dc06f4fd5d2d69c744cd28397a93eab8d6aecd566489154789a6b0308649af70dc06f4fd5d2d69c744cd283d403180c98c8f6db1f2a3f9c4040deb0ab51b29933f2c123c58386b06fba186a"
19 | if expected != actual {
20 | t.Fatalf("Expected - %s\nActual - %s", expected, actual)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/matasano/08-detect_aes_ecb.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "crypto/aes"
4 |
5 | // DetectAESECB detects which line is likely to be encoded by AES in ECB mode
6 | // This solves http://cryptopals.com/sets/1/challenges/8/
7 | func DetectAESECB(lines []string) string {
8 | var result string
9 | var blockScore int
10 | for _, line := range lines {
11 | if similarBlocks(line) > blockScore {
12 | result = line
13 | blockScore = similarBlocks(line)
14 | }
15 | }
16 | return result
17 | }
18 |
19 | func similarBlocks(line string) int {
20 | var score int
21 | blocks := make(map[string]int)
22 | for i := 0; i < len(line); i += aes.BlockSize {
23 | cur := line[i : i+aes.BlockSize]
24 | blocks[cur] = blocks[cur] + 1
25 | }
26 | for _, v := range blocks {
27 | if v > 1 {
28 | score += v
29 | }
30 | }
31 | return score
32 | }
33 |
--------------------------------------------------------------------------------
/matasano/17-cbc_padding_oracle_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "testing"
4 |
5 | func TestCBCPaddingOracle(t *testing.T) {
6 | for _, s := range plaintexts17 {
7 | encrypted, iv := encrypt17(s)
8 |
9 | plaintext := CBCPaddingOracle(encrypted, iv)
10 | plaintext, err := StripPKCS7(plaintext)
11 | if err != nil || string(plaintext) != s {
12 | t.Fatalf("Expected - %v\nActual - %v", []byte(s), plaintext)
13 | }
14 | }
15 | }
16 |
17 | // func TestCBCPaddingOracle2(t *testing.T) {
18 | // iv := make([]byte, 16)
19 | // rand.Read(iv)
20 | // cbcEnc.(ivSetter).SetIV(iv)
21 | //
22 | // dst := make([]byte, 16)
23 | // src := make([]byte, 16)
24 | // rand.Read(src)
25 | //
26 | // for i := 15; i > 0; i-- {
27 | // src = src[:i]
28 | // src = PadPKCS7(src, 16)
29 | //
30 | // cbcEnc.CryptBlocks(dst, src)
31 | //
32 | // actual := CBCPaddingOracle(dst, iv)
33 | // if !bytes.Equal(actual, src) {
34 | // t.Fatalf("Expected - %v\nActual - %v", src, actual)
35 | // }
36 | // }
37 | // }
38 |
--------------------------------------------------------------------------------
/matasano/09-pkcs7.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "errors"
4 |
5 | var errPaddingMalformed = errors.New("PKCS7 malformed")
6 |
7 | // PadPKCS7 pads an input array of bytes till it is a multiple of n bytes in length
8 | // Described more here - https://en.wikipedia.org/wiki/Padding_%28cryptography%29#PKCS7
9 | // This solves http://cryptopals.com/sets/2/challenges/9/
10 | func PadPKCS7(input []byte, n int) []byte {
11 | np := n - (len(input) % n)
12 | padding := byte(np) - byte(0)
13 |
14 | pbytes := make([]byte, np)
15 | for i := range pbytes {
16 | pbytes[i] = padding
17 | }
18 |
19 | input = append(input, pbytes...)
20 | return input
21 | }
22 |
23 | // StripPKCS7 removes the PKCS7 padding from a slice of bytes
24 | func StripPKCS7(input []byte) ([]byte, error) {
25 | l := len(input) - 1
26 | n := int(input[l])
27 | if n < 1 {
28 | return input, errPaddingMalformed
29 | }
30 |
31 | for i := l; i > l-n; i-- {
32 | if input[i] != input[l] {
33 | return input, errPaddingMalformed
34 | }
35 | }
36 |
37 | return input[0 : l-n+1], nil
38 | }
39 |
--------------------------------------------------------------------------------
/matasano/12-break_aes_ecb_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 | )
7 |
8 | func TestBreakECB(t *testing.T) {
9 | expected := []byte{0x52, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x27, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x35, 0x2e, 0x30, 0xa, 0x57, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x72, 0x61, 0x67, 0x2d, 0x74, 0x6f, 0x70, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x73, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x61, 0x69, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x77, 0xa, 0x54, 0x68, 0x65, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x20, 0x77, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x61, 0x79, 0x20, 0x68, 0x69, 0xa, 0x44, 0x69, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x3f, 0x20, 0x4e, 0x6f, 0x2c, 0x20, 0x49, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x62, 0x79, 0xa, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0}
10 | actual := BreakECBEasy()
11 | if !bytes.Equal(actual, expected) {
12 | t.Fatalf("Expected %s\nFound %s", string(expected), string(actual))
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/matasano/14.5-break_ecb_moderate_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 | )
7 |
8 | func TestBreakECBModerate(t *testing.T) {
9 | expected := []byte{0x52, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x27, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x35, 0x2e, 0x30, 0xa, 0x57, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x72, 0x61, 0x67, 0x2d, 0x74, 0x6f, 0x70, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x73, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x61, 0x69, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x77, 0xa, 0x54, 0x68, 0x65, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x20, 0x77, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x61, 0x79, 0x20, 0x68, 0x69, 0xa, 0x44, 0x69, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x3f, 0x20, 0x4e, 0x6f, 0x2c, 0x20, 0x49, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x62, 0x79, 0xa, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0}
10 | actual := BreakECBModerate()
11 | if !bytes.Equal(actual, expected) {
12 | t.Fatalf("Expected %s\nFound %s", string(expected), string(actual))
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/matasano/16-cbc_bitflipping.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "crypto/aes"
5 | "strings"
6 | )
7 |
8 | // FlipCBC modifies the encrypted text such that the last block contains ";admin=true;"
9 | // Assumes that the input was a multiple of aes.BlockSize and the last block of ciphertext is padding only
10 | // This solves http://cryptopals.com/sets/2/challenges/16
11 | func FlipCBC(b []byte) []byte {
12 | x := b[len(b)-48 : len(b)-32]
13 | old := []byte("und%20of%20bacon")
14 | new := []byte("unds;admin=true;")
15 | for i := range x {
16 | x[i] = x[i] ^ old[i] ^ new[i]
17 | }
18 | return b
19 | }
20 |
21 | func encrypt16(input string) ([]byte, []byte) {
22 | input = strings.Replace(input, ";", "", -1)
23 | input = strings.Replace(input, "=", "", -1)
24 | b := []byte("comment1=cooking%20MCs;userdata=" + input + ";comment2=%20like%20a%20pound%20of%20bacon")
25 | b = PadPKCS7(b, aes.BlockSize)
26 | iv := randbytes(aes.BlockSize)
27 | cbcEnc.(ivSetter).SetIV(iv)
28 | cbcEnc.CryptBlocks(b, b)
29 | return b, iv
30 | }
31 |
32 | // returns true if b contains ";admin=true;"
33 | func decrypt16(b []byte, iv []byte) bool {
34 | cbcDec.(ivSetter).SetIV(iv)
35 | cbcDec.CryptBlocks(b, b)
36 | s := string(b)
37 | return strings.Contains(s, "admin=true")
38 | }
39 |
--------------------------------------------------------------------------------
/matasano/06-break_repeatedkey_xor_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "io/ioutil"
5 | "testing"
6 | )
7 |
8 | const datafile06 = "06-data.txt"
9 |
10 | func TestDecryptRepeatedXOR(t *testing.T) {
11 | encoded, err := ioutil.ReadFile(datafile06)
12 | if err != nil {
13 | t.Fatal(err)
14 | }
15 | b := make([]byte, (len(encoded)/4)*3)
16 | DecodeBase64(b, encoded)
17 |
18 | actkey, plaintext := DecryptRepeatedXOR(b)
19 | expkey := "Terminator X: Bring the noise"
20 | if expkey != actkey {
21 | t.Fatalf("Inputs - %s\nExptected key - %s\nActual key - %s\nPlaintext -\n%s", datafile06, expkey, actkey, plaintext)
22 | }
23 | }
24 |
25 | func TestKeySize(t *testing.T) {
26 | encoded, err := ioutil.ReadFile(datafile06)
27 | if err != nil {
28 | t.Fatal(err)
29 | }
30 | b := make([]byte, (len(encoded)/4)*3)
31 | DecodeBase64(b, encoded)
32 | expected := 29
33 | actual := keysize(b)
34 | if expected != actual {
35 | t.Fatalf("Inputs - %s\nExptected - %d\nActual - %d", datafile06, expected, actual)
36 | }
37 | }
38 |
39 | func TestHammingdistance(t *testing.T) {
40 | in1 := []byte("this is a test")
41 | in2 := []byte("wokka wokka!!!")
42 | expected := 37
43 | actual := hammingdistance(in1, in2)
44 | if expected != actual {
45 | t.Fatalf("Inputs - %s\t%s\nExptected - %d\nActual - %d", in1, in2, expected, actual)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/aes/perf_test.go:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import (
4 | "crypto/aes"
5 | "crypto/rand"
6 | "testing"
7 | )
8 |
9 | var (
10 | key = make([]byte, aes.BlockSize)
11 | buf1 = make([]byte, aes.BlockSize)
12 | buf2 = make([]byte, aes.BlockSize)
13 | )
14 |
15 | // All benchmarks run on an Early-2013 Macbook Pro
16 | // CPU Core i5-3230M. Supports AES-NI instructions
17 | // RAM 8GB
18 |
19 | // Using same/separate buffers changes the time taken
20 | // Same buffer - 30ns/op
21 | // Different buffer - 27ns/op
22 | func BenchmarkAssemblyAESSame(b *testing.B) {
23 | rand.Read(key)
24 | c, _ := aes.NewCipher(key)
25 | testFunc(b, c.Encrypt, buf1, buf1)
26 | }
27 |
28 | func BenchmarkAssemblyAESDifferent(b *testing.B) {
29 | rand.Read(key)
30 | c, _ := aes.NewCipher(key)
31 | testFunc(b, c.Encrypt, buf1, buf2)
32 | }
33 |
34 | // Using same/separate buffers does not change the time taken
35 | // Takes 1200 ns/op
36 | func BenchmarkMyAES(b *testing.B) {
37 | rand.Read(key)
38 | c := NewCipher(key)
39 | testFunc(b, c.Encrypt, buf1, buf2)
40 | }
41 |
42 | func testFunc(b *testing.B, f func([]byte, []byte), buf1, buf2 []byte) {
43 | for n := 0; n < b.N; n++ {
44 | f(buf1, buf2)
45 | }
46 | }
47 |
48 | // Takes 702 ns/op
49 | func BenchmarkKeyExpansion(b *testing.B) {
50 | rand.Read(key)
51 | for n := 0; n < b.N; n++ {
52 | keyExpansion(key)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/matasano/14-break_aes_ecb_hard_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | //
4 | // func TestBreakECBHard(t *testing.T) {
5 | // // expected := []byte{0x52, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x27, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x35, 0x2e, 0x30, 0xa, 0x57, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x72, 0x61, 0x67, 0x2d, 0x74, 0x6f, 0x70, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x73, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x61, 0x69, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x77, 0xa, 0x54, 0x68, 0x65, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x20, 0x77, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x61, 0x79, 0x20, 0x68, 0x69, 0xa, 0x44, 0x69, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x3f, 0x20, 0x4e, 0x6f, 0x2c, 0x20, 0x49, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x62, 0x79, 0xa, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0}
6 | // actual := BreakECBHard()
7 | // fmt.Println(string(actual))
8 | // // if !bytes.Equal(actual, expected) {
9 | // // t.Fatalf("Expected %s\nFound %s", string(expected), string(actual))
10 | // // }
11 | // }
12 | //
13 | // func TestGenChosenCiphersHard(t *testing.T) {
14 | // ciphers, _ := genChosenCiphersHard()
15 | // for i := range ciphers {
16 | // if len(ciphers[i]) == 0 {
17 | // fmt.Println(i)
18 | // }
19 | // }
20 | // }
21 |
--------------------------------------------------------------------------------
/matasano/09-pkcs7_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "testing"
4 |
5 | func TestPadPCKCS7(t *testing.T) {
6 | inputs := []string{"YELLOW SUBMARINE", "TWENTY BYTELONG PARTYELLOW SUBMARINERS", "YELLOW", "20 YELLOW SUBMARINES"}
7 | expected := []string{"YELLOW SUBMARINE\x04\x04\x04\x04", "TWENTY BYTELONG PARTYELLOW SUBMARINERS\x02\x02", "YELLOW\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e",
8 | "20 YELLOW SUBMARINES\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14"}
9 | for i, input := range inputs {
10 | result := PadPKCS7([]byte(input), 20)
11 | if string(result) != expected[i] {
12 | t.Fatalf("PKCS#7 padding failed. Expected %x - Received %x", expected[i], result)
13 | }
14 | }
15 | }
16 |
17 | func TestStripPKCS7(t *testing.T) {
18 | inputs := []string{"YELLOW SUBMARINE\x04\x04\x04\x04", "TWENTY BYTELONG PARTYELLOW SUBMARINERS\x02\x02", "YELLOW\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e",
19 | "20 YELLOW SUBMARINES\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14"}
20 | expected := []string{"YELLOW SUBMARINE", "TWENTY BYTELONG PARTYELLOW SUBMARINERS", "YELLOW", "20 YELLOW SUBMARINES"}
21 | for i, input := range inputs {
22 | result, err := StripPKCS7([]byte(input))
23 | if string(result) != expected[i] || err != nil {
24 | t.Fatalf("PKCS#7 stripping failed. Expected %x - Received %x\nError - %s", expected[i], result, err)
25 | }
26 | }
27 |
28 | fails := []string{"YELLOW SUBMARINE\x04\x04\x04", "YELLOW SUBMARINE\x00"}
29 | for _, fail := range fails {
30 | _, err := StripPKCS7([]byte(fail))
31 | if err != errPaddingMalformed {
32 | t.Fatalf("PKCS#7 stripping failed. Expected %s", errPaddingMalformed)
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/matasano/11-ecb_cbc_oracle_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "testing"
4 |
5 | func TestECBCBCOracle(t *testing.T) {
6 | plaintexts := []string{
7 | "Lorem ipsum dolor sit amet, consectetur000000000000000000000000000000000000000000000000 adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
8 | "Lorem ipsum dolor sit amet, consectetur adipiscing00000000000000000000000000000000 elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 00000000000000000000000000000000Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
9 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit,abcdefghijklmnopqrstuvwxyz012345 sed do eiusmod tempor incididunt ut labore et dolore magna ali/abcdefghijklmnopqrstuvwxyz012345qua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."}
10 | for _, plaintext := range plaintexts {
11 | ciphers, expected := generateCiphertexts([]byte(plaintext))
12 | predicted := OracleAES(ciphers)
13 | for i := range expected {
14 | if expected[i] != predicted[i] {
15 | if expected[i] == 1 {
16 | t.Fatalf("Plaintext - %s\nExpected Oracle to detect AES ECB but found CBC", plaintext)
17 | } else {
18 | t.Fatalf("Plaintext - %s\nExpected Oracle to detect AES CBC but found ECB", plaintext)
19 | }
20 | }
21 | }
22 | }
23 | }
24 |
25 | func TestRandbytes(t *testing.T) {
26 | for i := 2; i < 20; i++ {
27 | r := randbytes(i)
28 | if len(r) != i {
29 | t.Fatalf("Expected byte slice of length %d, got length %d instead", i, len(r))
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/matasano/03-break_singlekey_xor.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | // approximate frequencies of letters used in the english language
4 | // ETAOIN = 3, SHRDLU = 2.5, FGPWY = 2, B = 1.5, KV = 1.0, JX = 0.5, QZ = 0.1
5 | // based on http://en.wikipedia.org/wiki/Letter_frequency
6 | var letterfreq = map[byte]float64{'a': 3.0, 'A': 3.0,
7 | 'b': 1.5, 'B': 1.5, 'c': 2.5, 'C': 2.5, 'd': 2.5, 'D': 2.5,
8 | 'e': 3.0, 'E': 3.0, 'f': 2.0, 'F': 2.0, 'g': 2.0, 'G': 2.0,
9 | 'h': 2.5, 'H': 2.5, 'i': 3.0, 'I': 3.0, 'j': 0.5, 'J': 0.5,
10 | 'k': 1.0, 'K': 1.0, 'l': 2.5, 'L': 2.5, 'm': 2.0, 'M': 2.0,
11 | 'n': 3.0, 'N': 3.0, 'o': 3.0, 'O': 3.0, 'p': 2.0, 'P': 2.0,
12 | 'q': 0.1, 'Q': 0.1, 'r': 2.5, 'R': 2.5, 's': 2.5, 'S': 2.5,
13 | 't': 3.0, 'T': 3.0, 'u': 2.5, 'U': 2.5, 'v': 1.0, 'V': 1.0,
14 | 'w': 2.0, 'W': 2.0, 'x': 0.5, 'X': 0.5, 'y': 2.0, 'Y': 2.0,
15 | 'z': 0.1, 'Z': 0.1, ' ': 3.0, '.': 1.0, ',': 1.0, ':': 1.0}
16 |
17 | // BreakSingleXor decrypts an array of bytes by XOR-ing it with all possible letters and choosing the
18 | // array with the highest rank.
19 | // It returns the decrypted byte array, the rank of that array and the key used to decrypt it
20 | // This solves http://cryptopals.com/sets/1/challenges/3/
21 | func BreakSingleXor(input []byte) ([]byte, float64, byte) {
22 | var result []byte
23 | var currank float64
24 | var rkey byte
25 | for i := 0; i <= 255; i++ {
26 | key := byte(i)
27 | decrypted := XorOne(input, key)
28 | rank := getrank(decrypted)
29 | if currank <= rank {
30 | currank = rank
31 | result = decrypted
32 | rkey = key
33 | }
34 | }
35 | return result, currank, rkey
36 | }
37 |
38 | func getrank(input []byte) float64 {
39 | var rank float64
40 | for _, l := range input {
41 | rank += letterfreq[l]
42 | }
43 | return rank
44 | }
45 |
--------------------------------------------------------------------------------
/matasano/06-break_repeatedkey_xor.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "bytes"
4 |
5 | const (
6 | minKeySize = 2
7 | maxKeySize = 40
8 | )
9 |
10 | // DecryptRepeatedXOR decrypts ciphertext encrypted with repeating-key XOR
11 | // This solves http://cryptopals.com/sets/1/challenges/6/
12 | func DecryptRepeatedXOR(b []byte) (string, string) {
13 | ksize := keysize(b)
14 | buffers := make([]bytes.Buffer, ksize)
15 | for i := 0; i < len(b)-ksize+1; i += ksize {
16 | for j := range buffers {
17 | buffers[j].WriteByte(b[i+j])
18 | }
19 | }
20 | var key bytes.Buffer
21 | for i := range buffers {
22 | _, _, keybyte := BreakSingleXor(buffers[i].Bytes())
23 | key.WriteByte(keybyte)
24 | }
25 |
26 | return key.String(), string(decryptRepeatedXor(b, key.Bytes()))
27 | }
28 |
29 | func keysize(p []byte) int {
30 | var curdistance, curkeysize int
31 | curdistance = (1 << 32) - 1
32 | for i := minKeySize; i <= maxKeySize; i++ {
33 | distance := 0
34 | for j := 0; j < len(p)-i*2; j += i {
35 | distance += hammingdistance(p[j:j+i], p[j+i:j+2*i])
36 | }
37 | if curdistance > distance {
38 | curdistance = distance
39 | curkeysize = i
40 | }
41 | }
42 | return curkeysize
43 | }
44 |
45 | // hammingdistance finds the hamming distance between two byte arrays
46 | // hammingdistance(i, j) = hammingweight(i^j)
47 | // Methods to find weight - http://en.wikipedia.org/wiki/Hamming_weight
48 | // Super convoluted and efficient way to find weight - http://stackoverflow.com/a/109025/1109785
49 | func hammingdistance(p, q []byte) int {
50 | numbitset := func(b byte) int {
51 | var count int
52 | for b != 0 {
53 | b &= b - 1
54 | count++
55 | }
56 | return count
57 | }
58 |
59 | var distance int
60 | for i := 0; i < len(p); i++ {
61 | t := p[i] ^ q[i]
62 | distance += numbitset(t)
63 | }
64 | return distance
65 | }
66 |
--------------------------------------------------------------------------------
/matasano/01-hextobase64_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "testing"
4 |
5 | func TestEncodeBase64(t *testing.T) {
6 | inputs := []string{"pleasure.", "leasure.", "easure.", "asure.", "sure."}
7 | expected := []string{"cGxlYXN1cmUu", "bGVhc3VyZS4=", "ZWFzdXJlLg==", "YXN1cmUu", "c3VyZS4="}
8 | for i := range inputs {
9 | encoded := string(base64FromString([]byte(inputs[i])))
10 | if expected[i] != encoded {
11 | t.Fatalf("Input - %s\nExptected - %s\nActual - %s", inputs[i], expected[i], encoded)
12 | }
13 | }
14 | }
15 |
16 | func TestDecodeBase64(t *testing.T) {
17 | inputs := [][]byte{[]byte("cGxl\r\rYXN1cmUu"), []byte("bGVhc3\r\nVyZS4="),
18 | []byte("Z\rWFzdXJlL\ng=="), []byte("YX\nN1c\nmUu"), []byte("c3\n\rVyZS4=")}
19 | expected := []string{"pleasure.", "leasure.", "easure.", "asure.", "sure."}
20 | for i, src := range inputs {
21 | dst := make([]byte, (len(src)/4)*3)
22 | n := DecodeBase64(dst, src)
23 | dst = dst[0:n]
24 | if string(dst) != expected[i] {
25 | t.Fatalf("Input - %s\nExpected - %s\nFound - %s", string(src), expected[i], string(dst))
26 | }
27 | }
28 | }
29 |
30 | func TestStringFromHex(t *testing.T) {
31 | input := "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"
32 | expected := "I'm killing your brain like a poisonous mushroom"
33 | actual := string(StringFromHex([]byte(input)))
34 | if expected != actual {
35 | t.Fatalf("Input - %s\nExptected - %s\nActual - %s", input, expected, actual)
36 | }
37 | }
38 |
39 | func TestBase64FromHex(t *testing.T) {
40 | input := "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"
41 | expected := "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t"
42 | actual := string(Base64FromHex([]byte(input)))
43 | if expected != actual {
44 | t.Fatalf("Input - %s\nExptected - %s\nActual - %s", input, expected, actual)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/matasano/18-aes_ctr.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "crypto/cipher"
5 |
6 | "github.com/nindalf/crypto/aes"
7 | )
8 |
9 | var ctrAES = NewCTR(aesBlockCipher, make([]byte, aes.BlockSize))
10 |
11 | // ctr implements the Stream interface from crypto/cipher
12 | // http://golang.org/pkg/crypto/cipher/#Stream
13 | // This solves http://cryptopals.com/sets/3/challenges/17
14 | type ctr struct {
15 | cipher.Block
16 | nonce []byte
17 | }
18 |
19 | // NewCTR creates a new CTR
20 | func NewCTR(block cipher.Block, iv []byte) cipher.Stream {
21 | nonce := make([]byte, aes.BlockSize)
22 | copy(nonce, iv)
23 | return ctr{block, nonce}
24 | }
25 |
26 | // XORKeyStream XORs each byte in the given slice with a byte from the
27 | // cipher's key stream. Dst and src may point to the same memory.
28 | // If len(dst) < len(src), XORKeyStream should panic. It is acceptable
29 | // to pass a dst bigger than src, and in that case, XORKeyStream will
30 | // only update dst[:len(src)] and will not touch the rest of dst.
31 | func (c ctr) XORKeyStream(dst, src []byte) {
32 | if len(dst) < len(src) {
33 | panic("dst smaller than src")
34 | }
35 |
36 | temp := make([]byte, aes.BlockSize)
37 | counter := make(byteint, aes.BlockSize)
38 | copy(counter, c.nonce)
39 |
40 | for len(src) > 0 {
41 | copy(temp, counter)
42 | counter.AddOne()
43 |
44 | c.Encrypt(temp, temp)
45 |
46 | l := min(len(src), aes.BlockSize)
47 | xorBytes(temp[:l], src[:l])
48 | copy(dst[:l], temp)
49 |
50 | dst = dst[l:]
51 | src = src[l:]
52 | }
53 | }
54 |
55 | func (c ctr) SetIV(iv []byte) {
56 | copy(c.nonce, iv)
57 | }
58 |
59 | func min(a, b int) int {
60 | if a < b {
61 | return a
62 | }
63 | return b
64 | }
65 |
66 | // byteint is n-byte integer
67 | // It supports one operation - AddOne
68 | type byteint []byte
69 |
70 | func (b byteint) AddOne() {
71 | for i := len(b) - 1; i >= 0; i-- {
72 | b[i]++
73 | if b[i] != 0 {
74 | break
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/stanford/6.3-unifying-theme.md:
--------------------------------------------------------------------------------
1 | Unifying Theme
2 | ====
3 |
4 | **One way functions**
5 |
6 | A function f is one-way if
7 |
8 | * There is an efficient algorithm to evaluate f(.) but
9 | * Inverting f is hard. For all efficient A and x <- X: Pr[f(A(f(x))) = f(x)] < negligible
10 | * Say f(x1) = f(x2) = f(x3), given this value, A will not be able to produce any of x1, x2, x3
11 |
12 | Proving the existence of one-way functions is the same as proving P != NP
13 |
14 | **Example 1: Generic one-way functions**
15 |
16 | * Let f: X -> Y be a secure PRG (|Y| >> |X|), eg. f built using det. counter mode
17 | * Lemma: f is a secure PRG => f is one-way
18 | * Proof: Consider the contrapositive. A inverts f. Using A we could build a distinguisher that checks if f(A(y)) = y. For a truly random output y, it would fail and hence the PRG would no longer be secure
19 | * This is not useful for key exchange. The best key exchange possible with this is Merkle puzzles
20 |
21 | **Example 2: DLOG**
22 |
23 | * Fix a cyclic group G (eg. G = ℤN* or an elliptic curve) of order n
24 | * Fix a generator g in G (ie G = {1, g, g2, ..., gn-1})
25 | * Define f: ℤN -> G as f(x) = gx ∈ G
26 | * Lemma: Dlog hard in G => f is one-way
27 | * Important property: f(x), f(y) => f(x+y) = f(x).f(y). This enables public key crypto
28 |
29 | **Example 3: RSA**
30 |
31 | * Choose random primes p,q ≈ 1024 bits. Set N=p.q
32 | * Choose e,d s.t. e.d = 1 mod 𝜑(N)
33 | * Define f: ℤN* -> ℤN* as f(x) = xe in ℤN*
34 | * Lemma: f is one-way under the RSA assumption. (The assumption is that f is one-way)
35 | * Properties: f(x), f(y) => f(x.y) = f(x).f(y) *and* f has a trapdoor (the trapdoor makes it very easy to make digital signatures)
36 |
37 | **Summary**
38 |
39 | Public key encryption was made possible by one-way functions with special properties. In particular, the homomorphic property (f(x), f(y) => f(x.y) or f(x+y))
40 |
--------------------------------------------------------------------------------
/matasano/13-ecb_cut_paste_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "strings"
5 | "testing"
6 | )
7 |
8 | func TestCreateAdminProfile(t *testing.T) {
9 | profile := decryptProfile(CreateAdminProfile())
10 | expectedlen := 3
11 | if len(profile) != expectedlen {
12 | t.Fatalf("Returned profile is not of length %d", expectedlen)
13 | }
14 | expectedrole := "admin"
15 | if profile["role"] != expectedrole {
16 | t.Fatalf("Expected role - %s\tActual role - %s", expectedrole, profile["role"])
17 | }
18 | }
19 |
20 | func TestKvencoder(t *testing.T) {
21 | input := map[string]string{"a": "first", "b": "2nd", "c&b=malicious": "3", "c": "3&b=malicious", "d": "4ourth", "e": "b=malicious"}
22 | expectedKeys := 3
23 | actual := kvencoder(input)
24 | if strings.Contains(actual, "malicious") {
25 | t.Fatalf("Encoded string contains malicious input - %s", actual)
26 | }
27 | if strings.Count(actual, "=") != expectedKeys || strings.Count(actual, "&") != expectedKeys-1 {
28 | t.Fatalf("Encoded string contains incorrect number of params - %s", actual)
29 | }
30 | }
31 |
32 | func TestKvencoderBad(t *testing.T) {
33 | input := map[string]string{"a": "first", "b": "2nd", "c&b=malicious": "3", "c": "3&b=malicious", "d": "4ourth", "e": "b=malicious"}
34 | keys := []string{"a", "b", "c&b=malicious", "3&b=malicious", "d", "e"}
35 | actual := kvencoderBad(input, keys)
36 | expected := "a=first&b=2nd&d=4ourth"
37 | if expected != actual {
38 | t.Fatalf("Encoding failed. Expected - %s\tActual - %s\n", expected, actual)
39 | }
40 | }
41 |
42 | func TestKvdecoder(t *testing.T) {
43 | input := "a=first&b=2nd&d=4ourth"
44 | actual := kvdecoder(input)
45 | expected := map[string]string{"a": "first", "b": "2nd", "d": "4ourth"}
46 | if len(actual) != len(expected) {
47 | t.Fatalf("Failed to decode string.\nExpected length - %d\tActual length - %d", len(expected), len(actual))
48 | }
49 | for k := range expected {
50 | if expected[k] != actual[k] {
51 | t.Fatalf("Failed to decode string. Different values found for key - %s\nExpected - %s\tActual - %s", k, expected[k], actual[k])
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/matasano/12-break_aes_ecb.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/nindalf/crypto/aes"
7 | )
8 |
9 | // a function that produces: AES-128-ECB(b || unknown-string, random-key)
10 | func oracleeasy(b []byte) []byte {
11 | plaintext := []byte("Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK")
12 | dec := make([]byte, (3*len(plaintext))/4)
13 | DecodeBase64(dec, plaintext)
14 | b = append(b, dec...)
15 | b = PadPKCS7(b, aes.BlockSize)
16 | ecbEnc.CryptBlocks(b, b)
17 | return b
18 | }
19 |
20 | // BreakECBEasy decrypts a ciphertext received from the oracle function (defined above)
21 | // It does so by repeated calls to the oracle
22 | // This solves http://cryptopals.com/sets/2/challenges/12/
23 | func BreakECBEasy() []byte {
24 | chosens := genChosenCiphersEasy()
25 | var decrypted bytes.Buffer
26 | previous := make([]byte, aes.BlockSize, len(chosens[0]))
27 | for i := 0; i < len(chosens[0]); i += aes.BlockSize {
28 | previous = decrypt16bytesEasy(chosens, previous, i)
29 | decrypted.Write(previous)
30 | }
31 | return decrypted.Bytes()
32 | }
33 |
34 | func decrypt16bytesEasy(chosens [][]byte, previous []byte, index int) []byte {
35 | decrypted := make([]byte, 0, aes.BlockSize)
36 | for i := len(chosens) - 1; i >= 0; i-- {
37 | previous = previous[1:len(previous)]
38 | dec := decryptbyteEasy(chosens[i][index:index+aes.BlockSize], previous)
39 | previous = append(previous, dec)
40 | decrypted = append(decrypted, dec)
41 | }
42 | return decrypted
43 | }
44 |
45 | func decryptbyteEasy(chosen, previous []byte) byte {
46 | previous = append(previous, byte(0))
47 | for i := 0; i < 255; i++ {
48 | previous[aes.BlockSize-1] = byte(i)
49 | if bytes.Equal(oracleeasy(previous)[0:aes.BlockSize], chosen) {
50 | return byte(i)
51 | }
52 | }
53 | return 0
54 | }
55 |
56 | func genChosenCiphersEasy() [][]byte {
57 | chosens := make([][]byte, 0, aes.BlockSize)
58 | prefix := make([]byte, 0, aes.BlockSize-1)
59 | chosens = append(chosens, oracleeasy(prefix))
60 | var x byte
61 | for i := 0; i < aes.BlockSize-1; i++ {
62 | prefix = append(prefix, x)
63 | chosens = append(chosens, oracleeasy(prefix))
64 | }
65 | return chosens
66 | }
67 |
--------------------------------------------------------------------------------
/stanford/6-public-key-encryption.md:
--------------------------------------------------------------------------------
1 | Public Key Encryption
2 | ===
3 |
4 | A public key encryption system is a triple of algorithms (G, E, D).
5 |
6 | * G() - a randomized algorithm that outputs a key pair (pk, sk) (public key, secret key)
7 | * E(pk, m) - Encrypts the message m ∈ M under the private key and generates a ciphertext c ∈ C
8 | * D(sk, c) - Decrypts the ciphertext c ∈ C using the secret key to recover the message m or ⟘
9 |
10 | The triple is consistent. ∀(pk, sk) output by G and ∀ m ∈ M: D(sk, E(pk, m)) = m
11 |
12 | Its useful for
13 |
14 | * Session setup, say between a web server and a web browser
15 | * Non-interactive applications
16 | 1. Email - encrypt the message with the recipient's public key
17 | 2. Encrypted filesystems - encrypt a file with a symmetric key and include in the header copies of the symmetric key encrypted with the public keys of the people who have access. Such a scheme accommodates key escrow services - where one of the public keys used is kescrow
18 |
19 | ---
20 |
21 | #### Security
22 |
23 | **Example of active attack**:
24 |
25 | Scenario: Bob sends the gmail server a message for Caroline(caroline@gmail.com) encrypted with CTR mode. The attacker intercepts the message and modifies it. He knows that the first few bytes of the message is "to:caroline@". He trivially changes that to "to:attacker@". The plaintext gets sent to him by the gmail server.
26 |
27 | **Chosen ciphertext security**:
28 |
29 | The game for encryption scheme (G, E, D) is defined thus:
30 |
31 | * The challenger is implementing experiment "b" = {0, 1}.
32 | * The challenger generates (pk, sk) and sends the adversary pk.
33 | * The adversary enters CCA phase 1 and submits a series of ciphertexts and asks for the plaintexts.
34 | * The adversary then submits 2 messages m0 and m1 where |m0| = |m1|. The challenger returns the ciphertext c <- E(pk, mb).
35 | * The adversary enters CCA phase 1 and submits a series of ciphertexts and asks for the plaintexts. The only restriction is that he can't submit the ciphertext c.
36 |
37 | (G, E, D) is Chosen Ciphertext Attack (CCA) secure if for all efficient adversaries - AdvCCA[A, E] = |Pr[Exp(0)=1] - Pr[Exp(1)=1]| < negligible
38 |
39 | This is the correct notion of security for Public Key systems
40 |
--------------------------------------------------------------------------------
/matasano/07-aes_ecb.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "crypto/cipher"
5 | "runtime"
6 | "sync"
7 |
8 | "github.com/nindalf/crypto/aes"
9 | )
10 |
11 | // Used when a random key needs to be used repeatedly
12 | var rkey = randbytes(16)
13 | var aesBlockCipher = aes.NewCipher(rkey)
14 | var ecbDec = newECBDecrypter(aesBlockCipher)
15 | var ecbEnc = newECBEncrypter(aesBlockCipher)
16 |
17 | type ecb struct {
18 | cipher.Block // the block cipher
19 | }
20 |
21 | // ecbDecrypter decrypts a ciphertext encrypted with AES in ECB mode.
22 | // implements the BlockMode interface from crypto/cipher
23 | // http://golang.org/pkg/crypto/cipher/#BlockMode
24 | // This solves http://cryptopals.com/sets/1/challenges/7/
25 | type ecbDecrypter ecb
26 |
27 | func newECBDecrypter(b cipher.Block) cipher.BlockMode {
28 | e := &ecb{b}
29 | return (*ecbDecrypter)(e)
30 | }
31 |
32 | func (e *ecbDecrypter) CryptBlocks(dst, src []byte) {
33 | for len(src) > 0 && len(dst) > 0 {
34 | e.Decrypt(dst[:aes.BlockSize], src[:aes.BlockSize])
35 | src = src[aes.BlockSize:]
36 | dst = dst[aes.BlockSize:]
37 | }
38 | }
39 |
40 | // ecbEncrypter encrypts a plaintext with AES in ECB mode.
41 | // implements the BlockMode interface from crypto/cipher
42 | // http://golang.org/pkg/crypto/cipher/#BlockMode
43 | type ecbEncrypter ecb
44 |
45 | func newECBEncrypter(b cipher.Block) cipher.BlockMode {
46 | e := &ecb{b}
47 | return (*ecbEncrypter)(e)
48 | }
49 |
50 | func (e *ecbEncrypter) CryptBlocks(dst, src []byte) {
51 | for len(src) > 0 && len(dst) > 0 {
52 | e.Encrypt(dst[:aes.BlockSize], src[:aes.BlockSize])
53 | src = src[aes.BlockSize:]
54 | dst = dst[aes.BlockSize:]
55 | }
56 | }
57 |
58 | // EncryptAESECBParallel encrypts a plaintext with AES in ECB mode.
59 | func EncryptAESECBParallel(b, key []byte) {
60 | aesc := aes.NewCipher(key)
61 |
62 | c := runtime.NumCPU()
63 | blocks := len(b) / aes.BlockSize
64 | blocksperCPU := blocks/c + 1
65 | var wg sync.WaitGroup
66 |
67 | for i := 0; i+aes.BlockSize*blocksperCPU <= len(b); i += aes.BlockSize * blocksperCPU {
68 | wg.Add(1)
69 | go encryptECBblocks(b[i:i+aes.BlockSize*blocksperCPU], aesc, &wg)
70 | }
71 | wg.Wait()
72 | }
73 |
74 | func encryptECBblocks(b []byte, aesc cipher.Block, wg *sync.WaitGroup) {
75 | for len(b) > 0 {
76 | aesc.Decrypt(b[:aes.BlockSize], b[:aes.BlockSize])
77 | b = b[aes.BlockSize:]
78 | }
79 | wg.Done()
80 | }
81 |
--------------------------------------------------------------------------------
/matasano/10-aes_cbc.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "crypto/cipher"
5 |
6 | "github.com/nindalf/crypto/aes"
7 | )
8 |
9 | var cbcDec = NewCBCDecrypter(aesBlockCipher, []byte{})
10 | var cbcEnc = NewCBCEncrypter(aesBlockCipher, []byte{})
11 |
12 | type cbc struct {
13 | cipher.Block // the block cipher
14 | iv []byte
15 | }
16 |
17 | type ivSetter interface {
18 | SetIV([]byte)
19 | }
20 |
21 | // cbcDecrypter decrypts a ciphertext encrypted with AES in CBC mode.
22 | // implements the BlockMode interface from crypto/cipher
23 | // http://golang.org/pkg/crypto/cipher/#BlockMode
24 | // This solves http://cryptopals.com/sets/2/challenges/10/
25 | type cbcDecrypter cbc
26 |
27 | // NewCBCDecrypter creates a new CBC decrypter using a given block cipher
28 | func NewCBCDecrypter(b cipher.Block, iv []byte) cipher.BlockMode {
29 | ivcopy := make([]byte, aes.BlockSize)
30 | copy(ivcopy, iv)
31 | c := &cbc{b, ivcopy}
32 | return (*cbcDecrypter)(c)
33 | }
34 |
35 | func (c *cbcDecrypter) CryptBlocks(dst, src []byte) {
36 | temp1, temp2 := make([]byte, aes.BlockSize), make([]byte, aes.BlockSize)
37 | copy(temp1, c.iv)
38 | for len(src) > 0 && len(dst) > 0 {
39 | copy(temp2, src[:aes.BlockSize])
40 |
41 | c.Decrypt(dst[:aes.BlockSize], src[:aes.BlockSize])
42 | xorBytes(dst[:aes.BlockSize], temp1)
43 |
44 | src = src[aes.BlockSize:]
45 | dst = dst[aes.BlockSize:]
46 |
47 | copy(temp1, temp2)
48 | }
49 | }
50 |
51 | func (c *cbcDecrypter) SetIV(iv []byte) {
52 | copy(c.iv, iv)
53 | }
54 |
55 | // cbcEncrypter decrypts a ciphertext encrypted with AES in CBC mode.
56 | // implements the BlockMode interface from crypto/cipher
57 | // http://golang.org/pkg/crypto/cipher/#BlockMode
58 | type cbcEncrypter cbc
59 |
60 | // NewCBCEncrypter creates a new CBC Encrypter using a given block cipher
61 | func NewCBCEncrypter(b cipher.Block, iv []byte) cipher.BlockMode {
62 | ivcopy := make([]byte, aes.BlockSize)
63 | copy(ivcopy, iv)
64 | c := &cbc{b, ivcopy}
65 | return (*cbcEncrypter)(c)
66 | }
67 |
68 | func (c *cbcEncrypter) CryptBlocks(dst, src []byte) {
69 | temp := make([]byte, aes.BlockSize)
70 | copy(temp, c.iv)
71 |
72 | for len(src) > 0 && len(dst) > 0 {
73 | xorBytes(temp, src)
74 | c.Encrypt(dst[:aes.BlockSize], temp)
75 |
76 | copy(temp, dst[:aes.BlockSize])
77 |
78 | src = src[aes.BlockSize:]
79 | dst = dst[aes.BlockSize:]
80 | }
81 | }
82 |
83 | func (c *cbcEncrypter) SetIV(iv []byte) {
84 | copy(c.iv, iv)
85 | }
86 |
87 | func xorBytes(dst, src []byte) {
88 | for i := range dst {
89 | dst[i] ^= src[i]
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/matasano/17-cbc_padding_oracle.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "crypto/aes"
6 | )
7 |
8 | var plaintexts17 = []string{
9 | "MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc=",
10 | "MDAwMDAxV2l0aCB0aGUgYmFzcyBraWNrZWQgaW4gYW5kIHRoZSBWZWdhJ3MgYXJlIHB1bXBpbic=",
11 | "MDAwMDAyUXVpY2sgdG8gdGhlIHBvaW50LCB0byB0aGUgcG9pbnQsIG5vIGZha2luZw==",
12 | "MDAwMDAzQ29va2luZyBNQydzIGxpa2UgYSBwb3VuZCBvZiBiYWNvbg==",
13 | "MDAwMDA0QnVybmluZyAnZW0sIGlmIHlvdSBhaW4ndCBxdWljayBhbmQgbmltYmxl",
14 | "MDAwMDA1SSBnbyBjcmF6eSB3aGVuIEkgaGVhciBhIGN5bWJhbA==",
15 | "MDAwMDA2QW5kIGEgaGlnaCBoYXQgd2l0aCBhIHNvdXBlZCB1cCB0ZW1wbw==",
16 | "MDAwMDA3SSdtIG9uIGEgcm9sbCwgaXQncyB0aW1lIHRvIGdvIHNvbG8=",
17 | "MDAwMDA4b2xsaW4nIGluIG15IGZpdmUgcG9pbnQgb2g=",
18 | "MDAwMDA5aXRoIG15IHJhZy10b3AgZG93biBzbyBteSBoYWlyIGNhbiBibG93"}
19 |
20 | // CBCPaddingOracle breaks a ciphertext encrypted using CBC-mode block cipher
21 | // It does so by changing ciphertext bytes and checking if the corresponding padding is valid
22 | // This solves http://cryptopals.com/sets/3/challenges/17
23 | func CBCPaddingOracle(b, iv []byte) []byte {
24 | var decrypted bytes.Buffer
25 | t := make([]byte, aes.BlockSize)
26 |
27 | for len(b) > 0 {
28 | copy(t, b[:aes.BlockSize])
29 | dec := breakCBCBlock(b[:aes.BlockSize], iv, len(b) == 16)
30 | copy(iv, t)
31 | b = b[aes.BlockSize:]
32 | decrypted.Write(dec)
33 | }
34 | return decrypted.Bytes()
35 | }
36 |
37 | // decrypts the first 16 bytes of block b using calls to the padding oracle
38 | func breakCBCBlock(b, iv []byte, lastblock bool) []byte {
39 | p := make([]byte, aes.BlockSize)
40 | c := make([]byte, aes.BlockSize)
41 | ivc := make([]byte, aes.BlockSize)
42 | for i := 15; i >= 0; i-- {
43 | copy(ivc, iv)
44 | paddingbyte := byte(16 - i)
45 |
46 | for j := 15; j > i; j-- {
47 | ivc[j] ^= p[j] ^ paddingbyte
48 | }
49 |
50 | temp := iv[i]
51 | for k := 0; k < 256; k++ {
52 | if lastblock && i == 15 && byte(k) == paddingbyte {
53 | continue
54 | }
55 | ivc[i] = temp ^ byte(k) ^ paddingbyte
56 | if isPaddingValid(c, b, ivc) {
57 | p[i] = byte(k)
58 | break
59 | }
60 | }
61 | }
62 | return p
63 | }
64 |
65 | func encrypt17(s string) ([]byte, []byte) {
66 | b := []byte(s)
67 | b = PadPKCS7(b, 16)
68 | iv := randbytes(aes.BlockSize)
69 | cbcEnc.(ivSetter).SetIV(iv)
70 | cbcEnc.CryptBlocks(b, b)
71 | return b, iv
72 | }
73 |
74 | // isPaddingValid decrypts the ciphertext and returns true if the padding is valid
75 | func isPaddingValid(dst, src, iv []byte) bool {
76 | cbcDec.(ivSetter).SetIV(iv)
77 | cbcDec.CryptBlocks(dst, src)
78 | _, err := StripPKCS7(dst)
79 | return err == nil
80 | }
81 |
--------------------------------------------------------------------------------
/matasano/18-aes_ctr_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "crypto/rand"
6 | "testing"
7 |
8 | "github.com/nindalf/crypto/aes"
9 | )
10 |
11 | func TestCTREncryptDecrypt(t *testing.T) {
12 | input := "ATTACK AT DAWN!!ATTACK AT DAWN!!"
13 | testCTR(t, input)
14 | testCTR(t, input[0:1])
15 | testCTR(t, input[0:15])
16 | testCTR(t, input[0:16])
17 | testCTR(t, input[0:17])
18 | }
19 |
20 | func testCTR(t *testing.T, input string) {
21 | b := []byte(input)
22 |
23 | iv := make([]byte, aes.BlockSize)
24 | rand.Read(iv)
25 | ctrAES.(ivSetter).SetIV(iv)
26 |
27 | ctrAES.XORKeyStream(b, b)
28 | if string(b) == input {
29 | t.Fatalf("Failed to encrypt - %s", input)
30 | }
31 |
32 | ctrAES.XORKeyStream(b, b)
33 | if string(b) != input {
34 | t.Fatalf("Failed to decrypt - %s, %s", input, string(b))
35 | }
36 | }
37 |
38 | func TestCTRDecryptCoursera(t *testing.T) {
39 | // Modified ciphertext from coursera to render copying moot
40 | b := []byte{0xe4, 0x62, 0x18, 0xc0, 0xa5, 0x3c, 0xbe, 0xca, 0x69, 0x5a, 0xe4, 0x5f, 0xaa, 0x89, 0x52, 0xaa, 0xe, 0x37, 0xd, 0xdf, 0xd9, 0x55, 0x5, 0x3f, 0x6f, 0x78, 0x96, 0xc0, 0x45, 0x2, 0xfc, 0xc7, 0x1b, 0x23, 0xd6, 0x35, 0x7d, 0xbe, 0x62, 0xe, 0x52, 0x8d, 0x70, 0xf7, 0xb0, 0xd1, 0x85, 0x32, 0xf5, 0x11}
41 | expected := "Always avoid the random gibberish while decrypting"
42 |
43 | key := []byte{0x36, 0xf1, 0x83, 0x57, 0xbe, 0x4d, 0xbd, 0x77, 0xf0, 0x50, 0x51, 0x5c, 0x73, 0xfc, 0xf9, 0xf2}
44 | iv := []byte{0x77, 0xb, 0x80, 0x25, 0x9e, 0xc3, 0x3b, 0xeb, 0x25, 0x61, 0x35, 0x8a, 0x9f, 0x2d, 0xc6, 0x17}
45 |
46 | block := aes.NewCipher(key)
47 | ctr := newCTR(block, iv)
48 | ctr.XORKeyStream(b, b)
49 |
50 | if string(b) != expected {
51 | t.Fatalf("Failed to decrypt in CTR mode. Expected - %s\tFound - %s", expected, string(b))
52 | }
53 | }
54 |
55 | func TestCTRDecryptMatasano(t *testing.T) {
56 | // Modified ciphertext from matasano to decrypt with big endian CTR instead of little endian
57 | cbase64 := []byte("L77na/nrFsKvynd6HzOoGwmL9IdFE3VwIGiYjm2sZ3DTipkgGMEWpydcWhNf5gf1K+UD6F6F")
58 | c := make([]byte, (len(cbase64)/4)*3)
59 | DecodeBase64(c, cbase64)
60 | expected := []byte{0x59, 0x6f, 0x2c, 0x20, 0x56, 0x49, 0x50, 0x20, 0x4c, 0x65, 0x74, 0x27, 0x73, 0x20, 0x6b, 0x69, 0x63, 0x6b, 0x20, 0x69, 0x74, 0x20, 0x49, 0x63, 0x65, 0x2c, 0x20, 0x49, 0x63, 0x65, 0x2c, 0x20, 0x62, 0x61, 0x62, 0x79, 0x20, 0x49, 0x63, 0x65, 0x2c, 0x20, 0x49, 0x63, 0x65, 0x2c, 0x20, 0x62, 0x61, 0x62, 0x79, 0x20, 0x49, 0xfa}
61 |
62 | key := []byte("YELLOW SUBMARINE")
63 | iv := make([]byte, 16)
64 |
65 | block := aes.NewCipher(key)
66 | ctr := newCTR(block, iv)
67 | ctr.XORKeyStream(c, c)
68 |
69 | if !bytes.Equal(c, expected) {
70 | t.Fatalf("Failed to decrypt in CTR mode. Expected - %s\tFound - %s", expected, string(c))
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/matasano/11-ecb_cbc_oracle.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "crypto/aes"
5 | crand "crypto/rand"
6 | "math/rand"
7 | "time"
8 | )
9 |
10 | // OracleAES guesses whether a ciphertext has been encrypted with ECB mode (1) or not (0)
11 | // This only works if the plaintext contains one of
12 | // 1. 1 or more 48-byte blocks of the same character
13 | // 2. 2 or more identical 32-byte blocks of the same character
14 | // 3. 2 or more identical 32-byte blocks of any characters *but* separated by 16*n bytes (n=0,1,2,3...)
15 | // The test file contains an example of each
16 | // This solves http://cryptopals.com/sets/2/challenges/10/
17 | func OracleAES(ciphers [][]byte) []int {
18 | guesses := make([]int, len(ciphers))
19 | for i := range ciphers {
20 | if isAESECB(ciphers[i]) {
21 | guesses[i] = 1
22 | } else {
23 | guesses[i] = 0
24 | }
25 | }
26 | return guesses
27 | }
28 |
29 | func isAESECB(b []byte) bool {
30 | if similarBlocks(string(b)) > 0 {
31 | return true
32 | }
33 | return false
34 | }
35 |
36 | // generateCiphertexts accepts a plaintext b and generates ciphertexts based on this procedure
37 | // 1. Prefixes 5-20 random bytes
38 | // 2. Appends PKCS#7 padding
39 | // 3. Generates a random 16-byte key to encrypt it with
40 | // 4. Encrypts with the plaintext AES-ECB or AES-CBC, depending on the flip of a coin (rand.Intn(2))
41 | // All ciphertexts and the result of each coin flip is returned
42 | func generateCiphertexts(b []byte) ([][]byte, []int) {
43 | rand.Seed(time.Now().UnixNano())
44 |
45 | ciphers := make([][]byte, 10)
46 | coinflips := make([]int, 10)
47 | iv := make([]byte, aes.BlockSize)
48 |
49 | for i := range ciphers {
50 | p := getPlaintext(b)
51 | coin := rand.Intn(2)
52 | if coin == 1 {
53 | ecbEnc.CryptBlocks(p, p)
54 | } else {
55 | crand.Read(iv)
56 | cbcEnc.(ivSetter).SetIV(iv)
57 | cbcEnc.CryptBlocks(p, p)
58 | }
59 | ciphers[i] = p
60 | coinflips[i] = coin
61 | }
62 | return ciphers, coinflips
63 | }
64 |
65 | // prepends 5-20 random bytes and appends pkcs#7 padding
66 | func getPlaintext(b []byte) []byte {
67 | prefix := randbytes(rand.Intn(16) + 5)
68 | p := make([]byte, len(prefix), len(b)+20)
69 | copy(p, prefix)
70 | p = append(p, b...)
71 | p = PadPKCS7(p, aes.BlockSize)
72 | return p
73 | }
74 |
75 | func randbytes(n int) []byte {
76 | b := make([]byte, n)
77 | crand.Read(b)
78 | return b
79 | }
80 |
81 | // randbytes generates an byte slice of length n, filled with random bytes
82 | // n should be greater than 3
83 | // This function is deprecated, replaced with a function that uses crypto/rand instead of math/rand
84 | func randbytesDeprecated(n int) []byte {
85 | pad := n - (n % 4)
86 | b := make([]byte, n+pad)
87 | if n < 4 {
88 | return b
89 | }
90 | for i := 0; i < n; i += 4 {
91 | r := rand.Uint32()
92 | b[i] = byte(r >> 24)
93 | b[i+1] = byte(r >> 16 & 0xff)
94 | b[i+2] = byte(r >> 8 & 0xff)
95 | b[i+3] = byte(r & 0xff)
96 | }
97 | return b[0:n]
98 | }
99 |
--------------------------------------------------------------------------------
/matasano/14.5-break_ecb_moderate.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "math/rand"
6 |
7 | "github.com/nindalf/crypto/aes"
8 | )
9 |
10 | var numBytes = rand.Intn(40)
11 |
12 | // a function that produces: AES-128-ECB(random-text-of-fixed-length || b || unknown-string, random-key)
13 | func oraclemoderate(b []byte) []byte {
14 | plaintext := []byte("Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK")
15 | dec := make([]byte, (3*len(plaintext))/4)
16 | DecodeBase64(dec, plaintext)
17 | r := randbytes(numBytes)
18 | r = append(r, b...)
19 | r = append(r, dec...)
20 | r = PadPKCS7(r, aes.BlockSize)
21 | ecbEnc.CryptBlocks(r, r)
22 | return r
23 | }
24 |
25 | var oraclehelper func([]byte) []byte
26 |
27 | func setupHelper() {
28 | var frontpad, cutblock int
29 | b := make([]byte, 64, 79)
30 | e := oraclemoderate(b)
31 | for similarBlocks(string(e)) < 4 {
32 | b = append(b, byte(0))
33 | e = oraclemoderate(b)
34 | frontpad++
35 | }
36 | s := string(e)
37 | for i := 0; i < len(s)-64; i += aes.BlockSize {
38 | // aes.BlockSize = 16
39 | if s[i:i+16] == s[i+16:i+32] && s[i:i+16] == s[i+32:i+48] && s[i:i+16] == s[i+48:i+64] {
40 | cutblock = i / 16
41 | }
42 | }
43 | oraclehelper = func(x []byte) []byte {
44 | t := make([]byte, frontpad, len(x)+frontpad)
45 | t = append(t, x...)
46 | t = oraclemoderate(t)
47 | return t[cutblock*16 : len(t)]
48 | }
49 | }
50 |
51 | // BreakECBModerate decrypts a ciphertext received from the oracle function (defined above)
52 | // It does so by repeated calls to the oracle
53 | // This solves http://cryptopals.com/sets/2/challenges/14/
54 | func BreakECBModerate() []byte {
55 | setupHelper()
56 | chosens := genChosenCiphersEasy()
57 | var decrypted bytes.Buffer
58 | previous := make([]byte, aes.BlockSize, len(chosens[0]))
59 | for i := 0; i < len(chosens[0]); i += aes.BlockSize {
60 | previous = decrypt16bytesModerate(chosens, previous, i)
61 | decrypted.Write(previous)
62 | }
63 | return decrypted.Bytes()
64 | }
65 |
66 | func decrypt16bytesModerate(chosens [][]byte, previous []byte, index int) []byte {
67 | decrypted := make([]byte, 0, aes.BlockSize)
68 | for i := len(chosens) - 1; i >= 0; i-- {
69 | previous = previous[1:len(previous)]
70 | dec := decryptbyteModerate(chosens[i][index:index+aes.BlockSize], previous)
71 | previous = append(previous, dec)
72 | decrypted = append(decrypted, dec)
73 | }
74 | return decrypted
75 | }
76 |
77 | func decryptbyteModerate(chosen, previous []byte) byte {
78 | previous = append(previous, byte(0))
79 | for i := 0; i < 255; i++ {
80 | previous[aes.BlockSize-1] = byte(i)
81 | if bytes.Equal(oraclehelper(previous)[0:aes.BlockSize], chosen) {
82 | return byte(i)
83 | }
84 | }
85 | return 0
86 | }
87 |
88 | func genChosenCiphersModerate() [][]byte {
89 | chosens := make([][]byte, 0, aes.BlockSize)
90 | prefix := make([]byte, 0, aes.BlockSize-1)
91 | chosens = append(chosens, oraclehelper(prefix))
92 | var x byte
93 | for i := 0; i < aes.BlockSize-1; i++ {
94 | prefix = append(prefix, x)
95 | chosens = append(chosens, oraclehelper(prefix))
96 | }
97 | return chosens
98 | }
99 |
--------------------------------------------------------------------------------
/matasano/13-ecb_cut_paste.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "math/rand"
7 | "strconv"
8 | "strings"
9 | )
10 |
11 | var (
12 | uid = rand.Intn(100000)
13 | keys13 = []string{"email", "uid", "role"}
14 | )
15 |
16 | // CreateAdminProfile creates a profile where the role is "admin"
17 | // It does so by repeated calls to the profilefor() oracle
18 | // Assumptions made: email will be the first param, role will be the last.
19 | // This solves http://cryptopals.com/sets/2/challenges/13
20 | func CreateAdminProfile() []byte {
21 | frontpad := 16 - len("email=") // assumption that email will be the first parameter
22 | chosen := newRole(frontpad)
23 | b := encryptProfile(profilefor(chosen))
24 |
25 | encryptedadmin := make([]byte, 16)
26 | copy(encryptedadmin, b[16:32])
27 |
28 | blen := len(b)
29 | for len(b) == blen {
30 | chosen = "x" + chosen
31 | b = encryptProfile(profilefor(chosen))
32 | }
33 |
34 | fakeemail := newEmail(len(chosen) + len("user"))
35 | b = encryptProfile(profilefor(fakeemail))
36 | copy(b[len(b)-16:len(b)], encryptedadmin) // assumption that role will be the last parameter
37 |
38 | return b
39 | }
40 |
41 | func newRole(frontpad int) string {
42 | role := []byte("admin")
43 | role = PadPKCS7(role, 16)
44 | pad := make([]byte, frontpad)
45 | pad = append(pad, role...)
46 | return string(pad)
47 | }
48 |
49 | func newEmail(n int) string {
50 | email := "AChosenEmailOfAppropriateLengthOnADomainWeControl"
51 | domain := "@nindalf.com"
52 | return email[0:n-len(domain)] + domain
53 | }
54 |
55 | func profilefor(email string) string {
56 | profile := map[string]string{"email": email, "uid": strconv.Itoa(uid), "role": "user"}
57 | // return kvencoder(profile)
58 | return kvencoderBad(profile, keys13)
59 | }
60 |
61 | func encryptProfile(profile string) []byte {
62 | b := []byte(profile)
63 | b = PadPKCS7(b, 16)
64 | ecbEnc.CryptBlocks(b, b)
65 | return b
66 | }
67 |
68 | func decryptProfile(profile []byte) map[string]string {
69 | ecbDec.CryptBlocks(profile, profile)
70 | profile, _ = StripPKCS7(profile)
71 | return kvdecoder(string(profile))
72 | }
73 |
74 | func kvencoder(params map[string]string) string {
75 | var b bytes.Buffer
76 | for k, v := range params {
77 | if strings.ContainsAny(k, "&=") || strings.ContainsAny(v, "&=") || k == "" || v == "" {
78 | continue
79 | }
80 | b.WriteString(fmt.Sprintf("%s=%s&", k, v))
81 | }
82 | result := b.String()
83 | return result[0 : len(result)-1]
84 | }
85 |
86 | func kvencoderBad(params map[string]string, keys []string) string {
87 | var b bytes.Buffer
88 | for _, k := range keys {
89 | v := params[k]
90 | if strings.ContainsAny(k, "&=") || strings.ContainsAny(v, "&=") || k == "" || v == "" {
91 | continue
92 | }
93 | b.WriteString(fmt.Sprintf("%s=%s&", k, v))
94 | }
95 | result := b.String()
96 | return result[0 : len(result)-1]
97 | }
98 |
99 | func kvdecoder(params string) map[string]string {
100 | result := make(map[string]string)
101 | pairs := strings.Split(params, "&")
102 | for i := range pairs {
103 | pair := strings.Split(pairs[i], "=")
104 | result[pair[0]] = pair[1]
105 | }
106 | return result
107 | }
108 |
--------------------------------------------------------------------------------
/stanford/0-discrete-probability.md:
--------------------------------------------------------------------------------
1 | Discrete Probability
2 | ===
3 |
4 | In the old days crypto didn't have proofs and it sucked. Modern cryptography has been developed as a rigorous science and new methods need to be accompanied by a proof of security. For this we need discrete probability.
5 |
6 | Further reading - https://en.wikibooks.org/wiki/High_School_Mathematics_Extensions/Discrete_Probability
7 |
8 | Mathematical symbols copied from [wiki page](https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode). Some symbols used are ∑ ∏ ∀ ∈ (belongs to) ∉ ⊆ ∪ ⨁ ∄ ∃ ϵ (epsilon) ≈ ⟘ 𝜑
9 |
10 | #### Basics
11 |
12 | * Defined over U: finite set (eg. U={00, 01, 10, 11})
13 | * Probability distribution P over U is a function P:U -> [0,1]
14 | * P assigns every element in U a number between 0 and 1 such that ∑P(x) = 1 (x ∈ U). The number assigned to that element is called the probability of of that element.
15 | * Since U is finite, we can write down the whole set along with corresponding probabilities and represent it as a vector
16 |
17 | #### Some distributions
18 |
19 | * Uniform distribution - all elements of set have equal probability
20 | * Point distribution - one element has probability 1. Rest have probability 0
21 |
22 | #### Event
23 |
24 | * A subset of the universe U, ie, A ⊆ U
25 | * The probability of it occurring is between [0, 1]
26 | * The union bound - Probability that either event 1 (A1) occurs OR event 2 (A2) occurs is by union - Pr[A1 ∪ A2] <= Pr[A1] + Pr[A2]
27 | * If the intersection of A1 and A2 is null, ie the 2 events are disjoint, ie, A1 ∩ A2 = ϕ, then Pr[A1 ∪ A2] = Pr[A1] + Pr[A2]
28 | * Independence - Events A1 and A2 are independent if one event happening tells you nothing about whether the other event occurred. Probability of both events happening = Pr[A1 and A2] = Pr[A1] * Pr[A2]
29 |
30 | #### Random variables
31 |
32 | * A random variable X is a function X:U -> V. X is a function, U is the universe and it maps into V, where it takes its values.
33 | * Example. X: {0,1}^n -> {0,1}. Universe is all n-bit binary strings and it maps into a 1 bit value. Here the function could be lsb(y)
34 | * More generally: rand var X induces a distribution on V. Pr[X=v] := Pr[X^-1 (v)]
35 | * Independence - random variables X and Y are independent if ∀ a, b ∈ V: Pr[X=a and Y=b] = Pr[X=a] * Pr[Y=b]
36 | * Example of independent RV - XOR ⨁. If X is a random variable over {0,1}^n and Y is an independent uniform random variable over {0,1}^n, then the result Z is a uniform random variable on {0,1}^n. This theorem is important for cryptography
37 |
38 | #### Uniform random variable
39 |
40 | * Let U = {0,1}^n
41 | * r is a uniform random variable such that Pr[r=a] = 1/|U| where a ∈ U (|U| is the size of U)
42 |
43 | #### Randomized algorithms
44 |
45 | * Deterministic algorithm: y <- A(m). We get the same output every time we run the function over the input message m.
46 | * Randomized algorithm: y <- A(m, r) where r is a random variable. Every time we run y, a new r is generated and we get a different output.
47 | * If you think about it, the second y is a random variable itself. An example of this would be encrypting a message over a key.
48 |
49 | #### The Birthday Paradox
50 |
51 | Let r1, .., rn ∈ U be n independent, indentically distributed random variables
52 |
53 | If you sample n = 1.2 * sqrt(|U|) times, then the probability that there exists two indices i, j such that ri = rj is greater than half.
54 |
55 | Example. Sample n= 2^64 elements from the set of all 2^128 length messages. Two sampled messages are likely to be the same. The probability converges very quickly to 1 for n greater than sqrt(|U|)
56 |
57 | For 2 people sharing the same birthday, the probability is 0.5 for n=23 people.
58 |
59 | 
60 |
--------------------------------------------------------------------------------
/matasano/06-data.txt:
--------------------------------------------------------------------------------
1 | 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
65 |
--------------------------------------------------------------------------------
/matasano/07-data.txt:
--------------------------------------------------------------------------------
1 | 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
65 |
--------------------------------------------------------------------------------
/matasano/10-data.txt:
--------------------------------------------------------------------------------
1 | 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
65 |
--------------------------------------------------------------------------------
/aes/aes_test.go:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import (
4 | "crypto/rand"
5 | "testing"
6 | )
7 |
8 | func TestKeyExpansion(t *testing.T) {
9 | key := "YELLOW SUBMARINE"
10 | expandedkey := []uint32{0x594f5552, 0x45574249, 0x4c204d4e, 0x4c534145, 0x632c792b,
11 | 0x6a3d7f36, 0x22024f01, 0x4c1f5e1b, 0x6448311a, 0x162b5462, 0x8d8fc0c1, 0xbda2fce7,
12 | 0xca82b3a9, 0x6e451173, 0x19965697, 0x1fbd41a6, 0x4dcf7cd5, 0xe6a3b2c1, 0x3dabfd6a,
13 | 0xcc713096, 0x25ea9643, 0xe447f534, 0xad06fb91, 0xcfbe8e18, 0x1df76122, 0x6522d7e3,
14 | 0x6fd6c, 0xd56be5fd, 0x4cbbdaf8, 0x3517c023, 0x5452afc3, 0x462dc835, 0xea518b73,
15 | 0x1b0cccef, 0xc2903ffc, 0x72ae2d7, 0x2e7ff487, 0xaba76b84, 0xcc5c639f, 0x88a24097,
16 | 0x4738cc4b, 0x70d7bc38, 0x44187be4, 0x9f3d7dea}
17 | actual := keyExpansion([]byte(key))
18 | for i := range expandedkey {
19 | if expandedkey[i] != actual[i] {
20 | t.Fatalf("Expanded key for %s is incorrect\n", key)
21 | }
22 | }
23 | }
24 |
25 | func TestEncryptDecrypt(t *testing.T) {
26 | key := "PURPLE SIDEKICKS"
27 | expkey := keyExpansion([]byte(key))
28 | enc := func(state []uint32) {
29 | encrypt(state, expkey)
30 | }
31 | dec := func(state []uint32) {
32 | decrypt(state, expkey)
33 | }
34 | testForwardAndInverse(t, enc, dec, "Encrypt")
35 | }
36 |
37 | // test vectors from https://en.wikipedia.org/wiki/Rijndael_mix_columns#Test_vectors_for_MixColumns.28.29.3B_not_for_InvMixColumns
38 | func TestMixColumns(t *testing.T) {
39 | input := []uint32{0xdbf201c6, 0x130a01c6, 0x532201c6, 0x455c01c6}
40 | expected := []uint32{0x8e9f01c6, 0x4ddc01c6, 0xa15801c6, 0xbc9d01c6}
41 | testOperation(t, mixColumns, input, expected, "MixColumns")
42 | }
43 |
44 | // test vectors reversed from TestMixColumns
45 | func TestInvMixColumns(t *testing.T) {
46 | input := []uint32{0x8e9f01c6, 0x4ddc01c6, 0xa15801c6, 0xbc9d01c6}
47 | expected := []uint32{0xdbf201c6, 0x130a01c6, 0x532201c6, 0x455c01c6}
48 | testOperation(t, invMixColumns, input, expected, "InvMixColumns")
49 | }
50 |
51 | func TestBothMixColumns(t *testing.T) {
52 | testForwardAndInverse(t, mixColumns, invMixColumns, "MixColumns")
53 | }
54 |
55 | func TestShiftRows(t *testing.T) {
56 | input := []uint32{0x8e9f01c6, 0x4ddc01c6, 0xa15801c6, 0xbc9d01c6}
57 | expected := []uint32{0x8e9f01c6, 0xdc01c64d, 0x01c6a158, 0xc6bc9d01}
58 | testOperation(t, shiftRows, input, expected, "ShiftRows")
59 | }
60 |
61 | func TestInvShiftRows(t *testing.T) {
62 | input := []uint32{0x8e9f01c6, 0x4ddc01c6, 0xa15801c6, 0xbc9d01c6}
63 | expected := []uint32{0x8e9f01c6, 0xc64ddc01, 0x01c6a158, 0x9d01c6bc}
64 | testOperation(t, invShiftRows, input, expected, "InvShiftRows")
65 | }
66 |
67 | func TestBothShiftRows(t *testing.T) {
68 | testForwardAndInverse(t, shiftRows, invShiftRows, "ShiftRows")
69 | }
70 |
71 | func TestSubBytes(t *testing.T) {
72 | input := []uint32{0x8e9ff1c6, 0x4ddce1c7, 0xa158d1c8, 0xbc9dc1c9}
73 | expected := []uint32{0x19dba1b4, 0xe386f8c6, 0x326a3ee8, 0x655e78dd}
74 | testOperation(t, subBytes, input, expected, "SubBytes")
75 | }
76 |
77 | func TestInvSubBytes(t *testing.T) {
78 | input := []uint32{0x19dba1b4, 0xe386f8c6, 0x326a3ee8, 0x655e78dd}
79 | expected := []uint32{0x8e9ff1c6, 0x4ddce1c7, 0xa158d1c8, 0xbc9dc1c9}
80 | testOperation(t, invSubBytes, input, expected, "SubBytes")
81 | }
82 |
83 | func TestBothSubBytes(t *testing.T) {
84 | testForwardAndInverse(t, subBytes, invSubBytes, "Substitution")
85 | }
86 |
87 | func TestTranspose(t *testing.T) {
88 | input := []uint32{0x8e9f01c6, 0x4ddc01c6, 0xa15801c6, 0xbc9d01c6}
89 | expected := []uint32{0x8e4da1bc, 0x9fdc589d, 0x01010101, 0xc6c6c6c6}
90 | testOperation(t, transpose, input, expected, "Transpose")
91 | }
92 |
93 | func TestTransposeInverse(t *testing.T) {
94 | testForwardAndInverse(t, transpose, transpose, "Transpose")
95 | }
96 |
97 | func testOperation(t *testing.T, operation func([]uint32), input, expected []uint32, name string) {
98 | operation(input)
99 | for i := range input {
100 | if input[i] != expected[i] {
101 | t.Fatalf("%s failed at index %d. Expected - 0x%x, Received - 0x%x", name, i, expected[i], input[i])
102 | }
103 | }
104 | }
105 |
106 | func testForwardAndInverse(t *testing.T, forward, inverse func([]uint32), name string) {
107 | input, expected := make([]uint32, 4), make([]uint32, 4)
108 | b := make([]byte, 16)
109 | for i := 0; i < 10; i++ {
110 | rand.Read(b)
111 | pack(input, b)
112 | pack(expected, b)
113 |
114 | forward(input)
115 | inverse(input)
116 | for j := range input {
117 | if input[j] != expected[j] {
118 | t.Fatalf("%s forward and inverse failed. Expected - %d, Received %d", name, expected[j], input[j])
119 | }
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/matasano/14-break_aes_ecb_hard.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "errors"
6 | "fmt"
7 | "math/rand"
8 | "time"
9 |
10 | "github.com/nindalf/crypto/aes"
11 | )
12 |
13 | // a function that produces: AES-128-ECB(random-text-of-random-length || b || unknown-string, random-key)
14 | func oraclehard(b []byte) []byte {
15 | plaintext := []byte("Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK")
16 | dec := make([]byte, (3*len(plaintext))/4)
17 | DecodeBase64(dec, plaintext)
18 | rand.Seed(time.Now().UnixNano())
19 | r := randbytes(rand.Intn(40))
20 | r = append(r, b...)
21 | r = append(r, dec...)
22 | r = PadPKCS7(r, 16)
23 | ecbEnc.CryptBlocks(r, r)
24 | return r
25 | }
26 |
27 | // BreakECBHard decrypts a ciphertext received from the oracle function (defined above)
28 | // It does so by repeated calls to the oracle
29 | // This solves http://cryptopals.com/sets/2/challenges/14/
30 | func BreakECBHard() []byte {
31 | chosens, previous := genChosenCiphersHard()
32 | var decrypted bytes.Buffer
33 | for i := 0; i < 160; i += aes.BlockSize {
34 | previous = decrypt16bytesHard(chosens, previous, i)
35 | fmt.Println(string(previous))
36 | decrypted.Write(previous) // reverse
37 | }
38 | return decrypted.Bytes()
39 | }
40 |
41 | func decrypt16bytesHard(chosens [][]byte, previous []byte, index int) []byte {
42 | decrypted := make([]byte, aes.BlockSize)
43 | for i := aes.BlockSize - 1; i >= 0; i-- {
44 | previous = previous[0 : len(previous)-1]
45 | l := len(chosens[i])
46 | dec := decryptbyteHard(chosens[i][l-index-32:l-index-16], previous)
47 | fmt.Print(dec)
48 | previous = append([]byte{dec}, previous...)
49 | decrypted[i] = dec
50 | }
51 | return decrypted
52 | }
53 |
54 | func decryptbyteHard(chosen, previous []byte) byte {
55 | previous = append([]byte{0}, previous...)
56 | temp := make([]byte, aes.BlockSize)
57 | for i := 0; i < 255; i++ {
58 | copy(temp, previous)
59 | temp[0] = byte(i)
60 | temp, _ := encryptBlock(temp)
61 | if bytes.Equal(temp, chosen) {
62 | return byte(i)
63 | }
64 | }
65 | return 0
66 | }
67 |
68 | // generates chosen ciphertexts and the last decrypted block
69 | func genChosenCiphersHard() ([][]byte, []byte) {
70 | chosens := make([][]byte, 0, aes.BlockSize)
71 | existing := make(map[string]int)
72 | chosen := make([]byte, 48)
73 | var i int
74 | for len(chosens) != aes.BlockSize {
75 | b := oraclehard(chosen)
76 | lastblock := string(b[len(b)-16 : len(b)])
77 | if _, ok := existing[lastblock]; ok == false {
78 | cutoff := getSimilarityCutoff(b)
79 | chosens = append(chosens, b[cutoff:len(b)])
80 | existing[lastblock] = i
81 | i++
82 | }
83 | }
84 | orderedChosens := make([][]byte, aes.BlockSize)
85 | guessed, temp := make([]byte, 0, 16), make([]byte, 16)
86 | var err error
87 | for i := 15; i > 0; i-- {
88 | bc := make([]byte, 1, 16)
89 | bc = append(bc, guessed...)
90 | bc = PadPKCS7(bc, 16)
91 | for j := 0; j < 256; j++ {
92 | bc[0] = byte(j)
93 | copy(temp, bc)
94 | temp, err = encryptBlock(temp)
95 | if err != nil {
96 | fmt.Printf("Trouble encrypting %v, %s\n", bc, err)
97 | }
98 |
99 | if index, ok := existing[string(temp)]; ok {
100 | orderedChosens[i] = chosens[index]
101 | chosens[index] = make([]byte, 0)
102 | t := make([]byte, 1, 16)
103 | t[0] = byte(j)
104 | guessed = append(t, guessed...)
105 | break
106 | }
107 | }
108 | }
109 | for i := range chosens {
110 | if len(chosens[i]) > 0 {
111 | orderedChosens[0] = chosens[i]
112 | }
113 | }
114 | fmt.Println(guessed)
115 | return orderedChosens, guessed
116 | }
117 |
118 | func getSimilarityCutoff(b []byte) int {
119 | s := string(b)
120 | for i := 0; i < len(s)-32; i += 16 {
121 | if s[i:i+16] == s[i+16:i+32] {
122 | return i + 32
123 | }
124 | }
125 | return 0
126 | }
127 |
128 | // encrypts a 16 byte block under the uknown key
129 | // its a little complicated to get a 16 byte block encrypted since we don't know where it will be
130 | func encryptBlock(b []byte) ([]byte, error) {
131 | if len(b) != 16 {
132 | return b, errors.New("incorrect length")
133 | }
134 | pad := make([]byte, 32)
135 | block := make([]byte, 0, 80)
136 | block = append(block, pad...)
137 | block = append(block, b...)
138 | block = append(block, pad...)
139 | enc := oraclehard(block)
140 | // if the pads are on the 16-byte boundaries, they will generate 4 similar blocks
141 | for similarBlocks(string(enc)) < 4 {
142 | enc = oraclehard(block)
143 | }
144 | s := string(enc)
145 | for i := 0; i < len(s)-80; i += 16 {
146 | if s[i:i+16] == s[i+16:i+32] && s[i:i+16] != s[i+32:i+48] && s[i:i+16] == s[i+48:i+64] && s[i:i+16] == s[i+64:i+80] {
147 | return []byte(s[i+32 : i+48]), nil
148 | }
149 | }
150 | return b, errors.New("couldn't find the encrypted block")
151 | }
152 |
--------------------------------------------------------------------------------
/matasano/01-hextobase64.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import "bytes"
4 |
5 | var base64enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
6 | var base64dec = map[byte]byte{'a': 26, 'A': 0,
7 | 'b': 27, 'B': 1, 'c': 28, 'C': 2, 'd': 29, 'D': 3,
8 | 'e': 30, 'E': 4, 'f': 31, 'F': 5, 'g': 32, 'G': 6,
9 | 'h': 33, 'H': 7, 'i': 34, 'I': 8, 'j': 35, 'J': 9,
10 | 'k': 36, 'K': 10, 'l': 37, 'L': 11, 'm': 38, 'M': 12,
11 | 'n': 39, 'N': 13, 'o': 40, 'O': 14, 'p': 41, 'P': 15,
12 | 'q': 42, 'Q': 16, 'r': 43, 'R': 17, 's': 44, 'S': 18,
13 | 't': 45, 'T': 19, 'u': 46, 'U': 20, 'v': 47, 'V': 21,
14 | 'w': 48, 'W': 22, 'x': 49, 'X': 23, 'y': 50, 'Y': 24,
15 | 'z': 51, 'Z': 25, '0': 52, '1': 53, '2': 54, '3': 55,
16 | '4': 56, '5': 57, '6': 58, '7': 59, '8': 60, '9': 61,
17 | '+': 62, '/': 63, '=': 0}
18 |
19 | var hexvals = []byte("0123456789abcdef")
20 |
21 | // Base64FromHex converts a hex string to a base64 encoded string
22 | // This solves http://cryptopals.com/sets/1/challenges/1/
23 | func Base64FromHex(hex []byte) []byte {
24 | return base64FromString(StringFromHex(hex))
25 | }
26 |
27 | // StringFromHex converts a hex encoded string to a byte-encoded one
28 | func StringFromHex(hex []byte) []byte {
29 | convert := func(hex []byte) byte {
30 | var sum int
31 | sum += bytes.Index(hexvals, hex[0:1]) * 16
32 | sum += bytes.Index(hexvals, hex[1:2]) * 1
33 | return byte(sum)
34 | }
35 | var b bytes.Buffer
36 | for i := 0; i < len(hex); {
37 | b.WriteByte(convert(hex[i : i+2]))
38 | i += 2
39 | }
40 | return b.Bytes()
41 | }
42 |
43 | func HexFromString(str []byte) []byte {
44 | convert := func(b byte) []byte {
45 | out := make([]byte, 2)
46 | out[1] = hexvals[b/16]
47 | out[0] = hexvals[b%16]
48 | return out
49 | }
50 | var b bytes.Buffer
51 | for i := 0; i < len(str); i++ {
52 | hex := convert(str[i])
53 | b.WriteByte(hex[1])
54 | b.WriteByte(hex[0])
55 | }
56 | return b.Bytes()
57 | }
58 |
59 | func base64FromString(b []byte) []byte {
60 | dst := make([]byte, maxEncodeLength(b))
61 | EncodeBase64(dst, b)
62 | return dst
63 | }
64 |
65 | func maxEncodeLength(b []byte) int {
66 | n := len(b)
67 | if n%3 == 0 {
68 | return (n / 3) * 4
69 | }
70 | return ((n / 3) + 1) * 4
71 | }
72 |
73 | // EncodeBase64 encodes a string to base64
74 | // This is my implementation, which is not that bad compared to the std lib implementation below
75 | func EncodeBase64(dst, src []byte) {
76 | var i, j int
77 | for i+2 < len(src) {
78 | encode4Base64Bytes(dst[j:j+4], src[i:i+3])
79 | i += 3
80 | j += 4
81 | }
82 | switch len(src[i:len(src)]) {
83 | case 2:
84 | src = padBase64(src, 1)
85 | encode4Base64Bytes(dst[j:j+4], src[i:i+3])
86 | dst[j+3] = 64 // equality symbol
87 | case 1:
88 | src = padBase64(src, 2)
89 | encode4Base64Bytes(dst[j:j+4], src[i:i+3])
90 | dst[j+3] = 64
91 | dst[j+2] = 64
92 | }
93 | for i := 0; i < len(dst); i++ {
94 | dst[i] = base64enc[dst[i]]
95 | }
96 | }
97 |
98 | func encode4Base64Bytes(dst, src []byte) {
99 | dst[0] = src[0] >> 2
100 | dst[1] = ((src[0] & ((1 << 2) - 1)) << 4) | (src[1] >> 4)
101 | dst[2] = ((src[1] & ((1 << 4) - 1)) << 2) | src[2]>>6
102 | dst[3] = (src[2] & ((1 << 6) - 1))
103 | }
104 |
105 | func padBase64(b []byte, n int) []byte {
106 | t := make([]byte, n)
107 | for _, l := range t {
108 | b = append(b, l)
109 | }
110 | return b
111 | }
112 |
113 | // copied from http://golang.org/src/encoding/base64/base64.go#L54
114 | var removeNewlinesMapper = func(r rune) rune {
115 | if r == '\r' || r == '\n' {
116 | return -1
117 | }
118 | return r
119 | }
120 |
121 | // DecodeBase64 decodes a base64 encoded string
122 | // Skips all the error checking done in the stdlib implementation.
123 | // It will panic on mangled input
124 | func DecodeBase64(dst, src []byte) int {
125 | src = bytes.Map(removeNewlinesMapper, src)
126 | var written int
127 | for len(src) > 0 {
128 | var b0, b1, b2 byte
129 |
130 | b0 = base64dec[src[0]] << 2
131 |
132 | b0 |= base64dec[src[1]] >> 4
133 | b1 = base64dec[src[1]] << 4
134 |
135 | b1 |= base64dec[src[2]] >> 2
136 | b2 = base64dec[src[2]] << 6
137 |
138 | b2 |= base64dec[src[3]]
139 |
140 | dst[0] = b0
141 | dst[1] = b1
142 | dst[2] = b2
143 |
144 | src = src[4:]
145 | dst = dst[3:]
146 | written += 3
147 | if len(src) == 4 {
148 | if src[3] == '=' {
149 | written--
150 | }
151 | if src[2] == '=' {
152 | written--
153 | }
154 | }
155 | }
156 | return written
157 | }
158 |
159 | // From the go std lib - http://golang.org/src/encoding/base64/base64.go#L71
160 | // I made a minor modification - removing encoder and using base64vals instead
161 |
162 | // Encode encodes src using the encoding enc, writing
163 | // EncodedLen(len(src)) bytes to dst.
164 | //
165 | // The encoding pads the output to a multiple of 4 bytes,
166 | // so Encode is not appropriate for use on individual blocks
167 | // of a large data stream. Use NewEncoder() instead.
168 | func Encode(dst, src []byte) {
169 | if len(src) == 0 {
170 | return
171 | }
172 |
173 | for len(src) > 0 {
174 | var b0, b1, b2, b3 byte
175 |
176 | // Unpack 4x 6-bit source blocks into a 4 byte
177 | // destination quantum
178 | switch len(src) {
179 | default:
180 | b3 = src[2] & 0x3F
181 | b2 = src[2] >> 6
182 | fallthrough
183 | case 2:
184 | b2 |= (src[1] << 2) & 0x3F
185 | b1 = src[1] >> 4
186 | fallthrough
187 | case 1:
188 | b1 |= (src[0] << 4) & 0x3F
189 | b0 = src[0] >> 2
190 | }
191 |
192 | // Encode 6-bit blocks using the base64 alphabet
193 | dst[0] = base64enc[b0]
194 | dst[1] = base64enc[b1]
195 | dst[2] = base64enc[b2]
196 | dst[3] = base64enc[b3]
197 |
198 | // Pad the final quantum
199 | if len(src) < 3 {
200 | dst[3] = '='
201 | if len(src) < 2 {
202 | dst[2] = '='
203 | }
204 | break
205 | }
206 |
207 | src = src[3:]
208 | dst = dst[4:]
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/stanford/6.2-public-key-encryption-diffie-hellman.md:
--------------------------------------------------------------------------------
1 | Public Key Encryption with Diffie-Hellman
2 | ===
3 |
4 | #### The Elgamal Public key system
5 |
6 | **Review: Diffie-Hellman protocol**
7 |
8 | * Fix a cyclic group G (eg. G = ℤN* or an elliptic curve) of order n
9 | * Fix a generator g in G (ie G = {1, g, g2, ..., gn-1})
10 | * Alice chooses a random a in {1, ..., n}. Bob chooses a random b in {1, ..., n}
11 | * Alice sends Bob A = ga. Bob sends Alice B = gb
12 | * Both raise what they have received to the power of the number they chose, yielding a shared secret gab
13 | * Attacker knows ℤN* , g, A and B, but finding gab from these is thought to be difficult.
14 |
15 | **Elgamal system in brief**
16 |
17 | * Alice chooses a random a in {1, ..., n}. Bob chooses a random b in {1, ..., n}
18 | * Alice sends Bob A = ga. Bob sends Alice B = gb. Both of these are considered public keys
19 | * Both raise what they have received to the power of the number they chose, yielding a shared secret gab
20 | * From gab they derive a symmetric key k, with which the encrypt messages
21 |
22 | **Elgamal system in detail**
23 |
24 | * G: a finite cyclic group of order n
25 | * (Es, Ds): symmetric authenticated encryption defined over (K, M, C)
26 | * H: G2 -> K a hash function
27 |
28 | Using these 3 we define a public key encryption system (Gen, E, D):
29 |
30 | * Key generation Gen:
31 | 1. Choose a random generator g in G. g <- {generators of G} (note: choosing a random generator instead of a fixed one makes it easier to prove security)
32 | 2. a <- ℤn
33 | 3. Output sk = a, pk = (g, h=ga)
34 | * Encryption
35 | 1. Bob chooses a random b in {1, ..., n}
36 | 2. u <- gb
37 | 3. v <- hb = gab
38 | 4. k <- H(u, v)
39 | 5. c <- Es(k, m)
40 | 6. Output (u, c)
41 | * Decryption
42 | 1. Alice computes v <- ua = gab
43 | 2. k <- H(u, v)
44 | 3. m <- Ds(k, c)
45 | 4. Output m
46 |
47 | **Performance**
48 |
49 | Exponentiation takes a few ms on a modern processor. Encryption involves 2 exponentiations - u <- gb, v <- hb and Decryption involves one v <- ua. Encryption is thus twice as slow. However, we can precompute the large tables gi and hi for i = 1,2,4,8,... which yields a speedup of 3x
50 |
51 | ---
52 |
53 | #### Elgamal security
54 |
55 | **Computational Diffie-Hellman assumption**
56 |
57 | * Consider a finite cyclic group G of order n.
58 | * Comp. DH (CDH) assumption holds in G if: gab cannot be calculated from g, ga, gb.
59 | * In other words, for all efficient algorithms A: Pr[A(g, ga, gb) = gab] < negligible where g <- {generators of G}, a,b <- ℤn
60 |
61 | This assumption is not ideal for analysing Elgamal. A stronger assumption is made instead.
62 |
63 | **Hash Diffie-Hellman assumption**
64 |
65 | * Consider a finite cyclic group G of order n.
66 | * Hash DH (HDH) assumption holds in G if: (g, ga, gb, H(gb, gab)) is computationally indistinguishable from (g, ga, gb, R) where g <- {generators of G}, a,b <- ℤn and R is a *truly random* key
67 |
68 | Why is this a stronger assumption? Consider the contra-positive. Suppose CDH is easy in the group G, then we can prove that HDH is easy in (G, H) ∀ H, |Im(H)| >= 2 (which is true for all practical hash functions). This is because if it was easy to compute gab we can simply compute H(gb, gab) and check if the sample is from the hash function or its truly random.
69 |
70 | **Semantic security under HDH**
71 |
72 | Can the attacker distinguish between (gb, Es(H(), m0)) and (gb, Es(H(), m1))? The output of H() is indistinguishable from a truly random key k. If it weren't, then that would break the Hash Diffie-Hellman assumption. Hence it is impossible to distinguish between the two.
73 |
74 | **Interactive Diffie-Hellman assumption**
75 |
76 | This is a stronger assumption. The game:
77 |
78 | 1. The challenger tells the attacker g, ga, gb
79 | 2. The attacker is allowed to submit queries (u1, v1) ∈ G2
80 | 3. For each query the challenger responds with 1 if u1a = v1 and 0 otherwise.
81 |
82 | There is no limit on the number of queries.
83 |
84 | IDH holds in G if: ∀ efficient A: Pr[A outputs gab] < negligible
85 |
86 | This is not an ideal assumption because it involves interactivity.
87 |
88 | **Chosen ciphertext security**
89 |
90 | Security theorem: If IDH holds in the group G, (Es, Ds) provides authenticated encryption, and H: G2 -> K is a "random oracle", then Elgamal is CCA secure
91 |
92 | Challenge: To prove CCA security using CDH. Options
93 |
94 | 1. use group G where CDH = IDH (aka bilinear groups constructed from elliptic curves)
95 | 2. change the Elgamal system
96 |
97 | **Twin Elgamal**
98 |
99 | * Key generation Gen:
100 | 1. g <- {generators of G}
101 | 2. a1, a2 <- ℤn
102 | 3. Output sk = (a1, a2), pk = (g, h1=ga1, h2=ga2)
103 | * Encryption
104 | 1. Bob chooses a random b in {1, ..., n}
105 | 2. u <- gb
106 | 3. k <- H(u, h1b, h2b)
107 | 4. c <- Es(k, m)
108 | 5. Output (u, c)
109 | * Decryption
110 | 1. k <- H(u, ua1, ua2)
111 | 2. m <- Ds(k, c)
112 | 3. Output m
113 |
114 | Security theorem: If CDH holds in the group G, (Es, Ds) provides authenticated encryption, and H: G3 -> K is a "random oracle", then Twin Elgamal is CCA secure
115 |
116 | Cost: One more exponentiation on each end.
117 |
118 | Can we build CCA-secure Elgamal without random oracles? Research is ongoing.
119 |
--------------------------------------------------------------------------------
/stanford/5-basic-key-exchange.md:
--------------------------------------------------------------------------------
1 | Basic Key Exchange
2 | ====
3 |
4 | #### Trusted 3rd parties
5 |
6 | * If there are n users in the world who all wish to communicate with each other.
7 | * Problem - They will require n! keys in total to do so, with every user storing n keys. Storing and using this many keys is not feasible.
8 | * Solution - A trusted 3rd party (TTP). Consider this toy protocol that is secure against eavesdropping.
9 | 1. Alice and Bob share their secret keys kA and kB with TTP.
10 | 2. Alice tells the TTP "I want a shared key with Bob".
11 | 3. TTP generates a random key kAB and sends E(kA, "A, B" || kAB) where (E, D) is a CPA secure cipher.
12 | 4. TTP also sends her the "ticket" - E(kB, "A, B" || kAB).
13 | 5. When communicating with Bob, she sends him the ticket, from which he can extract kAB.
14 | 6. Both now share a random key, unrelated to their actual secret keys. They can communicate. An eavesdropper has no way of knowing anything about kAB.
15 | * Pros of TTP
16 | 1. Simple, requiring only symmetric key encryption.
17 | 2. Symmetric key encryption is fast.
18 | * Cons of TTP
19 | 1. The TTP is needed for every exchange. If its offline, no communication is possible.
20 | 2. The TTP knows *all* session keys.
21 | 3. Vulnerable to replay attacks (an active attacker). Copy the bytes sent by Alice to Bob and send them again later.
22 | * Solution: Generate shared keys without an online TTP
23 |
24 | ---
25 |
26 | #### Merkle Puzzles
27 |
28 | It is possible to exchange keys without a TTP, using only block ciphers and hash functions (what we've learnt so far). It is inefficient, however.
29 |
30 | A puzzle is a problem that can be solved with some effort. For example, this puzzle:
31 |
32 | * E(k, m) is a symmetric cipher with k ∈ {0,1}128
33 | * puzzle(P) = E(P, "message") where P = 096 || b1...b32
34 | * Goal - finding P by trying all 232 possibilities.
35 |
36 | Procedure for the Merkle Puzzle
37 |
38 | 1. Alice generates 232 such puzzles in O(N) time.
39 | 2. For i = 1, ..., 232 choose random Pi ∈ {0,1}32 and xi, ki ∈ {0,1}128, set puzzlei <- E(096 || Pi, "Puzzle xi" || ki)
40 | 3. Alice sends all the puzzles to Bob, in a random order.
41 | 4. Bob randomly chooses one of the puzzles - puzzlej solves in at most 232 iterations (in O(N) time). He obtains (xj, kj)
42 | 5. He sends her xj and both use kj as the shared secret
43 |
44 | For an eavesdropper to break this, he needs to do O(N2) work. This is decent, but Alice needs to send a *lot* of data to Bob (on the order of gigabytes) and both need to do 232 work. In return, they get a scheme that can be broken in only 264 iterations, which is doable. It would be better to have security up to 2128 but asking Alice and Bob to do 264 work and also send that much data one way is impossible. Roughly speaking, such a quadratic gap is the best possible using symmetric ciphers/hash functions.
45 |
46 | That's why this isn't used in practice. However there is a good idea here - the participants had to some work to set up the scheme but the attacker had to do much more to break it.
47 |
48 | ---
49 |
50 | #### Diffie-Hellman protocol
51 |
52 | Goal - an exponential gap between the attacker's work and the participant's work.
53 |
54 | An informal explanation of Diffie-Hellman
55 |
56 | 1. Fix a large prime p (eg. 600 digits, or 2000 bits) forever
57 | 2. Fix an integer g in {0, 1, ...., p} forever
58 | 3. Alice chooses a in {0, 1, ...., p}. She computes A <- `ga (mod p)` efficiently and sends A to Bob
59 | 4. Bob does something similar with a number b. He computes B <- `gb (mod p)` and sends B to Alice
60 | 5. Alice computes Ba and Bob computes Ab. Both are equal to gab (mod p)
61 |
62 | **Security**: Its easy to see that Alice and Bob now share a value. What's difficult is proving that an eavesdropper (Eve) can't calculate that value (gab) despite knowing p, g, A, B. How hard is it to compute DHg(ga, gb) (mod p)?
63 |
64 | The best known algorithm to compute the DH function is the General Number Field Sieve, an algo used to factor integers larger than 100 digits. Its running time is sub-exponential - eO(cubrt(n)) (Exponential would be en). To ensure security, the modulus size should be 15360 for a 256-bit key, 3072 for a 128-bit key. 15360 is much too large to work with. Thus, DH is modified to work with Elliptic Curves, which would yield moduluses that are 2x the size of the keys.
65 |
66 | **Insecure against Man-in-the-Middle**: A MitM receives A from from Alice and sends A' to Bob. She receives B from Bob and sends Alice B'. Alice computes gab' and Bob computes ga'b. The MitM knows both. Alice sends a message encrypted with gab', Eve decrypts it and encrypts it with ga'b and sends it to Bob.
67 |
68 | ---
69 |
70 | #### Public Key Encryption
71 |
72 | A public key encryption system is a triple of algorithms (G, E, D).
73 |
74 | * G() - a randomized algorithm that outputs a key pair (pk, sk) (public key, secret key)
75 | * E(pk, m) - Encrypts the message m ∈ M under the private key and generates a ciphertext c ∈ C
76 | * D(sk, c) - Decrypts the ciphertext c ∈ C using the secret key to recover the message m or ⟘
77 |
78 | The triple is consistent. ∀(pk, sk) output by G and ∀ m ∈ M: D(sk, E(pk, m)) = m
79 |
80 | **Semantic security**:
81 |
82 | Chosen plaintext security makes no sense in a public key encryption system because the adversary already knows the public key. He can generate all the ciphertexts he wants. The adversary submits 2 plaintexts m0 and m1 of equal length and gets ciphertext c <- E(pk, mb). He needs to guess which message was encrypted.
83 |
84 | The system E = (G, E, D) is semantically secure against *eavesdropping* if the all efficient adversaries A cannot distinguish between the 2 experiments.
85 |
86 | AdvSS[A, E] = |Pr[Exp(0)=1] - Pr[Exp(1)=1]| < negligible
87 |
88 | Note that in public key encryption, one-time security implies many-time security because the adversary has the public key and can make as many ciphertexts as he pleases.
89 |
90 | **Key exchange**:
91 |
92 | 1. Alice sends Bob her public key
93 | 2. Bob encrypts a random 128-bit key with the public key and returns the ciphertext
94 | 3. Alice decrypts the ciphertext using her secret key, recovering the 128-bit key
95 |
96 | This is still vulnerable to a MitM attack.
97 |
--------------------------------------------------------------------------------
/stanford/5.5-number-theory.md:
--------------------------------------------------------------------------------
1 | Number theory
2 | ====
3 |
4 | Number theory is useful in building:
5 |
6 | * Key exchange protocols
7 | * Digital signatures
8 | * Public key encryption
9 |
10 | Further reading: A Computational Introduction to Number Theory and Algebra by Victor Shoup - [Free PDF](http://shoup.net/ntb/). In particular, chapters 1-4, 11, 12
11 |
12 | **Notation**:
13 |
14 | * N - positive integer
15 | * p - prime number
16 | * ℤN - {0, 1, ..., N-1}. Its a ring where addition and multiplication are done modulo-N
17 |
18 | **GCD**:
19 |
20 | * gcd(x, y) denotes the greatest common divisor of x and y.
21 | * For all integers x, y ∃ a, b s.t. a.x + b.y = gcd(x, y)
22 | * a, b can be found efficiently using the [Extended Euclid Algorithm](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers). Running time is O(n2) where n is the number of bits of N
23 | * If gcd(x, y) = 1, x and y are relatively prime
24 |
25 | **Modular inversion**:
26 |
27 | * The inverse of an element x in ℤN is y s.t. xy = 1 in ℤN
28 | * y is denotes by x-1
29 | * Lemma: x in ℤN has an inverse iff gcd(x, N) = 1
30 | * If x is relatively prime to N, use the equation from above a.x + b.N = 1 and find a, b using EEA. a is the inverse of x
31 | * It is trivial to solve linear equations a.x + b = 0 modulo N. x = -b.a-1
32 |
33 | **ℤN* **:
34 |
35 | * Set of invertible elements in ℤN
36 | * For a prime number, all elements in ℤN are relatively prime. Hence the |ℤN* | = p - 1 (0 not counted)
37 |
38 | ---
39 |
40 | #### Fermat and Euler
41 |
42 | **Fermat's little theorem**:
43 |
44 | * ∀ x ∈ ℤp* : xp-1 = 1 in ℤp
45 | * Example. p=5. 35-1 = 81 = 1 in ℤ5
46 | * Implication of FLT: xp-1 = 1 in ℤp => x.xp-2 = 1 => x-1 = xp-2 in ℤp. This method is less efficient than EEA and it only works modulo-primes.
47 | * Application of FLT: To generate a large prime, say of 1024 bits. Choose a random number p between 21024 and 21025-1. Test if 2p-1=1 in ℤp. If so, output p. This is a simple algo to generate primes, but there is a small probability (2-60) that a composite can be generated
48 |
49 | **Euler's work on ℤp* **:
50 |
51 | * It is a cyclic group, meaning that ∃ g ∈ ℤp* such that {1, g, g2, ..., gp-2} = (ℤp* ).
52 | * g is called the generator of ℤp* . Obviously, gp-1 = 1 from Fermat's theorem.
53 | * Not ever element in ℤp* is a generator
54 |
55 | **Order**:
56 |
57 | * For ∀ g ∈ ℤp* the set {1, g, g2, ...} is called the group generated by g.
58 | * The order of g ∈ ℤp* is the size of the group.
59 | * The order of g is the smallest number a > 0 s.t. ga = 1 in ℤp
60 |
61 | **Lagrange's theorem**:
62 |
63 | * ∀ g ∈ ℤp* : ordp(g) divides p-1.
64 | * Fermat's theorem follows directly from Lagrange's theorem.
65 |
66 | **Euler's generalisation of Fermat's theorem**:
67 | * For an integer N we define 𝜑(N) = |ℤN* | then 𝜑(p) = p-1.
68 | * Also - for a number that's a product of 2 primes N = p.q, 𝜑(N) = N - p - q + 1 (all the numbers in N minus the ones that aren't relatively prime to N, ie, divisible by p or divisible by q plus 1) = (p-1)(q-1)
69 | * Euler's theorem - ∀ x ∈ ℤN* : x𝜑(N) = 1 in ℤN. If N was prime p, we would simply write xp-1 = 1 in ℤp, which is FLT.
70 |
71 | ---
72 |
73 | #### Modular e'th roots:
74 |
75 | * For a linear equation a.x + b = 0 in ℤp, x = -b.a-1
76 | * Objective - solving higher degree polynomials - x2 - c = 0 and y3 - c = 0 and z37 - c = 0 in ℤp
77 | * Defintion - x ∈ ℤp s.t. xe = c in ℤp is called the e'th root of c
78 | * The e'th root doesn't always exist. When does it exist? Can we compute it efficiently?
79 | * Easy case: Suppose gcd(e, p-1) = 1. Then for all ∀ c ∈ ℤp* : e1/e exists in ℤp* and is easy to find.
80 | * Hard case:
81 | * Solving quadratic equations mod p: a.x2 + b.x + c = 0 in ℤp.
82 | * Solution: x = (-b +- sqrt(b2 - 4.a.c))/2.a in ℤp
83 | * Find (2.a)-1 using extended Euclid
84 | * Find sqrt(b2 - 4.a.c) using one of the square root algorithms
85 | * Computing c1/e in ℤN requires the factorisation of N, as far as we know
86 |
87 | ---
88 |
89 | #### Arithmetic Algorithms
90 |
91 | * To represent an n-bit integer on a 64-bit machine, it is broken into n/32 32-bit blocks. Some processors have 128-bit registers. The size of each block is kept half the size of the processor's register size so that the result after multiplication can fit in the register
92 | * Addition and subtraction of 2 n-bit integers - O(n)
93 | * Naive multiplication algorithm - O(n2). There are better algos - O(n1.585) [Karatsuba], O(n.lg(n)). Karatsuba's algo is preferred in most crypto libraries.
94 | * Division with remainder - O(n2)
95 | * Exponentiation - by Repeated squaring. To find g53, we calculate g2, g4, g8, g16 and then find g32.g16.g4.g1. To calculate gx, it takes O(log2(x)), so to calculate the entire exponent, it takes O(log(x).n2) <= O(n3)
96 |
97 | ---
98 |
99 | #### Intractable Problems:
100 |
101 | **Some easy problems**:
102 |
103 | * Given N and x in ℤN, find x-1 in ℤN
104 | * Given p and polynomial f(x) in ℤp[x] find x in ℤp such that f(x) = 0 in ℤp. Running time is linear in deg(f)
105 |
106 | **Intractable problems with primes**
107 |
108 | * Fix a prime p > 2 and g in ℤp* of order q
109 | * Consider the function x -> gx in ℤp
110 | * Now consider the inverse function Dlogg(gx) = x where x in {0, 1, ..., q-2}
111 | * This is extremely difficult to compute for large primes
112 | * In general, it doesn't have to apply only to the cyclic group ℤp* . We can define it more formally:
113 | * Consider a finite cyclic group G, where g is a generator of G. So G = {1, g, g2,..., gq-1}
114 | * We say DLOG is hard in G if for all efficient algorithms A, Prg<-G, x<-Zq[A(G, q, g, gx) = x] < negligible
115 | * Examples:
116 | * ℤp* for large p. Complexity exp(O(cubrt(n))).
117 | * elliptic curve groups mod p. Complexity exp(n/2)
118 |
119 | **Intractable problems with composites**
120 |
121 | * Consider the set of integers ℤ2(n) = {N = p.q where p,q are n-bit primes}
122 | * Problem 1: Factor a random N in ℤ2(n). This is considered hard for n = 2048
123 | * Problem 2: Given a polynomial f(x) where degree(f) > 1 and a random N in ℤ2(n) find x in ℤN such that f(x) = 0 in ℤN. (RSA is based on this)
124 |
125 | Testing the primality of a number is easy - both deterministic and randomised algorithms for this exist. Factorising a composite into its prime factors is more difficult.
126 |
--------------------------------------------------------------------------------
/aes/aes.go:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | import "crypto/cipher"
4 |
5 | const (
6 | // BlockSize is the size of each AES block
7 | BlockSize = 16
8 | )
9 |
10 | // cipherAES is a block cipher that implements the Advances Encryption Standard (AES)
11 | type cipherAES struct {
12 | expkey []uint32
13 | }
14 |
15 | // NewCipher creates a cipherAES object
16 | func NewCipher(key []byte) cipher.Block {
17 | expkey := keyExpansion(key)
18 | return cipherAES{expkey}
19 | }
20 |
21 | func (a cipherAES) Encrypt(dst, src []byte) {
22 | state := make([]uint32, 4)
23 | pack(state, src[0:BlockSize])
24 | encrypt(state, a.expkey)
25 | unpack(dst[0:BlockSize], state)
26 | }
27 |
28 | func (a cipherAES) Decrypt(dst, src []byte) {
29 | state := make([]uint32, 4)
30 | pack(state, src[0:BlockSize])
31 | decrypt(state, a.expkey)
32 | unpack(dst[0:BlockSize], state)
33 | }
34 |
35 | func (a cipherAES) BlockSize() int {
36 | return BlockSize
37 | }
38 |
39 | // decrypt decrypts the ciphertext in the state []uint32
40 | // under the expanded key expkey
41 | func decrypt(state, expkey []uint32) {
42 | keyi := len(expkey) - 4
43 | addRoundKey(state, expkey[keyi:keyi+4])
44 | keyi -= 4
45 | rounds := len(expkey)/4 - 2
46 | for i := 0; i < rounds; i++ {
47 | invShiftRows(state)
48 | invSubBytes(state)
49 | addRoundKey(state, expkey[keyi:keyi+4])
50 | keyi -= 4
51 | invMixColumns(state)
52 | }
53 | invShiftRows(state)
54 | invSubBytes(state)
55 | addRoundKey(state, expkey[keyi:keyi+4])
56 | }
57 |
58 | // encrypt encrypts the plaintext in the state []uint32
59 | // under the expanded key expkey
60 | func encrypt(state, expkey []uint32) {
61 | keyi := 0
62 | addRoundKey(state, expkey[keyi:keyi+4])
63 | keyi += 4
64 | rounds := len(expkey)/4 - 2
65 | for i := 0; i < rounds; i++ {
66 | subBytes(state)
67 | shiftRows(state)
68 | mixColumns(state)
69 | addRoundKey(state, expkey[keyi:keyi+4])
70 | keyi += 4
71 | }
72 | subBytes(state)
73 | shiftRows(state)
74 | addRoundKey(state, expkey[keyi:keyi+4])
75 | }
76 |
77 | func invShiftRows(state []uint32) {
78 | for i := 1; i < 4; i++ {
79 | state[i] = rotWordRight(state[i], uint(i))
80 | }
81 | }
82 |
83 | func shiftRows(state []uint32) {
84 | for i := 1; i < 4; i++ {
85 | state[i] = rotWordLeft(state[i], uint(i))
86 | }
87 | }
88 |
89 | func invSubBytes(state []uint32) {
90 | for i := range state {
91 | state[i] = invSubWord(state[i])
92 | }
93 | }
94 |
95 | func subBytes(state []uint32) {
96 | for i := range state {
97 | state[i] = subWord(state[i])
98 | }
99 | }
100 |
101 | func addRoundKey(state, key []uint32) {
102 | for i := range state {
103 | state[i] = state[i] ^ key[i]
104 | }
105 | }
106 |
107 | // based on https://en.wikipedia.org/wiki/Rijndael_mix_columns#InverseMixColumns
108 | func invMixColumns(state []uint32) {
109 | // a0-3 represent the bytes of a column
110 | // r0-3 are the transformed bytes
111 | calcInvMixCols := func(a0, a1, a2, a3 byte) (r0, r1, r2, r3 byte) {
112 | r0 = gMulBy14[a0] ^ gMulBy11[a1] ^ gMulBy13[a2] ^ gMulBy9[a3] // 14*a0 + 11*a1 + 13*a2 + 9*a3
113 | r1 = gMulBy9[a0] ^ gMulBy14[a1] ^ gMulBy11[a2] ^ gMulBy13[a3] // 9*a0 + 14*a1 + 11*a2 + 13*a3
114 | r2 = gMulBy13[a0] ^ gMulBy9[a1] ^ gMulBy14[a2] ^ gMulBy11[a3] // 13*a0 + 9*a1 + 14*a2 + 11*a3
115 | r3 = gMulBy11[a0] ^ gMulBy13[a1] ^ gMulBy9[a2] ^ gMulBy14[a3] // 11*a0 + 13*a1 + 9*a2 + 14*a3
116 | return
117 | }
118 | manipulateColumns(state, calcInvMixCols)
119 | }
120 |
121 | // based on https://en.wikipedia.org/wiki/Rijndael_mix_columns#MixColumns
122 | func mixColumns(state []uint32) {
123 | // a0-3 represent the bytes of a column
124 | // r0-3 are the transformed bytes
125 | calcMixCols := func(a0, a1, a2, a3 byte) (r0, r1, r2, r3 byte) {
126 | r0 = gMulBy2[a0] ^ gMulBy3[a1] ^ a2 ^ a3 // 2*a0 + 3*a1 + a2 + a3
127 | r1 = a0 ^ gMulBy2[a1] ^ gMulBy3[a2] ^ a3 // a0 + 2*a1 + 3*a2 + a3
128 | r2 = a0 ^ a1 ^ gMulBy2[a2] ^ gMulBy3[a3] // a0 + a1 + 2*a2 + 3*a3
129 | r3 = gMulBy3[a0] ^ a1 ^ a2 ^ gMulBy2[a3] // 3*a0 + a1 + a2 + 2*a3
130 | return
131 | }
132 | manipulateColumns(state, calcMixCols)
133 | }
134 |
135 | func manipulateColumns(state []uint32, calc func(byte, byte, byte, byte) (byte, byte, byte, byte)) {
136 | for i := uint(0); i < 4; i++ {
137 | // Read one column at a time
138 | var a0, a1, a2, a3 byte
139 | a0 = byte((state[0] >> ((3 - i) * 8)) & 0xff)
140 | a1 = byte((state[1] >> ((3 - i) * 8)) & 0xff)
141 | a2 = byte((state[2] >> ((3 - i) * 8)) & 0xff)
142 | a3 = byte((state[3] >> ((3 - i) * 8)) & 0xff)
143 |
144 | // calculate the transformed bytes
145 | r0, r1, r2, r3 := calc(a0, a1, a2, a3)
146 |
147 | // use this mask to clear the column of its existing value
148 | var mask uint32
149 | mask = 0xff << ((3 - i) * 8)
150 | mask = ^mask
151 |
152 | // set the column with the calculated values
153 | state[0] = (state[0] & mask) | (uint32(r0) << ((3 - i) * 8))
154 | state[1] = (state[1] & mask) | (uint32(r1) << ((3 - i) * 8))
155 | state[2] = (state[2] & mask) | (uint32(r2) << ((3 - i) * 8))
156 | state[3] = (state[3] & mask) | (uint32(r3) << ((3 - i) * 8))
157 | }
158 | }
159 |
160 | // KeyExpansion is based on https://en.wikipedia.org/wiki/Rijndael_key_schedule
161 | // I've tried to optimise for readability. For now it only supports expansion for 128-bit keys
162 | // nwords - number of words. Values are 4, 6, 8 for 128, 192 and 256-bit
163 | // rounds - number of rounds. Values are 10, 12, 14 for 128, 192 and 256-bit
164 | // each round requires a 4 word key. So we need 4(10+1), 4(12+1) and 4(14+1) words in the expanded key
165 | func keyExpansion(key []byte) []uint32 {
166 | nwords := 4
167 | rounds := 10
168 |
169 | expkeys := make([]uint32, 4*(rounds+1))
170 | // the key occupies the first nwords slots of the expanded key
171 | var i int
172 | for i < nwords {
173 | expkeys[i] = uint32(key[i*4])<<24 | uint32(key[i*4+1])<<16 | uint32(key[i*4+2])<<8 | uint32(key[i*4+3])
174 | i++
175 | }
176 |
177 | for i < 4*(rounds+1) {
178 | expkeys[i] = expkeys[i-1]
179 | expkeys[i] = rotWordLeft(expkeys[i], 1)
180 | expkeys[i] = subWord(expkeys[i])
181 | expkeys[i] ^= rcon(i/nwords - 1)
182 | expkeys[i] ^= expkeys[i-nwords]
183 |
184 | for j := 1; j <= 3; j++ {
185 | expkeys[i+j] = expkeys[i+j-1] ^ expkeys[i+j-nwords]
186 | }
187 |
188 | i += nwords
189 | }
190 | for j := 0; j < len(expkeys); j += 4 {
191 | transpose(expkeys[j : j+4])
192 | }
193 |
194 | return expkeys
195 | }
196 |
197 | func rcon(i int) uint32 {
198 | return uint32(powx[i]) << 24
199 | }
200 |
201 | // rotWordLeft rotates the word n bytes to the left.
202 | func rotWordLeft(input uint32, n uint) uint32 {
203 | return input>>(32-8*n) | input<<(8*n)
204 | }
205 |
206 | // rotWordRight rotates the word n bytes to the right.
207 | func rotWordRight(input uint32, n uint) uint32 {
208 | return input<<(32-8*n) | input>>(8*n)
209 | }
210 |
211 | func subWord(input uint32) uint32 {
212 | return uint32(sbox0[input>>24])<<24 |
213 | uint32(sbox0[input>>16&0xff])<<16 |
214 | uint32(sbox0[input>>8&0xff])<<8 |
215 | uint32(sbox0[input&0xff])
216 | }
217 |
218 | func invSubWord(input uint32) uint32 {
219 | return uint32(sbox1[input>>24])<<24 |
220 | uint32(sbox1[input>>16&0xff])<<16 |
221 | uint32(sbox1[input>>8&0xff])<<8 |
222 | uint32(sbox1[input&0xff])
223 | }
224 |
225 | func transpose(input []uint32) {
226 | var c0, c1, c2, c3 uint32
227 | for i := uint(0); i < 4; i++ {
228 | c0 |= (input[i] >> 24) << (8 * (3 - i))
229 | c1 |= (input[i] >> 16 & 0xff) << (8 * (3 - i))
230 | c2 |= (input[i] >> 8 & 0xff) << (8 * (3 - i))
231 | c3 |= (input[i] & 0xff) << (8 * (3 - i))
232 | }
233 | input[0] = c0
234 | input[1] = c1
235 | input[2] = c2
236 | input[3] = c3
237 | }
238 |
--------------------------------------------------------------------------------
/stanford/6.1-public-key-encryption-trapdoor.md:
--------------------------------------------------------------------------------
1 | Public Key Encryption from Trapdoor Permutations
2 | ===
3 |
4 | #### Constructions
5 |
6 | **Trapdoor functions**:
7 |
8 | * A trapdoor function form set X -> set Y is a triple of efficient algs (G, F, F-1)
9 | * G(): randomized alg outputs a key pair (pk, sk)
10 | * F(pk, .): det. alg. that defines a function X -> Y
11 | * F-1(sk, .): defines a function Y -> X that inverts F(pk, .)
12 | * ∀(pk, sk) output by G and ∀ x ∈ X: F-1(sk, F(pk, x)) = x
13 | * (G, F, F-1) is secure if F(pk, .) is a one-way function, ie, it can be evaluated, but not inverted without sk.
14 | * More formally, if the adversary is given pk and y <- F(pk, x), he will output x'. (G, F, F-1) is a secure TDF if for all efficient A: AdvOW[A, F] = Pr[x=x'] < negligible
15 |
16 | **Review of modular arithmetic**:
17 |
18 | * Let N = p.q where p, q are prime and p, q ≈ sqrt(N)
19 | * ℤN = {0, 1, ..., N-1}
20 | * ℤN* = invertible elements in ℤN
21 | * x ∈ ℤN <=> (implies and implied by) gcd(x, N) = 1
22 | * sizeof(ℤN* ) = 𝜑(N) = (p-1)(q-1) = N - p - q + 1
23 | * 𝜑(N) ≈ N - 2.sqrt(N) + 1 ≈ N. A random element in ℤN is *very likely* to be an element in ℤN* as well
24 | * Euler's theorem - ∀ x ∈ ℤN* : x𝜑(N) = 1 in ℤN
25 |
26 | **RSA Trapdoor permutation**:
27 |
28 | Used widely. TLS uses it for both certificates and key exchange. Also used for secure email and file systems.
29 |
30 | * G()
31 | 1. Choose random primes p, q ≈ 1024 bits
32 | 2. N = p.q
33 | 3. Choose integers e, d s.t. e.d = 1 (mod 𝜑(N))
34 | 4. e = encryption exponent, d = decryption exponent
35 | 5. Ouput pk = (N, e); sk = (N, d)
36 | * F(pk, x): ℤN* -> ℤN*
37 | 1. Plaintext = x
38 | 2. Ciphertext y = xe mod N
39 | * F-1(sk, y)
40 | 1. Plaintext = yd mod N = xed mod N = xk.𝜑(N) + 1= (x𝜑(N))k.x = x
41 |
42 | **RSA assumption**
43 |
44 | * RSA is a one-way permutation
45 | * For all efficient algs. A: Pr[A(N, e, y)=y1/e] < negligible
46 | * where p, q are 2 random n-bit primes, N <- p.q, y is randomly distributed in ℤN*
47 |
48 | **RSA public key encryption (ISO standard)**
49 |
50 | * (Es, Ds) symmetric encryption schemes providing authenticated encryption
51 | * H: ℤN -> K where K is the keyspace of (Es, Ds) (say SHA-256)
52 | * G(): Generate RSA params pk = (N, e); sk = (N, d)
53 | * E(pk, m)
54 | 1. Choose random x in ℤN
55 | 2. y <- RSA(x) = xe
56 | 3. k <- H(x),
57 | 4. c <- Es(k, m)
58 | 5. Output (y, c)
59 | * D(sk, (y, c))
60 | 1. Output Ds(H(RSA-1(y)), c)
61 |
62 | **Textbook RSA**
63 |
64 | * Generate RSA params pk = (N, e); sk = (N, d)
65 | * Encrypt c <- me
66 | * Decrypt cd -> m
67 |
68 | This is not semantically secure, because its deterministic
69 |
70 | => the RSA trapdoor permutation is not an encryption scheme
71 |
72 | Simple attack
73 |
74 | * Client says hello to the server
75 | * Server responds with (e, N)
76 | * Client chooses a random k and sends c = RSA(k) = ke
77 | * Eve knows e, N, and c
78 | * There is a 20% chance that k can be factorized into 2 numbers k1, k2
79 | * c = (k1.k2)e
80 | * Eve tries a meet-in-the-middle attack. c/k1e = k2e
81 | * A 64 bit key can be broken in ≈ 240 time, which is much better than exhaustive search - 264
82 |
83 | ---
84 |
85 | #### PKCS1
86 |
87 | **RSA public key encryption (in practice)**
88 |
89 | 1. System generates a symmetric key, of say 128-bits
90 | 2. Preprocessing is done on the key to expand it to 2048-bits
91 | 3. RSA is used to encrypt the expanded key
92 |
93 | **PKCS1 v1.5**:
94 |
95 | The expanded 2048-bit key from most significant bit to least:
96 |
97 | 1. 16 bits - 02, indicating PKCS1
98 | 2. ~1900 bits - random, but not containing the 16 bits ff
99 | 3. The 16 bits ff, indicating that the key follows
100 | 4. The key
101 |
102 | This was used in HTTPS. In 1998, Bleichenbacher found a vulnerability based on the fact that the server will tell you if the first two bytes are 02 or not.
103 |
104 | * Choose r ∈ ℤN. Compute c' <- rec = (r.PKCS1(m))e
105 | * Send c' and check the response
106 |
107 | After a million such requests, it is possible to recover m completely.
108 |
109 | Defense: if the first two bits are invalid, the server should continue with a random string generated at the start of the decryption. Eventually the session will break down because client and server have different secrets.
110 |
111 | **PKCS1 v2.0 - OAEP**:
112 |
113 | 
114 |
115 | 1. Pad message. Generate random bits such that len(message || pad || random) = 2047
116 | 2. Plaintext to encrypt = message ⨁ H(rand) || rand ⨁ G(message ⨁ H(rand))
117 |
118 | Security: Assuming that RSA is a trapdoor permutation and H, G are random oracles (ideal hash functions), RSA-OAEP (Optimal Asymmetric Encryption Padding) is CCA-secure. In practice, SHA-256 is used for H and G
119 |
120 | Implementation note: while writing the decryption function, it is very easy to make the mistake of leaking timing information, leading to an attack similar to Bleichenbacher's. Lesson: don't implement crypto yourself
121 |
122 | ---
123 |
124 | #### Is RSA a one-way function?
125 |
126 | To invert the RSA function without d, attacker must compute x from xe mod N. How hard is computing the e'th root modulo N? The best known algorithm is:
127 |
128 | 1. Factor N (hard)
129 | 2. Compute e'th roots modulo p and q (Easy).
130 | 3. Combine both using Chinese Remainder theorem to recover e'th root modulo N (Easy)
131 |
132 | We claim that there is no efficient algorithm for computing the e'th root modulo N, since there is weak evidence that if it existed, factoring N (step 1) would be easy.
133 |
134 | **How not to optimize RSA**
135 |
136 | * Speeding up decryption: exponentiation to the power d takes O(log(d)), so one (bad) way is to suggest small values of d, say 128-bit d instead of a 2000-bit d. Weiner'87 proved that if d < N0.25 then RSA is insecure. BD'98 proved it insecure for d < N0.292. Its conjectured that it is insecure for d < N0.5
137 | * Lesson - Imposing limitations on d is a bad idea.
138 |
139 | ---
140 |
141 | #### RSA in practice
142 |
143 | **Implementation**
144 |
145 | * To speed up RSA encryption use a small e.
146 | * Minimum value = 3. Recommended value = 65537 = 216 + 1 (needs 17 multiplications).
147 | * RSA is asymmetric - fast encryption/slow decryption. For e = 65537, decryption would take approx. 2000 multiplications
148 | * Decryption commonly uses the Chinese Remainder Theorem. This yields a speedup of 4x
149 | 1. xp = cd in ℤp is calculated
150 | 2. xq = cd in ℤq is calculated
151 | 3. The two are combined to get x = cd in ℤN
152 |
153 | **Attacks**
154 |
155 | * Timing attack - time taken for decryption (cd mod N) can expose d. Defense - make sure decryption time should be independent of the arguments
156 | * Power attack - measuring the power consumption of a smartcard while it is computing cd mod N can expose d
157 | * Faults attack - a computer error durign cd mod N can expose d. Defense - check the output by computing (cd)e mod N
158 | 1. xp is calculated correctly, but because of a rare processor error, xq is not
159 | 2. The output is x', rather than x
160 | 3. x' = cd in ℤp but x' != cd in ℤq
161 | 4. => x'e = c in ℤp but x'e != c in ℤq
162 | 5. => gcd(x'e - c, N) = p, meaning a factor of N is now known
163 | 6. It is now possible to compute 𝜑(N) and break RSA, all from a single mistake.
164 | * Poor key generation - many firewalls create a key-pair at startup, when entropy is low. The first prime p is thus common across many such instances. q would be random, since its generated a few ms later. But if you have 2 public keys with a common p, its possible to do gcd(N1, N2) to recover p and from there recover q. Defense - Make sure the random number generator is properly seeded.
165 |
--------------------------------------------------------------------------------
/stanford/4.5-odds-and-ends.md:
--------------------------------------------------------------------------------
1 | Odds and Ends
2 | ===
3 |
4 | Details related to symmetric encryption not covered in the previous chapters
5 |
6 | #### Key Derivation Functions (KDFs)
7 |
8 | * We need multiple keys - a MAC key, and encryption key etc.
9 | * To generate more keys given a uniform source key SK, we feed it to a PRF F in this manner:
10 | * KDF(SK, CTX, L) = F(SK, (CTX || 0)) || F(SK, (CTX || 1)) || ... || F(SK, (CTX || L))
11 | * CTX is a variable that uniquely identifies the application. Even if multiple applications on a system sample the same source key, they will end up with different expanded keys.
12 |
13 | **Problem**: PRFs are only pseudo random if the input k is uniform in K. The source key might not be uniform if
14 |
15 | * Key exchange protocol was used. Such a key might be uniform in a subset of K
16 | * A hardware RNG was used and it might produce biased output
17 |
18 | **Solution**: Extract-then-Expand paradigm.
19 |
20 | * A pseudo-random key is derived from the source key.
21 | * An extractor takes an input that may not be uniform and generates an output that is uniform (or indistinguishable from uniform) over the key space.
22 | * The extractor uses a salt - a fixed, non-secret string chosen at random
23 | * Expand k as before
24 |
25 | **Examples**
26 |
27 | * HKDF - HMAC based KDF. Uses k <- HMAC(salt, SK) // HMAC(key, data). Then expand using HMAC as PRF with key k. This is a good method, as long as SK has sufficient entropy.
28 | * PBKDF - Password based KDF. Passwords have insufficient entropy, so HKDF is unsuitable. If HKDF is used, the derived key will be vulnerable to dictionary attacks. PBKDF uses salt and a slow hash function H(c), ie, H run c times. In PKCS#5 (aka PBKDF1) k <- H(c)(pwd || salt)
29 |
30 | ---
31 |
32 | #### Deterministic Encryption
33 |
34 | An encryption system that will always map the given message to the same ciphertext. Such a system can be used for lookups in to encrypted databases. To store (index, value) in a database, (E(k1, index), E(k2, value)) is sent to the database. To retrieve the data, a query with key E(k1, index) is sent. The database has no knowledge of what data is being stored within.
35 |
36 | **Security issues**:
37 |
38 | 1. Deterministic encryption cannot be chosen plaintext attack (CPA) secure
39 | 2. If the message space is small (say 256), its possible for the attacker to build a dictionary between messages and ciphertexts
40 | 3. Even if the attacker cannot decrypt messages, he can find out all the (encrypted) values corresponding to an index
41 |
42 | Expanding on point 1, the attacker needs to differentiate between the ciphertexts of two messages m0 and m1 to "win" the CPA game. Guide to winning:
43 |
44 | 1. Submit a pair of messages that are equal - (m0, m0). Hence find out c0
45 | 2. Submit a pair of messages (m0, m1).
46 | 3. The returned ciphertext is either c0 or c1. Its easy to tell which, and so the attacker wins every time, ie, with Advantage = 1
47 |
48 | **Solution**: Never encrypt the same message twice. The pair (k, m) never repeats. Either one/both of the pair change between encryptions. This happens when
49 |
50 | 1. Chooses messages at random from a large message space (say, random 128-bit messages)
51 | 2. Message structure ensures uniqueness. For example, the message includes the unique user ID and every user has only one entry in the database.
52 |
53 | Based on this we define Deterministic CPA security. In the Deterministic CPA game, the attacker submits q pairs (mi,0, mi,1) and always gets the ciphertext corresponding to either the left messages (b=0) or the right messages (b=1). The caveat now is that the attacker has to submit distinct messages - m1,0, ... mq,0 are distinct and m1,1, ... mq,1 are also distinct.
54 |
55 | AdvdCPA[A, E] = |Pr[EXP(0)=1] - Pr[EXP(1)=1]| is negligible
56 |
57 | **A common mistake** - using CBC with a fixed IV when deterministic CPA should be used. It is not secure. Using CTR with fixed IV is also insecure because CTR functions like a one-time pad, but with a fixed IV we would be reusing the pad for multiple messages.
58 |
59 |
60 |
61 | ---
62 |
63 | #### Deterministic Encryption Scheme 1 - Synthetic IVs (SIVs)
64 |
65 | Let (E, D) be a CPA-secure encryption. E(k, m; r) -> c. A cipher that doesn't use nonces has to be randomized somehow to be CPA-secure. r denotes the randomness. It comes from this PRF F: K x M -> R (r ∈ R)
66 |
67 | Edet((k1, k2), m) involves 3 steps
68 |
69 | 1. r <- F(k1, m)
70 | 2. c <- E(k2, m; r)
71 | 3. Output c
72 |
73 | **Theorem 1**: Edet is semantically secure under deterministic CPA. Intuition of the proof - Since r is indistinguishable from random strings, and output of E depends on r, E is semantically secure.
74 |
75 | **Features**:
76 |
77 | 1. This is well suited for messages longer than one block.
78 | 2. Ensures ciphertext integrity - decrypt the ciphertext with the prepended IV. Use the plaintext to generate the IV once more. To check integrity, see if the prepended IV matches the derived IV
79 |
80 | **Theorem 2**: If F is a secure PRF and CTR from FCTR is CPA-secure then SIV-CTR from F, FCTR provides Deterministic Authenticated Encryption (DAE). Intuition of the proof:
81 |
82 | * The attacker has q ciphertext-plaintext pairs and has to generate a valid ciphertext.
83 | * Even if he does, it is unlikely that the message will correspond to the IV he has prepended.
84 | * If it is a valid IV, then it must be one of the plaintexts from the q pairs, which means the corresponding ciphertext also lies in the q pairs (since this scheme is deterministic).
85 | * The attacker failed to come up with a new valid ciphertext
86 |
87 | ---
88 |
89 | #### Deterministic Encryption Scheme 2 - Pseudo Random Permutation (PRP)
90 |
91 | Used for messages shorter than 16 bytes.
92 |
93 | Let (E, D) be a secure PRP. E: K x X -> X
94 |
95 | **Theorem**: (E, D) is semantically secure under deterministic CPA. Intuition of the proof -
96 |
97 | * Let f: X -> X be a truly random invertible function. Since the PRP is secure, it is indistinguishable from f.
98 | * In Experiment(0) the adversary sees f(m1,0), ..., f(mq,0). Since q is random, the attacker sees q distinct, random values.
99 | * In Experiment(1) the adversary sees f(m1,1), ..., f(mq,1). Since q is random, the attacker sees q distinct, random values. This is identical and indistinguishable from the results of EXP(0)
100 | * Since he can't do it with a truly random function, he can't do it with a PRP
101 |
102 | So a good deterministic encryption scheme is AES.
103 |
104 | To construct a PRP-based deterministic encryption scheme for long inputs (a wide block PRP):
105 |
106 | 1. Let (E,D) be a secure PRP. E: K x {0,1}n -> {0,1}n. We need to construct a PRP on {0,1}N where N >> n
107 | 2. We take 2 keys (k, L).
108 | 3. We break the message into blocks and XOR each one with a padding function P(L, i) where i is the index of the block. Each result is encrypted to yield PPPi
109 | 4. All PPPi are XOR-ed together to yield MP. MP is encrypted to yield MC.
110 | 5. All PPPi are XOR-ed individually with P(M, i) to yield CCCi
111 | 6. Each CCCi is encrypted then XOR-ed with P(L, i) to yield output block yi
112 |
113 | This scheme is called EME and it involves 2 encryptions. Hence for performance reasons it is recommended for short messages while SIV is preferred for longer messages. EME is CPA secure, but doesn't provide integrity. We make one change to achieve integrity. We append n 0s to the plaintext and expect that many 0s after decryption. The chances of the attacker breaking integrity and constructing a valid ciphertext *with* n 0s in the plaintext is 1/2n which is negligible.
114 |
115 | ---
116 |
117 | #### Tweakable Encryption
118 |
119 | Consider Disk Encryption. It has the following properties
120 |
121 | 1. Sectors on disk are fixed (eg. 4kb). => The ciphertext of sector has to fit within the same space. => sizeof(m) = sizeof(c). The scheme must be deterministic because there is no space to store the randomness, no space for integrity bits either
122 | 2. Lemma - If (E, D) is a deterministic CPA secure cipher with M = C, then (E, D) is a PRP => Every sector will be encrypted with a PRP
123 |
124 | Naive encryption scheme - encrypt each sector with PRP(k, .).
125 |
126 | * Problem - identical sectors will have identical ciphertexts.
127 | * Solution - use different keys for each sector kt = PRF(k, t) where k is the "master-key" and the sector number t = 1, ..., L.
128 | * This is a tweakable block cipher - derive many PRPs from a single key. The "tweak" here is the sector number.
129 | * A tweakable cipher - E, D: K x T x X -> X. For ever t ∈ T and k <- K: E(k, t, .) is an invertible function of X, indistinguishable from random.
130 | * Problem - We aren't storing the derived keys so we would need to apply the PRF for every sector when encrypting/decrypting. That's 2n operations for every n blocks.
131 | * Solution - An XTS tweakable cipher.
132 | 1. Let (E,D) be a secure PRP, E: K x {0,1}n -> {0,1}n
133 | 2. then XTS: Etweak((k1, k2), (t, i), x) = _
134 | 3. The tweak space is (t, i) where i is the index.
135 | 4. We generate N <- E(k2, t)
136 | 5. We XOR the message with result of padding function P(N, i), yielding intermediate **1**. P is multiplication in a finite field, its extremely fast
137 | 6. We encrypt **1** with E(k1, .), yielding **2** (thus each block is only encrypted once)
138 | 7. We XOR **2** with P(N, i) to yield the ciphertext
139 |
140 | When we apply XTS to disk encryption, each 16-byte block is evaluated with a different tweak (t, i) where i is the block number. Its block level encryption, not sector level but that doesn't matter. Used in OS X, TrueCrypt etc.
141 |
142 | ---
143 |
144 | #### Format preserving encryption
145 |
146 | Consider credit cards.
147 |
148 | * The first 6 digits is the bin number, which represents the issuer. For example, Mastercard cards start with 51-55.
149 | * The next 9 digits is the account number.
150 | * The last digit is a checksum.
151 | * There are approximately 42 bits of information
152 |
153 | Goal: End-to-end encryption. Encrypt the credit card in such a manner that all processing intermediaries think they're interacting with a credit card, while not leaking any critical information to them.
154 |
155 | 1. Let the set of possible inputs be {0, ..., s-1}. We need a PRP on this set.
156 | 2. Let t be such that 2t-1 < s <= 2t. In the case of credit cards t=42.
157 | 3. We construct a PRF on 21 bits out of AES by truncating its output
158 | 4. We apply the Luby-Rackoff method (Refer notes on block ciphers) to create a PRP on 42 bits out of this. Although 3 is enough to construct the PRP, we will use 7 rounds of Luby-Rackoff to ensure security.
159 | 5. While applying the encryption to the input, we might get a ciphertext that doesn't lie in the input set. We keep applying the encryption on the ciphertext until it does. To decrypt, the decryption is applied repeatedly until the plaintext lies in the set. The expected number of iterations is 2.
160 |
--------------------------------------------------------------------------------
/aes/readme.md:
--------------------------------------------------------------------------------
1 | Implementing AES
2 | ===
3 |
4 | The Advanced Encryption Standard is the most widely used encryption algorithm today. Its fast and secure but also easy to understand and implement.
5 |
6 | If you're interested in learning about AES, look at this comic - [A Stick Figure Guide to the Advanced Encryption Standard](http://www.moserware.com/2009/09/stick-figure-guide-to-advanced.html). He splits his comic into 4 Acts:
7 |
8 | 1. brief history of crypto
9 | 2. crypto basics
10 | 3. implementation
11 | 4. math.
12 |
13 | He did a great job with all 4 parts, but I thought elaborating on the implementation would be helpful. In this post, I will only assume you've read Acts 2 and 3 and signed the foot-shooting-prevention agreement.
14 |
15 | 
16 |
17 | ---
18 |
19 | ### AES Encryption
20 |
21 | The implementation of AES involves doing a set of simple operations repeatedly. Each repetition is called a "round". Depending on the size of the key (128, 192 or 256 bit), the input (block of 16 bytes) goes through 10, 12 or 14 rounds. In applying the 2 Big Ideas - Diffusion and Confusion, AES makes sure that each bit in the 16 byte block depends on every bit in the same block from 2 rounds previously. That's quite the achievement, so lets speak about the operations in detail.
22 |
23 | Each round consists of 4 steps
24 |
25 | 1. applying a key - `addRoundKey()`
26 | 2. substituting bytes - `subBytes()`
27 | 3. shifting rows - `shiftRows()`
28 | 4. mixing columns - `mixColumns()`
29 |
30 | Decryption involves the inverse of these steps, in reverse order
31 |
32 | 1. inverse-mixing columns - `invMixColumns()`
33 | 2. inverse-shifting rows - `invShiftRows()`
34 | 3. inverse-substituting bytes - `invSubBytes()`
35 | 4. applying a key - `addRoundKey()`
36 |
37 | Have a look at the `encrypt` function below, implemented in Go (Go has a C-like syntax)
38 |
39 | ```
40 | func encrypt(state, expkey []uint32, rounds int) {
41 | keyi := 0
42 | addRoundKey(state, expkey[keyi:keyi+4])
43 | keyi += 4
44 | for i := 0; i < rounds; i++ {
45 | subBytes(state)
46 | shiftRows(state)
47 | mixColumns(state)
48 | addRoundKey(state, expkey[keyi:keyi+4])
49 | keyi += 4
50 | }
51 | subBytes(state)
52 | shiftRows(state)
53 | addRoundKey(state, expkey[keyi:keyi+4])
54 | }
55 | ```
56 |
57 | Notes on the implementation:
58 |
59 | * The 16-byte block, called state is represented as a slice of 4 4-byte unsigned integers. The 4-byte unsigned int is also referred to as a "word".
60 | * The expanded key is based on the original key. Its 16*(rounds+1) bytes in length.
61 |
62 | ---
63 |
64 | ### Step 1: subBytes and invSubBytes
65 |
66 | All the 4 operations are invertible. If you took any random 16-byte state and applied any operation and its inverse, you'd get back the original state. This is how decryption is a simple mirror of the encryption process.
67 |
68 | In `subBytes` each of the 16 bytes is replaced by a byte from the S-box (a lookup table). The code would look like:
69 |
70 | ```
71 | input[i] = sbox[input[i]] // i = 0, 1, ..., 15
72 | ```
73 |
74 | For `invSubBytes`, only the lookup table is changed. The code is `input[i] = invsbox[input[i]]`. The values for both lookup tables can be found on the [wiki page](https://en.wikipedia.org/wiki/Rijndael_S-box). If this step appears really simple, its because it is. Nevertheless, I'd suggest writing a test to check if its working correctly.
75 |
76 | ```
77 | input := []uint32{0x8e9ff1c6, 0x4ddce1c7, 0xa158d1c8, 0xbc9dc1c9}
78 | expected := []uint32{0x19dba1b4, 0xe386f8c6, 0x326a3ee8, 0x655e78dd}
79 | ```
80 |
81 | Another useful test would be to apply `subBytes` and `invSubBytes` on 16 random bytes and check if you get back the original.
82 |
83 | ---
84 |
85 | ### Step 2: shiftRows and invShiftRows
86 |
87 | In `shiftRows`, the rows are shifted left. The top row is left untouched, the second row by 1 byte, the third row by 2 bytes, the fourth row by 3 bytes. As depicted below
88 |
89 | 
90 |
91 | ```
92 | func shiftRows(state []uint32) {
93 | for i := 1; i < 4; i++ {
94 | // rotate word left by specified number of bytes
95 | state[i] = rotWordLeft(state[i], i)
96 | }
97 | }
98 | ```
99 |
100 | To test if `shiftRows` working correctly, use this input
101 |
102 | ```
103 | input := []uint32{
104 | 0x8e9f01c6,
105 | 0x4ddc01c6,
106 | 0xa15801c6,
107 | 0xbc9d01c6}
108 | expected := []uint32{
109 | 0x8e9f01c6,
110 | 0xdc01c64d,
111 | 0x01c6a158,
112 | 0xc6bc9d01}
113 | ```
114 |
115 | `invShiftRows` is the inverse operation. The top row is left untouched and the next 3 rows are shifted right by 1, 2, 3 bytes. Again, I'd recommend writing a test to ensure that applying both `shiftRows` and `invShiftRows` to random bytes returns the original.
116 |
117 | ---
118 |
119 | ### Step 3: mixColumns and invMixColumns
120 |
121 | This step is slightly complicated, compared to the other 3. The state is operated on column-wise. Each byte of the column is replaced based on an operation. As you'd expect, in `invMixColumns` the 4 bytes are replaced by the 4 original ones.
122 |
123 | 
124 |
125 | Speaking about the operation itself, it involves multiplication and addition in the Galois field. That sounded arcane to me, until I realised that I can get the results of multiplication via a lookup table and addition is just bit-wise XOR.
126 |
127 | ```
128 | // a0-3 represent the bytes of a column from top to bottom
129 | // r0-3 are the transformed bytes
130 |
131 | func calcMixCols(a0, a1, a2, a3 byte) (r0, r1, r2, r3 byte) {
132 | // r0 = 2*a0 + 3*a1 + a2 + a3
133 | // r1 = a0 + 2*a1 + 3*a2 + a3
134 | // r2 = a0 + a1 + 2*a2 + 3*a3
135 | // r3 = 3*a0 + a1 + a2 + 2*a3
136 | r0 = gMulBy2[a0] ^ gMulBy3[a1] ^ a2 ^ a3
137 | r1 = a0 ^ gMulBy2[a1] ^ gMulBy3[a2] ^ a3
138 | r2 = a0 ^ a1 ^ gMulBy2[a2] ^ gMulBy3[a3]
139 | r3 = gMulBy3[a0] ^ a1 ^ a2 ^ gMulBy2[a3]
140 | return
141 | }
142 |
143 | func calcInvMixCols(a0, a1, a2, a3 byte) (r0, r1, r2, r3 byte) {
144 | // r0 = 14*a0 + 11*a1 + 13*a2 + 9*a3
145 | // r1 = 9*a0 + 14*a1 + 11*a2 + 13*a3
146 | // r2 = 13*a0 + 9*a1 + 14*a2 + 11*a3
147 | // r3 = 11*a0 + 13*a1 + 9*a2 + 14*a3
148 | r0 = gMulBy14[a0]^gMulBy11[a1]^gMulBy13[a2]^gMulBy9[a3]
149 | r1 = gMulBy9[a0] ^gMulBy14[a1]^gMulBy11[a2]^gMulBy13[a3]
150 | r2 = gMulBy13[a0]^gMulBy9[a1] ^gMulBy14[a2]^gMulBy11[a3]
151 | r3 = gMulBy11[a0]^gMulBy13[a1]^gMulBy9[a2] ^gMulBy14[a3]
152 | return
153 | }
154 | ```
155 |
156 | Each of the `gMulBy` lookup tables are 256 bytes in size. (You can find them [here](https://en.wikipedia.org/wiki/Rijndael_mix_columns#Galois_Multiplication_lookup_tables))
157 |
158 | ```
159 | input := []uint32{
160 | 0xdbf201c6,
161 | 0x130a01c6,
162 | 0x532201c6,
163 | 0x455c01c6}
164 | expected := []uint32{
165 | 0x8e9f01c6,
166 | 0x4ddc01c6,
167 | 0xa15801c6,
168 | 0xbc9d01c6}
169 | ```
170 |
171 | For `invMixColumns`, the test vectors are simply reversed. As with the other steps, it's a good idea to check if your `mixColumns` and `invMixColumns` invert each other.
172 |
173 | I'm not going to explain Galois field arithmetic here for 2 reasons: I'd prefer to keep this post short, and its not necessary to know exactly how it works while implementing AES. I do recommend reading [this book](http://www.amazon.com/Design-RijndaeL-Encryption-Information-Cryptography/dp/3540425802) by the creators of AES if you're interested in that or other interesting topics like cryptanalysis of AES.
174 |
175 | ---
176 |
177 | ### Step 4: addRoundKey
178 |
179 | The simplest of all the steps. A bit-wise XOR between the 16-byte state and the appropriate 16-bytes of the expanded key.
180 |
181 | ```
182 | func addRoundKey(state, key []uint32) {
183 | for i := 0; i < 4; i++ {
184 | state[i] = state[i] ^ key[i]
185 | }
186 | }
187 | ```
188 |
189 | As you probably know, XOR-ing any input with the same key twice returns the original input. That's why we use the same operation with the same key in both encryption and decryption.
190 |
191 | ---
192 |
193 | ### Step 0: Key Expansion
194 |
195 | I mentioned previously that the expanded key is based on the 16-byte key and its 16*(rounds+1) bytes in length. Thus, a different 16-bytes is used for each call to `addRoundKey`
196 |
197 | ---
198 |
199 | ### Potential gotcha
200 |
201 | Be careful of how you fill the state matrix with your 16 bytes of input.
202 |
203 | ```
204 | // wrong
205 | 0 1 2 3
206 | 4 5 6 7
207 | 8 9 10 11
208 | 12 13 14 15
209 |
210 | // correct
211 | 0 4 8 12
212 | 1 5 9 13
213 | 2 6 10 14
214 | 3 7 11 15
215 | ```
216 |
217 | ---
218 |
219 | ### Congrats!
220 |
221 | You just implemented AES. Try decrypting the file [here](http://cryptopals.com/sets/1/challenges/7/) to see if you got it right :)
222 |
223 | If you haven't yet managed it, you could check out the [FIPS-197 Document](http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf) which elaborates on each step.
224 |
225 | ---
226 |
227 | ### My implementation
228 |
229 | You can find my implementation here:
230 |
231 | * [aes.go](https://github.com/nindalf/crypto/blob/master/aes/aes.go) - `encrypt()`, `decrypt()` and all helper functions.
232 | * [aes_test.go](https://github.com/nindalf/crypto/blob/master/aes/aes_test.go) - test vectors for each step.
233 | * [const.go](https://github.com/nindalf/crypto/blob/master/aes/const.go) - S-boxes and the Galois-field multiplication lookup tables.
234 |
235 | The caveats mentioned in the foot-shooting-prevention agreement apply to my code as well. The linked code is useful for learning about AES, but is not secure and should not be used to encrypt anything important.
236 |
237 | ---
238 |
239 | ### Advanced implementation
240 |
241 | The creators of AES designed the algorithm in such a way that implementations could make a trade-off between speed and code size. There are 4 possible levels, increasing in size and speed:
242 |
243 | * 0kB - no lookup tables, all steps are calculated, including substitution.
244 | * 256 bytes x 2 - s-box and inverse-s-box are stored as lookup tables.
245 | * 4kB x 2 - the Galois field multiplication tables are stored. (Approach taken by my impl.)
246 | * 24kB x2 - The entire round (`subBytes`, `shiftRows` and `mixColumns`) are replaced by a lookup table. The only operation left is `addRoundKey`.
247 |
248 | The last is the fastest possible software implementation. Such an implementation can be found in the Go standard library [here](http://golang.org/src/crypto/aes/block.go). If the CPU's cache is large enough to accommodate the entire table, it will be really fast.
249 |
250 | Hardware implementations are even faster. Intel and AMD introduced CPU instructions called [AES-NI](https://en.wikipedia.org/wiki/AES_instruction_set). These instructions are
251 |
252 | * `AESENC` and `AESENCLAST` (for the first n-1 round and last round respectively)
253 | * `AESDEC` and `AESDECLAST`
254 | * `AESKEYGENASSIST` (to generate the expanded key)
255 |
256 | These instructions can perform AES in 3.5 CPU cycles/byte, while the best software implementation would take 10-30 cycles/byte. [source](http://www.cryptopp.com/benchmarks-p4.html)
257 |
258 | The Go Standard Library also has [an implementation](http://golang.org/src/crypto/aes/asm_amd64.s) that uses these instructions.
259 |
260 | ---
261 |
262 | ### Closing
263 |
264 | I hope you found this post useful. I had a lot of fun learning about AES and implementing it and I wanted to share it with as many people as possible.
265 |
--------------------------------------------------------------------------------
/stanford/4-authenticated-encryption.md:
--------------------------------------------------------------------------------
1 | Authenticated Encryption
2 | ===
3 |
4 | **Confidentiality** - semantic security against a chosen plaintext attack. Encryption is secure against eavesdropping only.
5 |
6 | **Integrity** - Existential unforgeability under chosen message attack. eg. CBC-MAC, HMAC, PMAC, CW-MAC
7 |
8 | **Goal** - Encryption secure against tampering - Confidentiality + Integrity - Authenticated Encryption. The adversary is one who can tamper with traffic, dropping certain packets while injecting others
9 |
10 | #### A warning
11 |
12 | CPA security cannot guarantee secrecy under active attacks. They should never be used on their own. An attacker can still
13 |
14 | * Tamper with a block cipher in CBC mode when you know the plaintext corresponding to a certain block.
15 | * Tamper with packets being sent in CTR mode. By tampering with the CRC and Data fields of the TCP packet and listening for ACKs, its possible to guess the ciphertext. The listener can mistake the attack for poor connectivity. The recipient acts as an oracle.
16 |
17 | ---
18 |
19 | #### Definition
20 |
21 | An authenticated encryption system (E, D) is defined as
22 |
23 | * E: K x M x N -> C where N is optional
24 | * D: K x C x N -> M ∪ ⟘ (⟘ ∉ M, denotes invalid ciphertext)
25 |
26 | To be secure, such a system should provide
27 |
28 | 1. Semantic security under chosen plaintext attack
29 | 2. Ciphertext integrity - it should be impossible for the attacker to create ciphertexts that decrypt properly.
30 |
31 |
32 | #### Ciphertext integrity
33 |
34 | The adversary can submit q messages m1,... , mq to the challenger. The challenger encrypts these under a key k and returns c ciphertexts c1,... , cq. The adversary constructs and sends back a ciphertext c, to which the challenger responds with
35 |
36 | * b = 1 if D(k, c) != ⟘ and c ∉ {c1,... , cq}, indicating the adversary won
37 | * b = 0 otherwise, indicating the adversary lost
38 |
39 | Defintion of security - (E, D) has ciphertext integrity if for all "efficient" aversaries A, AdvCI[A, E] = Pr[Challenger outputs 1] is "negligible"
40 |
41 | ---
42 |
43 | #### Implications
44 |
45 | Chosen Ciphertext game: Adversary submits two messages one block m0 and m1. He gets back (IV, cb, he needs to guess which he got. He can submit a new ciphertext c' and ask for a decryption. Based on what he gets, he has to guess if the message was originally encrypted by the challenger. For CBC mode, its trivial to create c' such that the IV is IV ⨁ 1. This is a new, valid ciphertext and the corresponding plaintext is mb ⨁ 1. The adversary can thus guess b with advantage 1.
46 |
47 | **Authenticated encryption** => Chosen ciphertext security.
48 |
49 | Theorem: Let (E, D) be a cipher that provides authenticated encryption. Then (E, D) is CCA secure. In particular, for any q-query adversary A, there exists an adversary B1, B2 s.t.
50 |
51 | AdvCCA <= 2q AdvCI[B1, E] + AdvCI[B2, E]
52 |
53 | 1. Authenticity - the attacker cannot fool Bob by impersonating Alice, since he doesn't have the key k.
54 | 2. Secure against chosen ciphertext attacks, because it is not possible to create valid ciphertexts
55 | 3. It is still vulnerable to
56 | * Replay attacks
57 | * Side channel attacks
58 |
59 | ---
60 |
61 | #### Constructing an Authenticated Encryption scheme
62 |
63 | In the bad old days (pre-2000), crypto libraries provided CPA-secure functions (AES-CBC) and MAC functions (HMAC) and each developer could have fun mixing and matching. Not all combinations provided AE.
64 |
65 |
66 | 
67 |
68 | * SSL - MAC(m) then encrypt
69 | * IPsec - encrypt *then* MAC(c)
70 | * SSH - encrypt *and* MAC(m)
71 |
72 | Which scheme is best?
73 |
74 | * SSL's scheme is not perfect. It is vulnerable to CCA because of possible weird interactions between the MAC and the encryption scheme. However, in the case of rand-CTR or rand-CBC mode, MAC-then-encrypt provides AE. For rand-CTR, even one-time MAC is sufficient.
75 | * SSH's scheme is not recommended. Its perfectly ok in general for a tag to leak bits of the message, but in this case, it would break CPA security. Although SSH itself is not broken, this scheme isn't good.
76 | * IPsec's scheme is best, and always correct.
77 |
78 | Authenticated Encryption with Associated Data (AEAD) - only a part of the message needs to be encrypted, but the entire message needs to be authenticated. Here are a few modes that implement this, along with the associated speed on Prof Boneh's machine.
79 |
80 | 1. GCM (Galois/Counter mode) - CTR-mode encryption then Carter-Wegman MAC - 108 MBps
81 | 2. CCM (Counter with CBC MAC) - CBC-MAC then CTR-mode encryption - 61 MBps
82 | 3. EAX (couldn't find the expansion) - CTR-mode encryption then CMAC - 61 MBps
83 |
84 | All of these are nonce-based. Remember, the nonce need not be random and its ok to use a counter as a nonce. But the pair (key, nonce) should never, ever repeat.
85 |
86 | OCB is a one-pass mode (encrypt and MAC together) that's faster than any of the 3 modes (129 MBps), but is encumbered by patents.
87 |
88 | ---
89 |
90 | #### TLS Case study
91 |
92 | Communication between a browser b and a server s
93 |
94 | * There are 2 unidirectional keys kb->s and ks->b. Both parties know both the keys.
95 | * The browser uses kb->s to encrypt data before sending and ks->b to decrypt received data.
96 | * There are 2 64-bit counters ctrb->s and ctrs->b that are initialised to 0 when the session starts. Since both the server and the client maintain this state, TLS is stateful encryption
97 | * The appropriate counter is incremented when a record is sent or received. These counters are meant to protect against replay attacks
98 | * MAC-then-encrypt. The MAC is HMAC-SHA-1 and the encryption scheme is CBC AES-128.
99 |
100 | 
101 |
102 | **Browser side encryption**:
103 |
104 | 1. tag <- S(kmac, [++ctrb->s || header || data]).
105 | 2. pad [header || data || tag] to AES block size.
106 | 3. CBC encrypt with kenc with new random IV.
107 | 4. Prepend plaintext header (type || version || packet length).
108 |
109 | Note that kb->s = (kmac, kenc). So there are 4 keys in all, all of which are known to both parties. Also, the value of the counter isn't sent, because the server knows the current value of the counter.
110 |
111 | **Server side decryption**:
112 |
113 | 1. CBC decrypt with kenc.
114 | 2. Strip the padding. Send bad_record_mac if invalid. (ie, ⟘)
115 | 3. Verify the tag - V(kmac, [++ctrb->s || header || data], tag). Send bad_record_mac if invalid.
116 |
117 | **Security features**:
118 |
119 | 1. If a packet is resent by an attacker, the tag would no longer be valid. Sending the counter doesn't increase the length of the ciphertext either, so its a very neat solution.
120 | 2. By only sending ⟘ in case of bad pad OR bad MAC, it tells the attacker nothing. If he gets more specific error information, it could be used to break the protocol. General rule: If decryption fails, *never* explain why.
121 |
122 | **Bugs in previous version**:
123 |
124 | 1. IV for next record would be ciphertext of the current record. This isn't CPA secure (pre 1.1)
125 | 2. Padding oracle - it would send decryption_failed in case of bad pad and bad_record_mac in case of invalid MAC
126 |
127 | ---
128 |
129 | #### 802.11b WEP - how not to do it
130 |
131 | Previous vulnerabilities discussed
132 |
133 | * It becomes a 2-time pad after every 16m frames.
134 | * The seeds used for RC4 were highly related. RC4 wasn't designed to accept related keys
135 |
136 | Yet another vulnerability - the crc included in the frame was too linear. ∀ m, p: CRC(m⨁p) = CRC(m)⨁F(p), where F is a well-known function. It is trivial to modify the ciphertext and also modify the CRC such that it is valid for the tampered plaintext
137 |
138 | Solution - use a cryptographic MAC, not an ad-hoc solution like Cyclic Redundancy Check (CRC).
139 |
140 | ---
141 |
142 | #### Padding Oracle attack
143 |
144 | This is an example of a chosen ciphertext attack. If the attacker can differentiate between the two errors (invalidmac, invalidpad), the attacker submits a ciphertext and learns if the last bytes of the plaintext are a valid pad. He modifies the ciphertext and guesses the plaintext byte by byte.
145 |
146 | Even if the server sends the same response (⟘) in both cases, a timing attack is still possible. Since the padding is checked before the mac and verfication takes some time, the attacker can differentiate betweent the two errors. In OpenSSL 0.9.7a, the response for a bad padding was received in 21ms on average and response for a bad mac was received in 23ms
147 |
148 | **Steps**:
149 |
150 | 1. Start with ciphertext block i, throw away the blocks after that.
151 | 2. Guess a value g for the last byte of block i. Change the last byte of ciphertext block c[i-1] to (last-byte ⨁ g ⨁ 01) where 01 is the valid padding for a 15-byte long message
152 | 3. If the guess is correct, the last byte of plaintext m[i] becomes g ⨁ g ⨁ 01 = 01 and the server tells us that the pad is valid. The max number of guesses is 256 and on average it should take 128 guesses
153 |
154 | Padding oracle is difficult to pull off on TLS because when the server receives a message with invalidmac or invalidpad, it tears down the connection and renogiates the key.
155 |
156 | It is however, possible to pull off this attack on IMAP servers.
157 |
158 | **Lessons**:
159 |
160 | * Encrypt-then-MAC would have completely avoided this problem. MAC is checked first and discarded if invalid.
161 | * MAC-then-CBC provides AE, but a padding oracle destroys it.
162 |
163 | ---
164 |
165 | #### Attacking non-atomic decryption
166 |
167 | 
168 |
169 | SSH uses encrypt-*and*-MAC. Decryption procedure:
170 |
171 | 1. Decrypt packet field length only (!)
172 | 2. Read as many packets as the length specifies
173 | 3. Decrypt remaining ciphertext blocks
174 | 4. Check MAC tag and see if the error response is valid
175 |
176 | **How to exploit this**:
177 |
178 | 1. We expect that the server will send us a MAC error only if it reads the correct number of packets from the first decrypted block.
179 | 2. Say we have a ciphertext block. We send that to the server as the first block, corresponding to packet len.
180 | 3. We feed in data 1 byte at a time until we get a MAC error. When we do, we know that the first 5 bytes of the block we sent were correct.
181 | 4. We keep trying bytes in this manner
182 |
183 | **Lessons**:
184 |
185 | 1. Non-atomic decryption
186 | 2. Length field decrypted and used before it is authenticated
187 |
188 | **Ways to redesign this**:
189 |
190 | 1. Send the length field unencrypted, but MAC-ed.
191 | 2. Add a MAC of (seq-num, length) right after the len field.
192 |
193 | ---
194 |
195 | #### If you need to design your own encrypted authentication scheme
196 |
197 | Steps:
198 |
199 | 1. Stop
200 | 2. Don't do this
201 | 3. Use GCM, CCM or EAX instead
202 |
203 | But actual pointers in case you're doing it anyway
204 |
205 | 1. Use encrypt-then-MAC
206 | 2. Don't use length field before the length field is authenticated (like SSH did)
207 | 3. Don't use *any* decrypted field before its authenticated
208 |
209 | ---
210 |
211 | #### Papers
212 |
213 | 1. The Order of Encryption and Authentication for Protecting Communications - Krawczyk
214 | 2. Authenticated Encryption with Associated Data - Rogaway
215 | 3. Password Interception in an SSL/TLS channel (ie, padding oracle) - Canvel, Hiltgen, Vaudenay, Vuagnoux
216 | 4. Plaintext recovery attacks against SSH - Albrech, Paterson, Watson
217 | 5. Problem areas for IP security protocols (schemes that use CPA security and don't add integrity) - Bellovin
218 |
--------------------------------------------------------------------------------
/stanford/1-stream-ciphers.md:
--------------------------------------------------------------------------------
1 | Stream Ciphers
2 | ===
3 |
4 | #### Cipher
5 |
6 | * It is defined over the triple of sets (𝒦, ℳ, 𝓒) ie, the sets of all possible keys (keyspace), all possible messages and all possible ciphertexts. The triple defines the environment over which the cipher is defined.
7 | * A cipher is made up of two "efficient" algorithms - the encryption algo E and the decryption algo D.
8 | * E: 𝒦 x ℳ -> 𝓒
9 | * D: 𝒦 x 𝓒 -> ℳ
10 | * Correctness property. ∀ m ∈ ℳ, ∀ k ∈ 𝒦: D(k, E(k, m)) = m
11 | * Efficient means different things to different people. For some people it means algorithmic complexity. For others, it means how many ms taken to encrypt 1GB of data.
12 | * E is sometimes randomized. D is deterministic
13 |
14 | ---
15 |
16 | #### One time pad
17 |
18 | * Key is a long sequence of bits, as long as the message that needs to be encrypted
19 | * c = E(k, m) = k ⨁ m
20 | * m = D(k, c) = k ⨁ c = k ⨁ (k ⨁ m) = (k ⨁ k) ⨁ m = 0 ⨁ m = m (Reversible!)
21 | * From the discussion on discrete probability, k ⨁ m is uniformly distributed since k is uniformly distributed. Thus the distribution of k ⨁ m0 is indistinguishable from the distribution of k ⨁ m1.
22 | * Very fast, but the keys are too long. If you could transfer a key that long securely, you can use the same to transfer the message itself. So its hard to use in practice.
23 | * Its a good cipher.
24 |
25 | ---
26 |
27 | #### A good cipher
28 |
29 | * According to Shannon, a good cipher generates a ciphertext that reveals no "information" about the plaintext.
30 | * A cipher (E, D) over (𝒦, ℳ, 𝓒) has perfect secrecy if ∀ m0, m1 ∈ ℳ (|m0| = |m1|) and ∀ c ∈ 𝓒: Pr[E(m0, k) = c] = Pr[E(m, k) = c] where k is uniform in 𝒦.
31 | * In other words, on observing a ciphertext c, it is equally likely that it could have come from any m ∈ ℳ, ie, all mi messages are equally likely. Thus intercepting c tells you nothing about the message and no ciphertext-only attacks are possible on such a cipher.
32 | * But Shannon also proved this - for a cipher to be perfect, |𝒦| >= |ℳ|, so that pretty much excludes everything apart from the one time pad. Another way of stating it is that the key-len >= message-len
33 | * Therefore we need a less stringent definition of a good cipher. (covered later in this lesson)
34 |
35 | ---
36 |
37 | #### Pseudorandom Generator
38 |
39 | It is a function that takes an s-bit string (seed), and maps it onto a much larger output string. Ie, G: {0,1}s -> {0,1}n where n >> s. Some properties
40 |
41 | 1. efficient to compute.
42 | 2. It should be deterministic, the only random part is the seed.
43 | 3. The output should "look" random.
44 | 4. It should be unpredictable. G:{0,1}s -> {0,1}n is predictable if ∃ an efficient algorithm A and ∃ 1 <= i <= n s.t. Pr[A(G(k))|first i bits = G(k)|i+1] = 1/2 + ϵ for some non-negative ϵ. In other words, G is predictable if given the first i bits of output, there exists no efficient algorithm that can predict that i+1th bit with probability greater than 1/2 + ϵ where ϵ is non-negative.
45 |
46 | The challenge is in satisfying all of these criteria. Since G is deterministic, it is a one-to-one function. Since s << n, only a small subset of n-length strings are possible outputs. Nevertheless, the n-length string should be as uniformly distributed as possible.
47 |
48 | Note : ϵ is a scalar. For practitioners, (ϵ >= 1/230) is non-neglible, meaning if you used a key for encrypting a GB of data, then an event that happens with this probability will probably happen after a gigabyte of data. Since a GB is not that high, this event is likely to happen. An event that is (ϵ <= 1/280) is negligible, one that is unlikely to happen over the lifetime of the key
49 |
50 | Examples of bad PRGs
51 | * Linear congruential generator - r[i] = (r[i-1] * a + b) mod p - very easy to predict.
52 | * glibc random() - actually used by Kerberos v4
53 |
54 | ---
55 |
56 | #### Stream cipher
57 |
58 | * An attempt to make OTP practical. Instead of using a random key, we use a pseudo-random key. The key will be used as a seed.
59 | * Stream ciphers cannot have perfect secrecy because the key length is less than the message length and security would depend on the PRG
60 |
61 | Problems with OTP used as a stream cipher.
62 | 1. If the pad is reused, it is insecure. It basically becomes repeating-key XOR, which is breakable thanks to the sufficient redundancy in English and ASCII encoding. Russians used 2-time pads from 1941-46, Microsoft Point-to-Point protocol used it, Wi-Fi protocol WEP uses it (after every 16M frames). In WEP the key used to encrypt frames 1, 2, .. was (1||k), (2||k). Since its a 24-bit counter, it cycles. Also, k doesn't change long term, and the PRG used (RC4) depends on the lower bits changing. To prevent this:
63 | * If OTP is being used between client and server, 2 separate keys should be used.
64 | * For network traffic, negotiate a new key for every session.
65 | * For disk encryption, do not use a stream cipher.
66 | 2. No integrity. The ciphertext is malleable. Modifications to the ciphertext are undetected and have a predictable impact on the ciphertext. For example, the ciphertext of "attack at dawn" - "09e1c5f70a65ac519458e7e53f36" can be trivially changed to "09e1c5f70a65ac519458e7f13b33", meaning "attack at dusk".
67 |
68 | ---
69 |
70 | #### Examples of Stream ciphers
71 |
72 | * RC4 (1987). Takes a 128-bit key, expands this to 2048 bits and executes a simple loop with the state. Each loop gives 1 byte. Its used in HTTPS and WEP. Not recommended for use today. Problems
73 | 1. Bias in initial output - For example Pr[output[1] == 0] = 2/256 (it should be 1/256). Its recommended that the first 256 bytes of output of RC4 be ignored.
74 | 2. The probability of getting output [0,0] should be 1/2562. After a few GB of output, it becomes 1/2562 + 1/2563. It can be used to distinguish the output of the generator from truly random bytes.
75 | 3. Related key attacks like in WEP. If the keys are closely related, it is possible to recover the key
76 | * Linear Feedback Shift Registers. Take a seed. Every loop, shift the state right. The msb is the xored output of a few selected bytes or all bytes. Easy to implement in hardware. It is very broken. Examples, all of which are broken, but difficult to change since they're implemented in hardware.
77 | 1. Content Scrambling System ie CSS (used in DVD) uses 2 LFSRs. The seed used was 40 bits long (due to USG export regulations). It seeded a 17-bit LFSR and a 25-bit LFSR (leading 1s added). The output of both go through addition-modulo-256. With DVDs, the first 20-odd bytes of plaintext were known. We iterate through the possible outputs of the 17-bit one, subtract it from the known bytes and check if the remainder could possibly have been generated by a 25-bit LFSR
78 | 2. GSM (A5/1,2) uses 3 LFSRs
79 | 3. Bluetooth uses 4 LFSRs
80 | * eStream. PRG used is {0,1}s x R = {0,1}n. R is a nonce, a value which isn't repeated over the lifetime of the key. E(m, k, r) = m ⨁ PRG(k, r). The pair (k, r) is not used more than once. Since the pair isn't used twice, the key can be reused.
81 | * The PRG used in eStream is Salsa20: {0,1}128 or 256 x {0,1}64 -> {0,1}n where max n = 273 bits.
82 | * Salsa20(k, r) := H(k, (r, 0)) || H(k, (r, 1)) || ...
83 | * Its fast on both hardware and software, because the small h function can be implemented using x86 SSE2 instructions. Its about 5 times faster than RC4
84 |
85 | ---
86 |
87 | #### PRG Continued
88 |
89 | G: K -> {0,1}n be a PRG. The goal is that the output should be indistinguishable from a truly uniform distribution. This is difficult because the set of {0,1}n is very large while the seed space is quite small. Therefore, only a subset of {0,1}n is possible. Despite that, an adversary who looks at the output of the generator would find it impossible to distinguish from the output of the uniform distribution
90 |
91 | ##### Statistical tests
92 |
93 | A statistical test on {0,1}n is an algorithm A(x) tells if a PRG is random (1) or not random (0)
94 |
95 | 1. Iff |num(zeros) - num(ones)| <= 10 * sqrt(n)
96 | 2. Iff |num(two consecutive zeros)| - n/4 <= 10 * sqrt(n) // 00, 01, 10, 11 are all equally likely so they should be close to n/4
97 | 3. Iff max-num-consecutive(0) <= 10* log2(n)
98 |
99 | Statistical tests in general are not that great an idea. But how do we compare statistical tests? We look at advantage
100 |
101 | Adv[A, G] := | Pr[A(G(k)) == 1] - Pr[A(r) == 1] | where k is taken from the keyspace and r is truly random. Obviously Adv ∈ [0,1]. If Adv is close to 1, then the statistical test behaved completely differently in the two cases - it was able to distinguish between pseudo-random and truly random. In other words, statistical test A breaks generator G with advantage Adv[A, G]
102 |
103 | Therefore, we have a new definition of secure PRGs - if no efficient statistical test can distinguish between the generator and truly random output. In other words, ∀ "efficient" A: Adv[A, G] is negligible. Not just a particular battery of statistical tests, the definition mentions ∀ efficient tests.
104 |
105 | There are no known provably secure PRGs. P != NP kappa.
106 |
107 | Facts about secure PRGs
108 |
109 | 1. A secure PRG is unpredictable. We prove the contrapositive, if PRG is predictable, it is insecure. Suppose A is an efficient algorithm such that Pr[A(G(k)|1...i) = G(k)|i=1] = 1/2 + ϵ. ϵ is non-negligible, say 1/1000. Then to test A, we define B(X). We ask A to predict after each input, and output 1 if it was correct and 0 if it wasn't. Then we ask Pr[B(x) = 1]. Its clear that Pr[B(r) == 1] = 1/2. Pr[G(k) = 1] > 1/2 + ϵ. => Adv[B, G] = ϵ
110 |
111 | Yao's theorem: an unpredictable PRG is secure. If no next-byte predictor can predict the i+1th bit after seeing the first i input, then no statistical test can.
112 |
113 | Let P1 and P2 be 2 distributions over {0,1}n. They are computationally indistinguishable if ∀ A: |Pr[A(P1) ==1] - Pr[A(P2) == 1]|
114 |
115 | ---
116 |
117 | #### Semantic security
118 |
119 | To prove: If you use a secure PRG, you will get a secure stream.
120 |
121 | Recapping from earlier, according to Shannon a secure cipher shouldn't reveal any "information" about the plaintext. However, we need a less stringent definition because only a OTP satisfies Shannon's definition.
122 |
123 | Shannon said - Pr[E(k, m0) == c] == Pr[E(k, m1) == c]
124 |
125 | A weaker definition is Pr[E(k, m0) == c] ≈p Pr[E(k, m1) == c]
126 |
127 | Another way of looking at semantic security.
128 | * The adversary gives the challenger (kind of like an oracle) 2 messages m0, m1 ∈ M, |m0|=|m1|.
129 | * The challenger will encrypt one of them and return it - E(k, mb). The adversary has to guess which message it received.
130 | * The advantage of the adversary wrt semantic security is AdvSS = |Pr[W0] - Pr[W1]| ∈ [0,1]. Pr[Wb] is the probability that the adversary guessed "b".
131 | * Interpretation of Advantage. If its 0, the adversary wasn't able to guess which message it was. If its 1, he was able to distinguish an encryption of m0 from an encryption of m1 ie, its completely broken.
132 |
133 | Thus the definition - E is secure if ∀ "efficient" adversaries A AdvSS[A, E] is negligible.
134 |
135 | Example. Suppose the adversary can always tell the LSB of mb. It sends m0 and m1 such that lsb(m0) = 0 and lsb(m1) = 1. Thus the advantage would be |Pr[Exp(0) = 1] - Pr[Exp(1) = 1]| = |0 - 1| = 1. (Probability that the challenger guessed 1 for m0 - Probability that the challenger guessed 1 for m1).
136 |
137 | This holds for any information about the plaintext, not just the lsb. It could be msb, bit 7, the xor of all bits etc
138 |
139 | // What I'm not clear about - the difference between the Adv fn for PRGs and ciphers.
140 |
--------------------------------------------------------------------------------
/aes/const.go:
--------------------------------------------------------------------------------
1 | package aes
2 |
3 | // Powers of x mod poly in GF(2).
4 | var powx = [16]byte{
5 | 0x01,
6 | 0x02,
7 | 0x04,
8 | 0x08,
9 | 0x10,
10 | 0x20,
11 | 0x40,
12 | 0x80,
13 | 0x1b,
14 | 0x36,
15 | 0x6c,
16 | 0xd8,
17 | 0xab,
18 | 0x4d,
19 | 0x9a,
20 | 0x2f,
21 | }
22 |
23 | // FIPS-197 Figure 7. S-box substitution values in hexadecimal format.
24 | var sbox0 = [256]byte{
25 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
26 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
27 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
28 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
29 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
30 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
31 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
32 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
33 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
34 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
35 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
36 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
37 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
38 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
39 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
40 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
41 | }
42 |
43 | // FIPS-197 Figure 14. Inverse S-box substitution values in hexadecimal format.
44 | var sbox1 = [256]byte{
45 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
46 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
47 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
48 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
49 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
50 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
51 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
52 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
53 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
54 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
55 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
56 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
57 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
58 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
59 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
60 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
61 | }
62 |
63 | // Galois Field multiplication tables from
64 | // https://en.wikipedia.org/wiki/Rijndael_mix_columns#Galois_Multiplication_lookup_tables
65 |
66 | var gMulBy2 = [256]byte{
67 | 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
68 | 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
69 | 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
70 | 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
71 | 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
72 | 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
73 | 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
74 | 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
75 | 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
76 | 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
77 | 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
78 | 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
79 | 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
80 | 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
81 | 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
82 | 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5,
83 | }
84 |
85 | var gMulBy3 = [256]byte{
86 | 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
87 | 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
88 | 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
89 | 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
90 | 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
91 | 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
92 | 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
93 | 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
94 | 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
95 | 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
96 | 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
97 | 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
98 | 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
99 | 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
100 | 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
101 | 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a,
102 | }
103 |
104 | var gMulBy9 = [256]byte{
105 | 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
106 | 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
107 | 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
108 | 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
109 | 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
110 | 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
111 | 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
112 | 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
113 | 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
114 | 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
115 | 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
116 | 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
117 | 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
118 | 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
119 | 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
120 | 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46,
121 | }
122 |
123 | var gMulBy11 = [256]byte{
124 | 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
125 | 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
126 | 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
127 | 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
128 | 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
129 | 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
130 | 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
131 | 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
132 | 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
133 | 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
134 | 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
135 | 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
136 | 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
137 | 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
138 | 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
139 | 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3,
140 | }
141 |
142 | var gMulBy13 = [256]byte{
143 | 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
144 | 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
145 | 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
146 | 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
147 | 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
148 | 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
149 | 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
150 | 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
151 | 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
152 | 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
153 | 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
154 | 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
155 | 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
156 | 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
157 | 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
158 | 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97,
159 | }
160 |
161 | var gMulBy14 = [256]byte{
162 | 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
163 | 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
164 | 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
165 | 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
166 | 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
167 | 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
168 | 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
169 | 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
170 | 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
171 | 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
172 | 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
173 | 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
174 | 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
175 | 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
176 | 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
177 | 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d,
178 | }
179 |
--------------------------------------------------------------------------------
/matasano/07-aes_ecb_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "io/ioutil"
6 | "testing"
7 |
8 | "github.com/nindalf/crypto/aes"
9 | )
10 |
11 | const datafile07 = "07-data.txt"
12 |
13 | var plaintext07 = []byte{0x49, 0x27, 0x6d, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x6c, 0x20, 0xa, 0x41, 0x20, 0x72, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x27, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x6b, 0x65, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x79, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x73, 0x20, 0x79, 0x65, 0x6c, 0x6c, 0x20, 0xa, 0x49, 0x6e, 0x20, 0x65, 0x63, 0x73, 0x74, 0x61, 0x73, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x20, 0xa, 0x57, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x44, 0x4a, 0x20, 0x44, 0x65, 0x73, 0x68, 0x61, 0x79, 0x20, 0x63, 0x75, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x5a, 0x27, 0x73, 0x20, 0xa, 0x48, 0x69, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x68, 0x61, 0x72, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x67, 0x6f, 0x69, 0x6e, 0x27, 0x20, 0x63, 0x72, 0x61, 0x7a, 0x79, 0x20, 0xa, 0x56, 0x61, 0x6e, 0x69, 0x6c, 0x6c, 0x61, 0x27, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x6b, 0x65, 0x2c, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x2e, 0x20, 0xa, 0xa, 0x49, 0x27, 0x6d, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x6d, 0x79, 0x20, 0x64, 0x72, 0x75, 0x67, 0x20, 0x6b, 0x69, 0x63, 0x6b, 0x20, 0x69, 0x6e, 0x20, 0xa, 0x49, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x20, 0xa, 0x54, 0x6f, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x2c, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x73, 0x20, 0x67, 0x6f, 0x20, 0xa, 0x4d, 0x79, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x27, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x79, 0x65, 0x6c, 0x6c, 0x69, 0x6e, 0x27, 0x2c, 0x20, 0x47, 0x6f, 0x20, 0x56, 0x61, 0x6e, 0x69, 0x6c, 0x6c, 0x61, 0x20, 0x47, 0x6f, 0x21, 0x20, 0xa, 0xa, 0x53, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x20, 0x27, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0xa, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x61, 0x20, 0x64, 0x61, 0x6d, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0xa, 0x57, 0x68, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x74, 0x61, 0x72, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x74, 0x20, 0x6d, 0x65, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x27, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x67, 0x65, 0x20, 0xa, 0x54, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x64, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0xa, 0x49, 0x27, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x70, 0x68, 0x61, 0x73, 0x65, 0x20, 0xa, 0x54, 0x68, 0x65, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x73, 0x61, 0x20, 0x79, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6b, 0x20, 0xa, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x62, 0x65, 0x74, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x69, 0x64, 0x20, 0x6e, 0x27, 0x20, 0x70, 0x6c, 0x61, 0x79, 0x20, 0xa, 0xa, 0x53, 0x74, 0x61, 0x67, 0x65, 0x20, 0x32, 0x20, 0x2d, 0x2d, 0x20, 0x59, 0x65, 0x61, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x79, 0x61, 0x27, 0x20, 0x77, 0x61, 0x6e, 0x6e, 0x61, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0xa, 0x49, 0x74, 0x27, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x65, 0x61, 0x64, 0x20, 0x73, 0x6f, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x61, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x20, 0x69, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x20, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0xa, 0x31, 0x2d, 0x32, 0x2d, 0x33, 0x20, 0x59, 0x6f, 0x20, 0x2d, 0x2d, 0x20, 0x4b, 0x6e, 0x6f, 0x63, 0x6b, 0x20, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x6f, 0x64, 0x20, 0xa, 0x46, 0x6f, 0x72, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x6c, 0x75, 0x63, 0x6b, 0x2c, 0x20, 0x49, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x72, 0x68, 0x79, 0x6d, 0x65, 0x73, 0x20, 0x61, 0x74, 0x72, 0x6f, 0x63, 0x69, 0x6f, 0x75, 0x73, 0x20, 0xa, 0x53, 0x75, 0x70, 0x65, 0x72, 0x63, 0x61, 0x6c, 0x61, 0x66, 0x72, 0x61, 0x67, 0x69, 0x6c, 0x69, 0x73, 0x74, 0x69, 0x63, 0x65, 0x78, 0x70, 0x69, 0x61, 0x6c, 0x69, 0x64, 0x6f, 0x63, 0x69, 0x6f, 0x75, 0x73, 0x20, 0xa, 0x49, 0x27, 0x6d, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x74, 0x20, 0xa, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x79, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x65, 0x72, 0x20, 0x77, 0x65, 0x74, 0x2e, 0x20, 0xa, 0xa, 0x49, 0x27, 0x6d, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x53, 0x61, 0x6d, 0x73, 0x6f, 0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x53, 0x61, 0x6d, 0x73, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x44, 0x65, 0x6c, 0x69, 0x6c, 0x61, 0x68, 0x20, 0xa, 0x54, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x64, 0x65, 0x6e, 0x79, 0x69, 0x6e, 0x27, 0x2c, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x61, 0x6e, 0x67, 0x20, 0xa, 0x42, 0x75, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x27, 0x6c, 0x6c, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0xa, 0x4f, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x70, 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x20, 0xa, 0x42, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x61, 0x66, 0x65, 0x72, 0x2e, 0x20, 0xa, 0xa, 0x59, 0x6f, 0x75, 0x27, 0x6c, 0x6c, 0x20, 0x67, 0x65, 0x74, 0x20, 0x6e, 0x6f, 0x77, 0x68, 0x65, 0x72, 0x65, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x73, 0x20, 0xa, 0x53, 0x6f, 0x6f, 0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x4f, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x68, 0x6f, 0x6d, 0x65, 0x62, 0x6f, 0x64, 0x79, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x6c, 0x79, 0x20, 0x65, 0x61, 0x74, 0x20, 0xa, 0x53, 0x70, 0x61, 0x67, 0x68, 0x65, 0x74, 0x74, 0x69, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x73, 0x70, 0x6f, 0x6f, 0x6e, 0x21, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x79, 0x20, 0x69, 0x74, 0x21, 0x20, 0xa, 0xa, 0x56, 0x49, 0x50, 0x2e, 0x20, 0x56, 0x61, 0x6e, 0x69, 0x6c, 0x6c, 0x61, 0x20, 0x49, 0x63, 0x65, 0x20, 0x79, 0x65, 0x70, 0x2c, 0x20, 0x79, 0x65, 0x70, 0x2c, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x68, 0x61, 0x72, 0x64, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x72, 0x68, 0x69, 0x6e, 0x6f, 0x20, 0xa, 0x49, 0x6e, 0x74, 0x6f, 0x78, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x6e, 0x6f, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x70, 0x75, 0x6e, 0x6b, 0x73, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x20, 0x63, 0x72, 0x79, 0x69, 0x6e, 0x27, 0x20, 0xa, 0x56, 0x61, 0x6e, 0x69, 0x6c, 0x6c, 0x61, 0x20, 0x49, 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x65, 0x6c, 0x6c, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x62, 0x75, 0x79, 0x69, 0x6e, 0x27, 0x20, 0xa, 0x27, 0x43, 0x61, 0x75, 0x73, 0x65, 0x20, 0x77, 0x68, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x65, 0x61, 0x6b, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6a, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x27, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x43, 0x72, 0x61, 0x7a, 0x79, 0x20, 0x47, 0x6c, 0x75, 0x65, 0x20, 0xa, 0x4d, 0x6f, 0x76, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0xa, 0x41, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x68, 0x65, 0x74, 0x74, 0x6f, 0x20, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x67, 0x20, 0xa, 0x4e, 0x6f, 0x77, 0x20, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x61, 0x6d, 0x61, 0x7a, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x56, 0x49, 0x50, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x2e, 0x20, 0xa, 0xa, 0x53, 0x74, 0x65, 0x70, 0x70, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x6f, 0x20, 0x68, 0x61, 0x72, 0x64, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x47, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x20, 0x4e, 0x61, 0x7a, 0x69, 0x20, 0xa, 0x53, 0x74, 0x61, 0x72, 0x74, 0x6c, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x68, 0x69, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0xa, 0x54, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x74, 0x72, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x27, 0x20, 0x6f, 0x6e, 0x20, 0x6d, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0xa, 0x53, 0x70, 0x61, 0x72, 0x6b, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x2c, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x68, 0x61, 0x6e, 0x67, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x66, 0x61, 0x6e, 0x61, 0x74, 0x69, 0x63, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x20, 0x74, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x65, 0x61, 0x72, 0x20, 0xa, 0x27, 0x38, 0x39, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x21, 0x20, 0x59, 0x6f, 0x75, 0x2c, 0x20, 0x27, 0x39, 0x30, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x2e, 0x20, 0xa, 0xa, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x77, 0x65, 0x61, 0x6b, 0x65, 0x6e, 0x69, 0x6e, 0x27, 0x20, 0x66, 0x61, 0x73, 0x74, 0x2c, 0x20, 0x59, 0x4f, 0x21, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x74, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x72, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x27, 0x73, 0x20, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x68, 0x6f, 0x74, 0x2c, 0x20, 0x73, 0x6f, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x74, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x62, 0x65, 0x20, 0x73, 0x61, 0x64, 0x20, 0xa, 0x27, 0x43, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x79, 0x72, 0x69, 0x63, 0x73, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x49, 0x43, 0x45, 0x2c, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x20, 0x44, 0x61, 0x64, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x20, 0x66, 0x69, 0x74, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x75, 0x72, 0x65, 0x20, 0xa, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x64, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x49, 0x63, 0x65, 0x2c, 0x20, 0x64, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x75, 0x72, 0x65, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x75, 0x70, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x62, 0x65, 0x20, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x20, 0x77, 0x61, 0x6e, 0x6e, 0x61, 0x20, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x2d, 0x2d, 0x20, 0x41, 0x6e, 0x79, 0x74, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x79, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0xa, 0xa, 0x59, 0x6f, 0x75, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x77, 0x65, 0x61, 0x6b, 0x2c, 0x20, 0x42, 0x6f, 0x79, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x64, 0x65, 0x61, 0x64, 0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x67, 0x20, 0xa, 0xa, 0x53, 0x61, 0x79, 0x20, 0x2d, 0x2d, 0x20, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x53, 0x61, 0x79, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x20, 0x67, 0x6f, 0x20, 0xa, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x47, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0xa, 0x4c, 0x61, 0x79, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x6f, 0x67, 0x69, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x69, 0x65, 0x2e, 0x20, 0xa, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x20, 0x68, 0x65, 0x61, 0x72, 0x20, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x61, 0x79, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x20, 0x69, 0x74, 0x20, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x41, 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x6c, 0x6f, 0x75, 0x64, 0x65, 0x72, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0xa, 0x4, 0x4, 0x4, 0x4, 0x6d, 0xf0, 0x67, 0xa4, 0x81, 0x74, 0x79, 0xac, 0xaf, 0xb3, 0x2a, 0x51, 0xe1, 0xe, 0xc4, 0x42, 0x6d, 0xf0, 0x67, 0xa4, 0x81, 0x74, 0x79, 0xac, 0xaf, 0xb3, 0x2a, 0x51, 0xe1, 0xe, 0xc4, 0x42, 0x6d, 0xf0, 0x67, 0xa4, 0x81, 0x74, 0x79, 0xac, 0xaf, 0xb3, 0x2a, 0x51, 0xe1, 0xe, 0xc4, 0x42}
14 |
15 | func TestDecryptAESECB(t *testing.T) {
16 | encoded, err := ioutil.ReadFile(datafile07)
17 | if err != nil {
18 | t.Fatal(err)
19 | }
20 |
21 | b := make([]byte, (len(encoded)/4)*3)
22 | DecodeBase64(b, encoded)
23 | key := []byte("YELLOW SUBMARINE")
24 | block := aes.NewCipher(key)
25 | decrypter := newECBDecrypter(block)
26 |
27 | decrypter.CryptBlocks(b, b)
28 | if !bytes.Equal(b, plaintext07) {
29 | t.Fatalf("Plaintext was not - %s ...(truncated)", string(plaintext07[0:64]))
30 | }
31 | }
32 |
33 | func TestECBEncryptDecrypt(t *testing.T) {
34 | text := []byte("ATTACK AT DAWN!!")
35 | expected := "ATTACK AT DAWN!!"
36 |
37 | encrypter := newECBEncrypter(aesBlockCipher)
38 | encrypter.CryptBlocks(text, text)
39 | if string(text) == expected {
40 | t.Fatalf("Failed to encrypt - %s", expected)
41 | }
42 |
43 | decrypter := newECBDecrypter(aesBlockCipher)
44 | decrypter.CryptBlocks(text, text)
45 | if string(text) != expected {
46 | t.Fatalf("Failed to decrypt - %s", expected)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/matasano/10-aes_cbc_test.go:
--------------------------------------------------------------------------------
1 | package matasano
2 |
3 | import (
4 | "bytes"
5 | "crypto/rand"
6 | "io/ioutil"
7 | "testing"
8 |
9 | "github.com/nindalf/crypto/aes"
10 | )
11 |
12 | const datafile10 = "10-data.txt"
13 |
14 | var plaintext10 = []byte{0x49, 0x27, 0x6d, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x6c, 0x20, 0xa, 0x41, 0x20, 0x72, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x27, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x6b, 0x65, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x79, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x73, 0x20, 0x79, 0x65, 0x6c, 0x6c, 0x20, 0xa, 0x49, 0x6e, 0x20, 0x65, 0x63, 0x73, 0x74, 0x61, 0x73, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x20, 0xa, 0x57, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x44, 0x4a, 0x20, 0x44, 0x65, 0x73, 0x68, 0x61, 0x79, 0x20, 0x63, 0x75, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x5a, 0x27, 0x73, 0x20, 0xa, 0x48, 0x69, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x68, 0x61, 0x72, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x67, 0x6f, 0x69, 0x6e, 0x27, 0x20, 0x63, 0x72, 0x61, 0x7a, 0x79, 0x20, 0xa, 0x56, 0x61, 0x6e, 0x69, 0x6c, 0x6c, 0x61, 0x27, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x6b, 0x65, 0x2c, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x2e, 0x20, 0xa, 0xa, 0x49, 0x27, 0x6d, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x6d, 0x79, 0x20, 0x64, 0x72, 0x75, 0x67, 0x20, 0x6b, 0x69, 0x63, 0x6b, 0x20, 0x69, 0x6e, 0x20, 0xa, 0x49, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x20, 0xa, 0x54, 0x6f, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x2c, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x73, 0x20, 0x67, 0x6f, 0x20, 0xa, 0x4d, 0x79, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x27, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x79, 0x65, 0x6c, 0x6c, 0x69, 0x6e, 0x27, 0x2c, 0x20, 0x47, 0x6f, 0x20, 0x56, 0x61, 0x6e, 0x69, 0x6c, 0x6c, 0x61, 0x20, 0x47, 0x6f, 0x21, 0x20, 0xa, 0xa, 0x53, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x20, 0x27, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0xa, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x61, 0x20, 0x64, 0x61, 0x6d, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0xa, 0x57, 0x68, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x74, 0x61, 0x72, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x74, 0x20, 0x6d, 0x65, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x27, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x67, 0x65, 0x20, 0xa, 0x54, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x64, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0xa, 0x49, 0x27, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x70, 0x68, 0x61, 0x73, 0x65, 0x20, 0xa, 0x54, 0x68, 0x65, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x73, 0x61, 0x20, 0x79, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6b, 0x20, 0xa, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x62, 0x65, 0x74, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x69, 0x64, 0x20, 0x6e, 0x27, 0x20, 0x70, 0x6c, 0x61, 0x79, 0x20, 0xa, 0xa, 0x53, 0x74, 0x61, 0x67, 0x65, 0x20, 0x32, 0x20, 0x2d, 0x2d, 0x20, 0x59, 0x65, 0x61, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x79, 0x61, 0x27, 0x20, 0x77, 0x61, 0x6e, 0x6e, 0x61, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0xa, 0x49, 0x74, 0x27, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x65, 0x61, 0x64, 0x20, 0x73, 0x6f, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x61, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x20, 0x69, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x20, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0xa, 0x31, 0x2d, 0x32, 0x2d, 0x33, 0x20, 0x59, 0x6f, 0x20, 0x2d, 0x2d, 0x20, 0x4b, 0x6e, 0x6f, 0x63, 0x6b, 0x20, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x77, 0x6f, 0x6f, 0x64, 0x20, 0xa, 0x46, 0x6f, 0x72, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x6c, 0x75, 0x63, 0x6b, 0x2c, 0x20, 0x49, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x72, 0x68, 0x79, 0x6d, 0x65, 0x73, 0x20, 0x61, 0x74, 0x72, 0x6f, 0x63, 0x69, 0x6f, 0x75, 0x73, 0x20, 0xa, 0x53, 0x75, 0x70, 0x65, 0x72, 0x63, 0x61, 0x6c, 0x61, 0x66, 0x72, 0x61, 0x67, 0x69, 0x6c, 0x69, 0x73, 0x74, 0x69, 0x63, 0x65, 0x78, 0x70, 0x69, 0x61, 0x6c, 0x69, 0x64, 0x6f, 0x63, 0x69, 0x6f, 0x75, 0x73, 0x20, 0xa, 0x49, 0x27, 0x6d, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x74, 0x20, 0xa, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x79, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x65, 0x72, 0x20, 0x77, 0x65, 0x74, 0x2e, 0x20, 0xa, 0xa, 0x49, 0x27, 0x6d, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x53, 0x61, 0x6d, 0x73, 0x6f, 0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x53, 0x61, 0x6d, 0x73, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x44, 0x65, 0x6c, 0x69, 0x6c, 0x61, 0x68, 0x20, 0xa, 0x54, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x64, 0x65, 0x6e, 0x79, 0x69, 0x6e, 0x27, 0x2c, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x72, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x61, 0x6e, 0x67, 0x20, 0xa, 0x42, 0x75, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x27, 0x6c, 0x6c, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0xa, 0x4f, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x65, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x70, 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x20, 0xa, 0x42, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x61, 0x66, 0x65, 0x72, 0x2e, 0x20, 0xa, 0xa, 0x59, 0x6f, 0x75, 0x27, 0x6c, 0x6c, 0x20, 0x67, 0x65, 0x74, 0x20, 0x6e, 0x6f, 0x77, 0x68, 0x65, 0x72, 0x65, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x73, 0x20, 0xa, 0x53, 0x6f, 0x6f, 0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x4f, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x68, 0x6f, 0x6d, 0x65, 0x62, 0x6f, 0x64, 0x79, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x6c, 0x79, 0x20, 0x65, 0x61, 0x74, 0x20, 0xa, 0x53, 0x70, 0x61, 0x67, 0x68, 0x65, 0x74, 0x74, 0x69, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x73, 0x70, 0x6f, 0x6f, 0x6e, 0x21, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x79, 0x20, 0x69, 0x74, 0x21, 0x20, 0xa, 0xa, 0x56, 0x49, 0x50, 0x2e, 0x20, 0x56, 0x61, 0x6e, 0x69, 0x6c, 0x6c, 0x61, 0x20, 0x49, 0x63, 0x65, 0x20, 0x79, 0x65, 0x70, 0x2c, 0x20, 0x79, 0x65, 0x70, 0x2c, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x68, 0x61, 0x72, 0x64, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x72, 0x68, 0x69, 0x6e, 0x6f, 0x20, 0xa, 0x49, 0x6e, 0x74, 0x6f, 0x78, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x74, 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x6e, 0x6f, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x70, 0x75, 0x6e, 0x6b, 0x73, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x20, 0x63, 0x72, 0x79, 0x69, 0x6e, 0x27, 0x20, 0xa, 0x56, 0x61, 0x6e, 0x69, 0x6c, 0x6c, 0x61, 0x20, 0x49, 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x65, 0x6c, 0x6c, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x62, 0x75, 0x79, 0x69, 0x6e, 0x27, 0x20, 0xa, 0x27, 0x43, 0x61, 0x75, 0x73, 0x65, 0x20, 0x77, 0x68, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x65, 0x61, 0x6b, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6a, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x27, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x43, 0x72, 0x61, 0x7a, 0x79, 0x20, 0x47, 0x6c, 0x75, 0x65, 0x20, 0xa, 0x4d, 0x6f, 0x76, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0xa, 0x41, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x68, 0x65, 0x74, 0x74, 0x6f, 0x20, 0x67, 0x72, 0x6f, 0x6f, 0x76, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x67, 0x20, 0xa, 0x4e, 0x6f, 0x77, 0x20, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x61, 0x6d, 0x61, 0x7a, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x56, 0x49, 0x50, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x2e, 0x20, 0xa, 0xa, 0x53, 0x74, 0x65, 0x70, 0x70, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x6f, 0x20, 0x68, 0x61, 0x72, 0x64, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x47, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x20, 0x4e, 0x61, 0x7a, 0x69, 0x20, 0xa, 0x53, 0x74, 0x61, 0x72, 0x74, 0x6c, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x68, 0x69, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0xa, 0x54, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x74, 0x72, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x27, 0x20, 0x6f, 0x6e, 0x20, 0x6d, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0xa, 0x53, 0x70, 0x61, 0x72, 0x6b, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x2c, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x68, 0x61, 0x6e, 0x67, 0x69, 0x6e, 0x27, 0x20, 0x74, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x66, 0x61, 0x6e, 0x61, 0x74, 0x69, 0x63, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x20, 0x74, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x65, 0x61, 0x72, 0x20, 0xa, 0x27, 0x38, 0x39, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x21, 0x20, 0x59, 0x6f, 0x75, 0x2c, 0x20, 0x27, 0x39, 0x30, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x2e, 0x20, 0xa, 0xa, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x77, 0x65, 0x61, 0x6b, 0x65, 0x6e, 0x69, 0x6e, 0x27, 0x20, 0x66, 0x61, 0x73, 0x74, 0x2c, 0x20, 0x59, 0x4f, 0x21, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x74, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x72, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x27, 0x73, 0x20, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x27, 0x20, 0x68, 0x6f, 0x74, 0x2c, 0x20, 0x73, 0x6f, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x74, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x62, 0x65, 0x20, 0x73, 0x61, 0x64, 0x20, 0xa, 0x27, 0x43, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x79, 0x72, 0x69, 0x63, 0x73, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x49, 0x43, 0x45, 0x2c, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x20, 0x44, 0x61, 0x64, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x27, 0x20, 0x61, 0x20, 0x66, 0x69, 0x74, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x75, 0x72, 0x65, 0x20, 0xa, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x64, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x49, 0x63, 0x65, 0x2c, 0x20, 0x64, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x75, 0x72, 0x65, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x75, 0x70, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x62, 0x65, 0x20, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x20, 0xa, 0x59, 0x6f, 0x75, 0x20, 0x77, 0x61, 0x6e, 0x6e, 0x61, 0x20, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x2d, 0x2d, 0x20, 0x41, 0x6e, 0x79, 0x74, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x79, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0xa, 0xa, 0x59, 0x6f, 0x75, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x77, 0x65, 0x61, 0x6b, 0x2c, 0x20, 0x42, 0x6f, 0x79, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x64, 0x65, 0x61, 0x64, 0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0xa, 0x53, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x67, 0x20, 0xa, 0xa, 0x53, 0x61, 0x79, 0x20, 0x2d, 0x2d, 0x20, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x53, 0x61, 0x79, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x20, 0x67, 0x6f, 0x20, 0xa, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x47, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0xa, 0x4c, 0x61, 0x79, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x6f, 0x67, 0x69, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x64, 0x69, 0x65, 0x2e, 0x20, 0xa, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x20, 0x68, 0x65, 0x61, 0x72, 0x20, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x61, 0x79, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x20, 0x69, 0x74, 0x20, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x41, 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x6c, 0x6f, 0x75, 0x64, 0x65, 0x72, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x2c, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0xa, 0x50, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x6b, 0x79, 0x20, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x20, 0xa, 0x4, 0x4, 0x4, 0x4, 0x53, 0xcc, 0x47, 0x76, 0xd5, 0x12, 0x41, 0xfa, 0xae, 0xcf, 0xe1, 0xe0, 0x7f, 0x7a, 0x49, 0x23, 0x6d, 0xf0, 0x67, 0xa4, 0x81, 0x74, 0x79, 0xac, 0xaf, 0xb3, 0x2a, 0x51, 0xe1, 0xe, 0xc4, 0x42, 0x6d, 0xf0, 0x67, 0xa4, 0x81, 0x74, 0x79, 0xac, 0xaf, 0xb3, 0x2a, 0x51, 0xe1, 0xe, 0xc4, 0x42}
15 |
16 | func TestDecryptAESCBC(t *testing.T) {
17 | encoded, err := ioutil.ReadFile(datafile10)
18 | if err != nil {
19 | t.Fatal(err)
20 | }
21 | b := make([]byte, (len(encoded)/4)*3)
22 | DecodeBase64(b, encoded)
23 |
24 | key := []byte("YELLOW SUBMARINE")
25 | block := aes.NewCipher(key)
26 | iv := make([]byte, aes.BlockSize)
27 | cbcd := NewCBCDecrypter(block, iv)
28 |
29 | cbcd.CryptBlocks(b, b)
30 |
31 | if !bytes.Equal(b, plaintext10) {
32 | t.Fatalf("Plaintext was not - %s ...(truncated)", string(plaintext10[0:32]))
33 | }
34 | }
35 |
36 | func TestCBCEncryptDecrypt(t *testing.T) {
37 | text := []byte("ATTACK AT DAWN!!ATTACK AT DAWN!!ATTACK AT DAWN!!ATTACK AT DAWN!!")
38 | expected := "ATTACK AT DAWN!!ATTACK AT DAWN!!ATTACK AT DAWN!!ATTACK AT DAWN!!"
39 |
40 | iv := make([]byte, aes.BlockSize)
41 | _, err := rand.Read(iv)
42 | if err != nil {
43 | t.Fatal(err)
44 | }
45 |
46 | cbce := NewCBCEncrypter(aesBlockCipher, iv)
47 | cbce.CryptBlocks(text, text)
48 | if string(text) == expected {
49 | t.Fatalf("Failed to encrypt - %s", expected)
50 | }
51 |
52 | cbcd := NewCBCDecrypter(aesBlockCipher, iv)
53 | cbcd.CryptBlocks(text, text)
54 | if string(text) != expected {
55 | t.Fatalf("Failed to decrypt - %s", expected)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------