NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/Net/rc4.cs

119 lines
2.3 KiB
C#

using System;
using System.IO;
namespace Framework
{
public class RC4Cipher
{
private uint[] s = new uint[256];
private byte i, j;
public RC4Cipher(byte[] key) {
int k = key.Length;
if (k < 1 || k > 256) {
throw new RC4KeySizeException(k);
}
for (uint i = 0; i < 256; i++) {
s[i] = i;
}
byte j = 0;
uint t = 0;
for (int i = 0; i < 256; i++) {
j = (byte)(j + s[i] + key[i % k]);
t = s[i];
s[i] = s[j];
s[j] = t;
}
}
public void XORKeyStream(byte[] dst, int dstOffset, byte[] src, int srcOffset, int count) {
if (count == 0)
return;
byte i = this.i;
byte j = this.j;
uint t = 0;
for (int k = 0; k < count; k ++) {
i += 1;
j = (byte)(s[i] + j);
t = s[i];
s[i] = s[j];
s[j] = t;
dst[k + dstOffset] = (byte)(src[k + srcOffset] ^ (byte)(s[(byte)(s[i] + s[j])]));
}
this.i = i;
this.j = j;
}
}
public class RC4Stream : Stream
{
private Stream stream;
private RC4Cipher cipher;
public RC4Stream(Stream stream, byte[] key) {
this.stream = stream;
this.cipher = new RC4Cipher(key);
}
public override int Read(byte[] buffer, int offset, int count) {
count = stream.Read(buffer, offset, count);
cipher.XORKeyStream(buffer, offset, buffer, offset, count);
return count;
}
public override void Write(byte[] buffer, int offset, int count) {
byte[] dst = new byte[count];
cipher.XORKeyStream(dst, 0, buffer, offset, count);
stream.Write(dst, 0, count);
}
public override bool CanRead {
get { return stream.CanRead; }
}
public override bool CanSeek {
get { return stream.CanSeek; }
}
public override bool CanWrite {
get { return stream.CanWrite; }
}
public override long Length {
get { return stream.Length; }
}
public override long Position {
get { return stream.Position; }
set { stream.Position = value; }
}
public override long Seek(long offset, SeekOrigin origin) {
return stream.Seek(offset, origin);
}
public override void SetLength(long length) {
stream.SetLength(length);
}
public override void Flush() {
stream.Flush();
}
}
public class RC4KeySizeException : Exception
{
private int size;
public RC4KeySizeException(int size) {
this.size = size;
}
public override string Message {
get { return "RC4Stream: invalid key size " + size; }
}
}
}