using System;
using System.Text;
namespace Woodpecker.Security.Ciphering
{
///
/// Provides data ciphering with RC4.
///
public class rc4Provider : rc4Core
{
#region Fields
///
/// Multi-user integer.
///
private int i;
///
/// Multi-use integer.
///
private int j;
private int[] key = new int[256];
private int[] table = new int[256];
#endregion
#region Constructors
public rc4Provider(string publicKey)
{
// Reset work integers
this.i = 0;
this.j = 0;
string decodedKey = this.decodeKey(publicKey); // Decode public key
this.Initialize(decodedKey); // Initialize work integers, tables etc
this.premixTable(this.premixString); // Premix tables
}
#endregion
#region Methods
#region Initializing & premix
private void Initialize(string Key)
{
int keyValue = int.Parse(Key);
int keyLength = (keyValue & 0xf8) / 8;
if (keyLength < 20)
keyLength += 20;
int keyOffset = keyValue % keyWindow.Length;
int tGiven = keyValue;
int tOwn = 0;
int[] w = new int[keyLength];
for (int a = 0; a < keyLength; a++)
{
tOwn = keyWindow[Math.Abs((keyOffset + a) % keyWindow.Length)];
w[a] = Math.Abs(tGiven ^ tOwn);
if (a == 31)
tGiven = keyValue;
else
tGiven = (tGiven / 2);
}
for (int b = 0; b < 256; b++)
{
key[b] = w[b % w.Length];
table[b] = b;
}
int t = 0;
int u = 0;
for (int a = 0; a < 256; a++)
{
u = (int)((u + table[a] + key[a]) % 256);
t = table[a];
table[a] = table[u];
table[u] = t;
}
}
private void premixTable(string s)
{
for (int a = 0; a < 17; a++)
{
this.Encipher(s);
}
}
#endregion
#region Ciphering
public string Encipher(string s)
{
StringBuilder Ret = new StringBuilder(s.Length * 2);
int t = 0;
int k = 0;
for (int a = 0; a < s.Length; a++)
{
i = (i + 1) % 256;
j = (j + table[i]) % 256;
t = table[i];
table[i] = table[j];
table[j] = t;
k = table[(table[i] + table[j]) % 256];
int c = (char)s.Substring(a, 1).ToCharArray()[0] ^ k;
if (c <= 0)
Ret.Append("00");
else
{
Ret.Append(di[c >> 4 & 0xf]);
Ret.Append(di[c & 0xf]);
}
}
return Ret.ToString();
}
public string Decipher(string s)
{
try
{
StringBuilder Ret = new StringBuilder(s.Length);
int t = 0;
int k = 0;
for (int a = 0; a < s.Length; a += 2)
{
i = (i + 1) % 256;
j = (j + table[i]) % 256;
t = table[i];
table[i] = table[j];
table[j] = t;
k = table[(table[i] + table[j]) % 256];
t = System.Convert.ToInt32(this.JavaSubstring(s, a, a + 2), 16);
Ret = Ret.Append((char)(t ^ k));
}
return Ret.ToString();
}
catch { return ""; }
}
#endregion
#endregion
}
}