Check out the Pastebin Gadgets Shop. We have thousands of fun, geeky & affordable gadgets on sale :-)Want more features on Pastebin? Sign Up, it's FREE!

# A trivial distinguishing attack against RC4

By: a guest on Oct 19th, 2013  |  syntax: Python  |  size: 2.61 KB  |  views: 148  |  expires: Never
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
1. #!/usr/bin/env python
2. def rc4crypt(data, key):
3.     x = 0
4.     box = range(256)
5.     for i in range(256):
6.         x = (x + box[i] + key[i % len(key)]) % 256
7.         box[i], box[x] = box[x], box[i]
8.     x = 0
9.     y = 0
10.     out = []
11.     for byte in data:
12.         x = (x + 1) % 256
13.         y = (y + box[x]) % 256
14.         box[x], box[y] = box[y], box[x]
15.         out.append(byte ^ box[(box[x] + box[y]) % 256])
16.     return out
17.
18. def check_rc4_test_vector():
19.     data = [0]*16
20.     key = [0x01,0x02,0x03,0x04,0x05]
21.     # See RFC 6229
22.     testVector = [0xb2,0x39,0x63,0x05,0xf0,0x3d,0xc0,0x27,0xcc,0xc3,0x52,0x4a,0x0a,0x11,0x18,0xa8]
23.
24.     output = rc4crypt(data, key)
25.
26.     if (output != testVector):
27.         print "=== Test Vectors Failed ==="
28.     else:
29.         print "=== Test Vectors Passed ==="
30.
31. def get_rand_bytes(numberOfBytes):
32.     out = []
33.     file = open("/dev/urandom")
34.     data = file.read(numberOfBytes)
35.     for byte in data:
36.         out.append(ord(byte))
37.     file.close()
38.     return out
39.
40. class Challenger:
41.     def __init__(self):
42.         self.whichMessage = self.select_message()
43.
44.     def select_message(self):
45.         byte = get_rand_bytes(1)[0]
46.         if byte & 1 == 0:
47.             return "m0"
48.         else:
49.             return "m1"
50.
51.     def Challenge(self,m0, m1):
52.         key = get_rand_bytes(16)
53.         if (self.whichMessage == "m0"):
54.             return rc4crypt(m0, key)
55.         elif (self.whichMessage == "m1"):
56.             return rc4crypt(m1, key)
57.
58. class Attacker:
59.     def __init__(self, challenger):
60.         self.challenger = challenger
61.
62.     def attack(self, numberOfTries):
63.         byteHistogram = [0] * 256
64.         m0 = [0,0]
65.         m1 = [255,255]
66.         for i in range(1, numberOfTries):
67.             result = self.challenger.Challenge(m0, m1)
68.             byteHistogram[result[1]]+=1
69.
70.         if byteHistogram[0] > byteHistogram[255]:
71.             return "m0"
72.         else:
73.             return "m1"
74.
75. def main():
76.     import argparse
77.     parser = argparse.ArgumentParser(description='This program demonstrates a trivial distinguishing attack on RC4 under the same message being encrypted under many keys.')
78.     parser.add_argument('--trials', type=int,help='Set the number of times the attacker should iterate for.',default=2000)
79.
80.     check_rc4_test_vector()
81.
82.     challenger = Challenger()
83.     print "Challenger says: " + challenger.whichMessage
84.
85.     args = parser.parse_args()
86.     attacker = Attacker(challenger)
87.     result = attacker.attack(args.trials)
88.     print "Attacker says: " + result
89.
90.
91. if __name__ == "__main__":
92.     main()
clone this paste RAW Paste Data
Top