2 // ARC4Managed.cs: Alleged RC4(tm) compatible symmetric stream cipher
3 // RC4 is a trademark of RSA Security
7 using System.Security.Cryptography;
9 namespace Mono.Security.Cryptography {
12 // a. Usenet 1994 - RC4 Algorithm revealed
13 // http://www.qrst.de/html/dsds/rc4.htm
15 public class ARC4Managed : RC4, ICryptoTransform {
21 private bool m_disposed;
23 public ARC4Managed () : base ()
25 state = new byte [256];
34 protected override void Dispose (bool disposing)
40 Array.Clear (key, 0, key.Length);
43 Array.Clear (state, 0, state.Length);
45 GC.SuppressFinalize (this);
50 public override byte[] Key {
51 get { return (byte[]) key.Clone (); }
53 key = (byte[]) value.Clone ();
58 public bool CanReuseTransform {
62 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgvIV)
65 return (ICryptoTransform) this;
68 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgvIV)
71 return CreateEncryptor ();
74 public override void GenerateIV ()
76 // not used for a stream cipher
80 public override void GenerateKey ()
82 Key = KeyBuilder.Key (KeySizeValue >> 3);
85 public bool CanTransformMultipleBlocks {
89 public int InputBlockSize {
93 public int OutputBlockSize {
97 private void KeySetup (byte[] key)
102 for (int counter = 0; counter < 256; counter++)
103 state [counter] = (byte) counter;
106 for (int counter = 0; counter < 256; counter++) {
107 index2 = (byte) (key [index1] + state [counter] + index2);
109 byte tmp = state [counter];
110 state [counter] = state [index2];
111 state [index2] = tmp;
112 index1 = (byte) ((index1 + 1) % key.Length);
116 public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
119 for (int counter = 0; counter < inputCount; counter ++) {
121 y = (byte) (state [x] + y);
123 byte tmp = state [x];
124 state [x] = state [y];
127 xorIndex = (byte) (state [x] + state [y]);
128 outputBuffer [outputOffset + counter] = (byte) (inputBuffer [inputOffset + counter] ^ state [xorIndex]);
133 public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
135 byte[] output = new byte [inputCount];
136 TransformBlock (inputBuffer, inputOffset, inputCount, output, 0);