Posted By

weilawei on 05/10/12


Tagged

stream Encryption cipher alleged RC4 ARC4 arcfour


Versions (?)

ARC4


 / Published in: Python
 

This is a pure Python implementation of ARC4 as a generator to highlight its nature as a stream cipher. Several improvements can be made, for instance, it could take a nonce, use multiple state spaces (parallelizable), automatically discard the first 4K of the state space(s), use a more complex transformation than a simple swap, limit the # of bytes encrypted per nonce, etc.. The size of the state space is a parameter. The size of the key must not exceed the size of the state space, as additional key data will not be mixed into the prepared state.

  1. #!/usr/bin/env python3
  2.  
  3. def prepare_state(key, state_size=256):
  4. key_size = len(key)
  5. state = [i for i in range(state_size)]
  6. j = 0
  7.  
  8. for i in range(state_size):
  9. j = (j + state[i] + key[i % key_size]) % state_size
  10.  
  11. state[i] ^= state[j]
  12. state[j] ^= state[i]
  13. state[i] ^= state[j]
  14.  
  15. return state
  16.  
  17. def pseudorandom_generator(state):
  18. size = len(state)
  19. i = 0
  20. j = 0
  21.  
  22. while True:
  23. i = (i + 1) % size
  24. j = (j + state[i]) % size
  25.  
  26. state[i] ^= state[j]
  27. state[j] ^= state[i]
  28. state[i] ^= state[j]
  29.  
  30. yield state[(state[i] + state[j]) % size]
  31.  
  32. def ARC4(key, text):
  33. state = prepare_state(key)
  34. keystream = pseudorandom_generator(state)
  35.  
  36. for key_byte, text_byte in zip(keystream, text):
  37. yield key_byte ^ text_byte
  38.  
  39. # Test Vectors for ARC4
  40. # ---------------------
  41. #
  42. # key: b'Key'
  43. # plaintext: b'Plaintext'
  44. # ciphertext: b'\xbb\xf3\x16\xe8\xd9@\xaf\n\xd3'
  45. #
  46. # key: b'Wiki'
  47. # plaintext: b'pedia'
  48. # ciphertext: b'\x10!\xbf\x04 '
  49. #
  50. # key: b'Secret'
  51. # plaintext: b'Attack at dawn'
  52. # ciphertext: b'E\xa0\x1fd_\xc3[85RTK\x9b\xf5'
  53.  
  54. # Example usage
  55. if (__name__ == "__main__"):
  56. from pprint import pprint as pp
  57.  
  58. encryption = ARC4(b'Key', b'Plaintext')
  59. ciphertext = bytes([next(encryption) for i in range(len(b'Plaintext'))])
  60. pp(ciphertext)
  61.  
  62. decryption = ARC4(b'Key', ciphertext)
  63. plaintext = bytes([next(decryption) for i in range(len(ciphertext))])
  64. pp(plaintext)

Report this snippet  

You need to login to post a comment.