Advertisement
Guest User

A trivial distinguishing attack against RC4

a guest
Oct 19th, 2013
540
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.61 KB | None | 0 0
  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()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement