├── .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 | ![birthday distribution](https://upload.wikimedia.org/wikipedia/commons/c/ca/Birthday_paradox_probability.svg) 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 |
![diagram](http://i.imgur.com/a6XewSm.png)
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 |
![Agreement](http://i.imgur.com/bPZzTwsl.png)
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 | ![shiftrows](https://upload.wikimedia.org/wikipedia/commons/6/66/AES-ShiftRows.svg) 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 | ![mixcols](https://upload.wikimedia.org/wikipedia/commons/7/76/AES-MixColumns.svg) 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 |
![Three schemes of AE](http://i.imgur.com/lc3j8zq.png)
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 |
![TLS packet](http://i.imgur.com/zlIuDsh.png)
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 |
![SSH binary packet](http://i.imgur.com/voz0103.png)
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 | --------------------------------------------------------------------------------