cryptol/examples/maliciousSHA/malicious_SHA1.cry

176 lines
7.7 KiB
Plaintext
Executable File

/*
* Copyright (c) 2004, 2013-2014 Galois, Inc.
* Distributed under the terms of the BSD3 license (see LICENSE file)
*/
// Description of SHA1 at http://www.itl.nist.gov/fipspubs/fip180-4.htm
/* WARNING: This file represents a collision in a malicious SHA-1. It is modified
* to take initialization as an input. This interface to SHA-1 should not
* be used. The collision presented here, description, and paper can be found
* at http://malicioussha1.github.io/
* The Malicious SHA-1 project is a joint work of
* Ange Albertini (Corkami, Germany)
* Jean-Philippe Aumasson (Kudelski Security, Switzerland)
* Maria Eichlseder (Graz University of Technology, Austria)
* Florian Mendel (Graz University of Technology, Austria)
* Martin Schlaeffer (Graz University of Technology, Austria)
*
* Research paper at http://malicioussha1.github.io/doc/malsha1.pdf
*/
malicious_sha1 msg k = malicious_sha1' rmsg k
where
rmsg = pad(join(reverse (groupBy`{8} (join (reverse eve1)))))
malicious_sha1' : {chunks} (fin chunks) => [chunks][512] -> [4][32] -> [160]
malicious_sha1' pmsg k = join (Hs!0)
where
Hs = [[0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]] #
[ malicious_block (H, split(M)) k
| H <- Hs
| M <- pmsg
]
//hexdump of file available at http://malicioussha1.github.io/pocs/eve1.sh
//when executed will print an ascii cow
eve1 = [
0x1d23, 0x911b, 0x4034, 0xd809, 0x4d10, 0xd3a6, 0xe154, 0x2b10,
0x85b8, 0x5b12, 0x7847, 0xbd26, 0x37fd, 0xee2b, 0x50e6, 0x2c08,
0x4b75, 0x5716, 0x1138, 0xd8bf, 0xe0a5, 0x44b2, 0x941a, 0x2a51,
0x36cd, 0x04a2, 0xe2fe, 0x9f8a, 0x5532, 0xaa99, 0x7ab4, 0x82ed,
0x0a0a, 0x6669, 0x5b20, 0x6020, 0x646f, 0x2d20, 0x2074, 0x3178,
0x2d20, 0x336a, 0x2d20, 0x314e, 0x2d20, 0x6e41, 0x2220, 0x7b24,
0x7d30, 0x6022, 0x2d20, 0x7165, 0x2220, 0x3139, 0x2022, 0x3b5d,
0x7420, 0x6568, 0x206e, 0x200a, 0x6520, 0x6863, 0x206f, 0x2022,
0x2020, 0x2020, 0x2020, 0x2020, 0x5f28, 0x295f, 0x6e5c, 0x2020,
0x2020, 0x2020, 0x2020, 0x2820, 0x6f6f, 0x5c29, 0x206e, 0x2f20,
0x2d2d, 0x2d2d, 0x2d2d, 0x5c2d, 0x2f5c, 0x6e5c, 0x2f20, 0x7c20,
0x2020, 0x2020, 0x7c20, 0x5c7c, 0x2a6e, 0x2020, 0x7c7c, 0x2d2d,
0x2d2d, 0x7c7c, 0x6e5c, 0x2020, 0x5e20, 0x205e, 0x2020, 0x5e20,
0x225e, 0x0a3b, 0x6c65, 0x6573, 0x200a, 0x6520, 0x6863, 0x206f,
0x4822, 0x6c65, 0x6f6c, 0x5720, 0x726f, 0x646c, 0x222e, 0x0a3b,
0x6966, 0x000a]
//hexdump of file available at http://malicioussha1.github.io/pocs/eve2.sh
//when executed will print "hello world"
//The ascii cow and hello world can be switched out in both files
//and the hashes will still collide. The next example shows this
eve2 = [
0x1d23, 0x921b, 0x4014, 0xac09, 0x4d98, 0xd3a6, 0xe1bc, 0x4910,
0x8570, 0x1812, 0x786f, 0xb926, 0x37bd, 0xac2b, 0x50ae, 0x6a08,
0x4bfd, 0x5516, 0x1138, 0xccbf, 0xe0ad, 0x46b2, 0x94ba, 0x7e51,
0x3645, 0x06a2, 0xe27e, 0x9f8a, 0x559a, 0xa999, 0x7a1c, 0xe2ed,
0x0a0a, 0x6669, 0x5b20, 0x6020, 0x646f, 0x2d20, 0x2074, 0x3178,
0x2d20, 0x336a, 0x2d20, 0x314e, 0x2d20, 0x6e41, 0x2220, 0x7b24,
0x7d30, 0x6022, 0x2d20, 0x7165, 0x2220, 0x3139, 0x2022, 0x3b5d,
0x7420, 0x6568, 0x206e, 0x200a, 0x6520, 0x6863, 0x206f, 0x2022,
0x2020, 0x2020, 0x2020, 0x2020, 0x5f28, 0x295f, 0x6e5c, 0x2020,
0x2020, 0x2020, 0x2020, 0x2820, 0x6f6f, 0x5c29, 0x206e, 0x2f20,
0x2d2d, 0x2d2d, 0x2d2d, 0x5c2d, 0x2f5c, 0x6e5c, 0x2f20, 0x7c20,
0x2020, 0x2020, 0x7c20, 0x5c7c, 0x2a6e, 0x2020, 0x7c7c, 0x2d2d,
0x2d2d, 0x7c7c, 0x6e5c, 0x2020, 0x5e20, 0x205e, 0x2020, 0x5e20,
0x225e, 0x0a3b, 0x6c65, 0x6573, 0x200a, 0x6520, 0x6863, 0x206f,
0x4822, 0x6c65, 0x6f6c, 0x5720, 0x726f, 0x646c, 0x222e, 0x0a3b,
0x6966, 0x000a]
//K from proof-of-concept section of http://malicioussha1.github.io/#downloads
malicious_k1 = [0x5a827999, 0x88e8ea68, 0x578059de, 0x54324a39]
bad_sha_eve1 = malicious_sha1 eve1 malicious_k1
bad_sha_eve2 = malicious_sha1 eve2 malicious_k1
property malicious_sha1_collision1 = eve1 != eve2 && bad_sha_eve1 == bad_sha_eve2
//hexdump malicious/eve1.sh
eve1_galois = [
0x1d23, 0x911b, 0x4034, 0xd809, 0x4d10, 0xd3a6, 0xe154, 0x2b10,
0x85b8, 0x5b12, 0x7847, 0xbd26, 0x37fd, 0xee2b, 0x50e6, 0x2c08,
0x4b75, 0x5716, 0x1138, 0xd8bf, 0xe0a5, 0x44b2, 0x941a, 0x2a51,
0x36cd, 0x04a2, 0xe2fe, 0x9f8a, 0x5532, 0xaa99, 0x7ab4, 0x82ed,
0x0a0a, 0x6669, 0x5b20, 0x6020, 0x646f, 0x2d20, 0x2074, 0x3178,
0x2d20, 0x336a, 0x2d20, 0x314e, 0x2d20, 0x6e41, 0x2220, 0x7b24,
0x7d30, 0x6022, 0x2d20, 0x7165, 0x2220, 0x3139, 0x2022, 0x3b5d,
0x7420, 0x6568, 0x206e, 0x200a, 0x6520, 0x6863, 0x206f, 0x4322,
0x7972, 0x7470, 0x6c6f, 0x3b22, 0x650a, 0x736c, 0x0a65, 0x2020,
0x6365, 0x6f68, 0x2220, 0x6147, 0x6f6c, 0x7369, 0x3b22, 0x660a,
0x0a69]
//hexdump malicious/eve1.sh
eve2_galois = [
0x1d23, 0x921b, 0x4014, 0xac09, 0x4d98, 0xd3a6, 0xe1bc, 0x4910,
0x8570, 0x1812, 0x786f, 0xb926, 0x37bd, 0xac2b, 0x50ae, 0x6a08,
0x4bfd, 0x5516, 0x1138, 0xccbf, 0xe0ad, 0x46b2, 0x94ba, 0x7e51,
0x3645, 0x06a2, 0xe27e, 0x9f8a, 0x559a, 0xa999, 0x7a1c, 0xe2ed,
0x0a0a, 0x6669, 0x5b20, 0x6020, 0x646f, 0x2d20, 0x2074, 0x3178,
0x2d20, 0x336a, 0x2d20, 0x314e, 0x2d20, 0x6e41, 0x2220, 0x7b24,
0x7d30, 0x6022, 0x2d20, 0x7165, 0x2220, 0x3139, 0x2022, 0x3b5d,
0x7420, 0x6568, 0x206e, 0x200a, 0x6520, 0x6863, 0x206f, 0x4322,
0x7972, 0x7470, 0x6c6f, 0x3b22, 0x650a, 0x736c, 0x0a65, 0x2020,
0x6365, 0x6f68, 0x2220, 0x6147, 0x6f6c, 0x7369, 0x3b22, 0x660a,
0x0a69]
bad_sha_eve_galois1 = malicious_sha1 eve1_galois malicious_k1
bad_sha_eve_galois2 = malicious_sha1 eve2_galois malicious_k1
property malicious_sha1_collision2 = eve1_galois != eve2_galois && bad_sha_eve_galois1 == bad_sha_eve_galois2
property all_same_hashes = bad_sha_eve_galois1 == bad_sha_eve1 && malicious_sha1_collision1 && malicious_sha1_collision2
/*
As a summary, a "1" followed by m "0"s followed by a 64-
bit integer are appended to the end of the message to produce a
padded message of length 512 * n. The 64-bit integer is the length
of the original message. The padded message is then processed by the
SHA-1 as n 512-bit blocks.
*/
pad : {msgLen,contentLen,chunks,padding}
( fin msgLen
, 64 >= width msgLen // message width fits in a word
, contentLen == msgLen + 65 // message + header
, chunks == (contentLen+511) / 512
, padding == (512 - contentLen % 512) % 512 // prettier if type #'s could be < 0
, msgLen == 512 * chunks - (65 + padding) // redundant, but Cryptol can't yet do the math
)
=> [msgLen] -> [chunks][512]
pad msg = split (msg # [True] # (zero:[padding]) # (`msgLen:[64]))
f : ([8], [32], [32], [32]) -> [32]
f (t, x, y, z) =
if (0 <= t) && (t <= 19) then (x && y) ^ (~x && z)
| (20 <= t) && (t <= 39) then x ^ y ^ z
| (40 <= t) && (t <= 59) then (x && y) ^ (x && z) ^ (y && z)
| (60 <= t) && (t <= 79) then x ^ y ^ z
else error "f: t out of range"
Ks : [4][32] -> [80][32]
Ks k = [ k@0 | t <- [0..19] ]
# [ k@1 | t <- [20..39] ]
# [ k@2 | t <- [40..59] ]
# [ k@3 | t <- [60..79] ]
malicious_block : ([5][32], [16][32]) -> [4][32]-> [5][32]
malicious_block ([H0, H1, H2, H3, H4], M) k =
[(H0+As@80), (H1+Bs@80), (H2+Cs@80), (H3+Ds@80), (H4+Es@80)]
where
Ws : [80][32]
Ws = M # [ (W3 ^ W8 ^ W14 ^ W16) <<< 1
| W16 <- drop`{16 - 16} Ws
| W14 <- drop`{16 - 14} Ws
| W8 <- drop`{16 - 8} Ws
| W3 <- drop`{16 - 3} Ws
| t <- [16..79]
]
As = [H0] # TEMP
Bs = [H1] # As
Cs = [H2] # [ B <<< 30 | B <- Bs ]
Ds = [H3] # Cs
Es = [H4] # Ds
TEMP : [80][32]
TEMP = [ (A <<< 5) + f(t, B, C, D) + E + W + K
| A <- As | B <- Bs | C <- Cs | D <- Ds | E <- Es
| W <- Ws | K <- (Ks k)
| t <- [0..79]
]