You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
4.0 KiB
137 lines
4.0 KiB
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) |
|
#pragma warning disable |
|
using System; |
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters; |
|
|
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines |
|
{ |
|
public class VmpcEngine |
|
: IStreamCipher |
|
{ |
|
/* |
|
* variables to hold the state of the VMPC engine during encryption and |
|
* decryption |
|
*/ |
|
protected byte n = 0; |
|
protected byte[] P = null; |
|
protected byte s = 0; |
|
|
|
protected byte[] workingIV; |
|
protected byte[] workingKey; |
|
|
|
public virtual string AlgorithmName |
|
{ |
|
get { return "VMPC"; } |
|
} |
|
|
|
/** |
|
* initialise a VMPC cipher. |
|
* |
|
* @param forEncryption |
|
* whether or not we are for encryption. |
|
* @param params |
|
* the parameters required to set up the cipher. |
|
* @exception ArgumentException |
|
* if the params argument is inappropriate. |
|
*/ |
|
public virtual void Init( |
|
bool forEncryption, |
|
ICipherParameters parameters) |
|
{ |
|
if (!(parameters is ParametersWithIV)) |
|
throw new ArgumentException("VMPC Init parameters must include an IV"); |
|
|
|
ParametersWithIV ivParams = (ParametersWithIV) parameters; |
|
|
|
if (!(ivParams.Parameters is KeyParameter)) |
|
throw new ArgumentException("VMPC Init parameters must include a key"); |
|
|
|
KeyParameter key = (KeyParameter)ivParams.Parameters; |
|
|
|
this.workingIV = ivParams.GetIV(); |
|
|
|
if (workingIV == null || workingIV.Length < 1 || workingIV.Length > 768) |
|
throw new ArgumentException("VMPC requires 1 to 768 bytes of IV"); |
|
|
|
this.workingKey = key.GetKey(); |
|
|
|
InitKey(this.workingKey, this.workingIV); |
|
} |
|
|
|
protected virtual void InitKey( |
|
byte[] keyBytes, |
|
byte[] ivBytes) |
|
{ |
|
s = 0; |
|
P = new byte[256]; |
|
for (int i = 0; i < 256; i++) |
|
{ |
|
P[i] = (byte) i; |
|
} |
|
|
|
for (int m = 0; m < 768; m++) |
|
{ |
|
s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.Length]) & 0xff]; |
|
byte temp = P[m & 0xff]; |
|
P[m & 0xff] = P[s & 0xff]; |
|
P[s & 0xff] = temp; |
|
} |
|
for (int m = 0; m < 768; m++) |
|
{ |
|
s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.Length]) & 0xff]; |
|
byte temp = P[m & 0xff]; |
|
P[m & 0xff] = P[s & 0xff]; |
|
P[s & 0xff] = temp; |
|
} |
|
n = 0; |
|
} |
|
|
|
public virtual void ProcessBytes( |
|
byte[] input, |
|
int inOff, |
|
int len, |
|
byte[] output, |
|
int outOff) |
|
{ |
|
Check.DataLength(input, inOff, len, "input buffer too short"); |
|
Check.OutputLength(output, outOff, len, "output buffer too short"); |
|
|
|
for (int i = 0; i < len; i++) |
|
{ |
|
s = P[(s + P[n & 0xff]) & 0xff]; |
|
byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff]; |
|
// encryption |
|
byte temp = P[n & 0xff]; |
|
P[n & 0xff] = P[s & 0xff]; |
|
P[s & 0xff] = temp; |
|
n = (byte) ((n + 1) & 0xff); |
|
|
|
// xor |
|
output[i + outOff] = (byte) (input[i + inOff] ^ z); |
|
} |
|
} |
|
|
|
public virtual void Reset() |
|
{ |
|
InitKey(this.workingKey, this.workingIV); |
|
} |
|
|
|
public virtual byte ReturnByte( |
|
byte input) |
|
{ |
|
s = P[(s + P[n & 0xff]) & 0xff]; |
|
byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff]; |
|
// encryption |
|
byte temp = P[n & 0xff]; |
|
P[n & 0xff] = P[s & 0xff]; |
|
P[s & 0xff] = temp; |
|
n = (byte) ((n + 1) & 0xff); |
|
|
|
// xor |
|
return (byte) (input ^ z); |
|
} |
|
} |
|
} |
|
#pragma warning restore |
|
#endif
|
|
|