150 lines
5.2 KiB
C#
150 lines
5.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace BF
|
|
{
|
|
public class NetAesEncrypt : SymmetricAlgorithm
|
|
{
|
|
private readonly byte[] _counter;
|
|
private readonly AesManaged _aes;
|
|
|
|
private ICryptoTransform ict;
|
|
|
|
public byte[] aesKey { get; set; }
|
|
|
|
public NetAesEncrypt(byte[] counter)
|
|
{
|
|
if (counter == null) throw new ArgumentNullException("counter");
|
|
if (counter.Length != 16)
|
|
throw new ArgumentException(String.Format("Counter size must be same as block size (actual: {0}, expected: {1})",
|
|
counter.Length, 16));
|
|
|
|
_aes = new AesManaged
|
|
{
|
|
Mode = CipherMode.ECB,
|
|
Padding = PaddingMode.None
|
|
};
|
|
|
|
_counter = counter;
|
|
}
|
|
|
|
public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] ignoredParameter)
|
|
{
|
|
return new CounterModeCryptoTransform(_aes, rgbKey, _counter);
|
|
}
|
|
|
|
public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] ignoredParameter)
|
|
{
|
|
return new CounterModeCryptoTransform(_aes, rgbKey, _counter);
|
|
}
|
|
|
|
public override void GenerateKey()
|
|
{
|
|
_aes.GenerateKey();
|
|
}
|
|
|
|
public override void GenerateIV()
|
|
{
|
|
// IV not needed in Counter Mode
|
|
}
|
|
|
|
public void Encrypt(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
|
{
|
|
if(this.ict == null)
|
|
{
|
|
this.ict = CreateEncryptor(this.aesKey, null);
|
|
}
|
|
this.ict.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
|
|
}
|
|
|
|
public void Decrypt(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
|
{
|
|
if(this.ict == null)
|
|
{
|
|
this.ict = CreateDecryptor(this.aesKey, null);
|
|
}
|
|
this.ict.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
|
|
}
|
|
}
|
|
|
|
public class CounterModeCryptoTransform : ICryptoTransform
|
|
{
|
|
private readonly byte[] _counter;
|
|
private readonly ICryptoTransform _counterEncryptor;
|
|
private readonly Queue<byte> _xorMask = new Queue<byte>();
|
|
private readonly SymmetricAlgorithm _symmetricAlgorithm;
|
|
|
|
public CounterModeCryptoTransform(SymmetricAlgorithm symmetricAlgorithm, byte[] key, byte[] counter)
|
|
{
|
|
if (symmetricAlgorithm == null) throw new ArgumentNullException("symmetricAlgorithm");
|
|
if (key == null) throw new ArgumentNullException("key");
|
|
if (counter == null) throw new ArgumentNullException("counter");
|
|
if (counter.Length != symmetricAlgorithm.BlockSize / 8)
|
|
throw new ArgumentException(String.Format("Counter size must be same as block size (actual: {0}, expected: {1})",
|
|
counter.Length, symmetricAlgorithm.BlockSize / 8));
|
|
|
|
_symmetricAlgorithm = symmetricAlgorithm;
|
|
_counter = counter;
|
|
|
|
var zeroIv = new byte[_symmetricAlgorithm.BlockSize / 8];
|
|
_counterEncryptor = symmetricAlgorithm.CreateEncryptor(key, zeroIv);
|
|
}
|
|
|
|
public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
|
|
{
|
|
var output = new byte[inputCount];
|
|
TransformBlock(inputBuffer, inputOffset, inputCount, output, 0);
|
|
return output;
|
|
}
|
|
|
|
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
|
{
|
|
for (var i = 0; i < inputCount; i++)
|
|
{
|
|
if (NeedMoreXorMaskBytes()) EncryptCounterThenIncrement();
|
|
|
|
var mask = _xorMask.Dequeue();
|
|
outputBuffer[outputOffset + i] = (byte)(inputBuffer[inputOffset + i] ^ mask);
|
|
}
|
|
|
|
return inputCount;
|
|
}
|
|
|
|
private bool NeedMoreXorMaskBytes()
|
|
{
|
|
return _xorMask.Count == 0;
|
|
}
|
|
|
|
private void EncryptCounterThenIncrement()
|
|
{
|
|
var counterModeBlock = new byte[_symmetricAlgorithm.BlockSize / 8];
|
|
|
|
_counterEncryptor.TransformBlock(_counter, 0, _counter.Length, counterModeBlock, 0);
|
|
IncrementCounter();
|
|
|
|
foreach (var b in counterModeBlock)
|
|
{
|
|
_xorMask.Enqueue(b);
|
|
}
|
|
}
|
|
|
|
private void IncrementCounter()
|
|
{
|
|
for (var i = _counter.Length - 1; i >= 0; i--)
|
|
{
|
|
if (++_counter[i] != 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
public int InputBlockSize { get { return _symmetricAlgorithm.BlockSize / 8; } }
|
|
public int OutputBlockSize { get { return _symmetricAlgorithm.BlockSize / 8; } }
|
|
public bool CanTransformMultipleBlocks { get { return true; } }
|
|
public bool CanReuseTransform { get { return false; } }
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
}
|
|
} |