Created
July 3, 2011 09:06
-
-
Save dchest/1062092 to your computer and use it in GitHub Desktop.
Example of meet-in-the-middle attack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Written by Dmitry Chestnykh. Public domain. | |
package main | |
import ( | |
"crypto/blowfish" | |
"fmt" | |
"time" | |
) | |
func encrypt(key uint8, src string) string { | |
c, _ := blowfish.NewCipher([]byte{key, 0, 0, 0}) | |
b := make([]byte, 8) | |
c.Encrypt(b, []byte(src)) | |
return string(b) | |
} | |
func decrypt(key uint8, src string) string { | |
c, _ := blowfish.NewCipher([]byte{key, 0, 0, 0}) | |
b := make([]byte, 8) | |
c.Decrypt(b, []byte(src)) | |
return string(b) | |
} | |
func doubleEncrypt(key []uint8, src string) string { | |
return encrypt(key[1], encrypt(key[0], src)) | |
} | |
func encryptWithAllKeys(plaintext string) (r map[string]uint8) { | |
r = make(map[string]uint8, 256) | |
for i := 0; i < 256; i++ { | |
s := encrypt(uint8(i), plaintext) | |
r[s] = uint8(i) | |
} | |
return | |
} | |
const ( | |
reportFmt = "Key: \"%c%c\"\tOperations: %d\n" | |
notFoundFmt = "No keys founds in %d operations\n" | |
) | |
func bruteforce(plaintext, ciphertext string) { | |
op := 0 | |
for i := 0; i < 256; i++ { | |
s1 := decrypt(uint8(i), ciphertext) | |
for j := 0; j < 256; j++ { | |
op++ | |
if decrypt(uint8(j), s1) == plaintext { | |
fmt.Printf(reportFmt, j, i, op) | |
return | |
} | |
} | |
} | |
fmt.Printf(notFoundFmt, op) | |
} | |
func meetInTheMiddle(plaintext, ciphertext string) { | |
ekp := encryptWithAllKeys(plaintext) | |
op := len(ekp) | |
for i := 0; i < 256; i++ { | |
s := decrypt(uint8(i), ciphertext) | |
op++ | |
if k, ok := ekp[s]; ok { | |
fmt.Printf(reportFmt, k, i, op) | |
return | |
} | |
} | |
fmt.Printf(notFoundFmt, op) | |
} | |
func measure(name string, f func()) { | |
t := time.Nanoseconds() | |
f() | |
fmt.Printf("%s: %.2f sec\n\n", name, float64(time.Nanoseconds()-t)/1.0e9) | |
} | |
func main() { | |
plaintext := "Dear Bob" // must be exactly 8 bytes | |
key := []byte("Go") // must be exactly 2 bytes | |
ciphertext := doubleEncrypt(key, plaintext) | |
fmt.Printf("Plain-text: %q\n", plaintext) | |
fmt.Printf("Ciphertext: %q\n\n", ciphertext) | |
measure("Bruteforce", func() { | |
bruteforce(plaintext, ciphertext) | |
}) | |
measure("Meet-in-the-middle", func() { | |
meetInTheMiddle(plaintext, ciphertext) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Meet-in-the-middle attack on a 16-bit cipher derived from a 8-bit cipher by encrypting text with two 8-bit keys keys.
See http://en.wikipedia.org/wiki/Meet-in-the-middle_attack