public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { int returnCount = inputCount; this.LengthCipher += inputCount; for (int i = 0; i < inputCount; i += OutputBlockSize) { IncrementCounter(); byte[] iBuffer = new byte[InputBlockSize]; byte[] oBuffer = new byte[OutputBlockSize]; Array.Copy(inputBuffer, inputOffset + i, iBuffer, 0, InputBlockSize); this.Aes.Encrypt(Counter, 0, oBuffer, 0); oBuffer = iBuffer.Add(oBuffer); if (Encrypt) { ByteTag = GaloisMultiplication.GMul128(oBuffer.Add(ByteTag), H); } else { ByteTag = GaloisMultiplication.GMul128(iBuffer.Add(ByteTag), H); } Array.Copy(oBuffer, 0, outputBuffer, outputOffset + i, OutputBlockSize); } return(returnCount); }
public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { this.LengthCipher += inputCount; byte[] output = new byte[inputCount]; byte[] oBuffer = new byte[OutputBlockSize]; if (inputCount > 0) { IncrementCounter(); byte[] iBuffer = new byte[InputBlockSize]; Array.Copy(inputBuffer, inputOffset, iBuffer, 0, InputBlockSize); this.Aes.Encrypt(Counter, 0, oBuffer, 0); oBuffer = iBuffer.Add(oBuffer); if (Encrypt) { Array.Clear(oBuffer, inputCount, oBuffer.Length - inputCount); ByteTag = GaloisMultiplication.GMul128(oBuffer.Add(ByteTag), H); } else { ByteTag = GaloisMultiplication.GMul128(iBuffer.Add(ByteTag), H); } Array.Copy(oBuffer, 0, output, 0, inputCount); } byte[] length = ConvertToByteArray(AdditionalData.Length * 8, LengthCipher * 8); ByteTag = GaloisMultiplication.GMul128(ByteTag.Add(length), H); this.Aes.Encrypt(InitialCounter, 0, oBuffer, 0); ByteTag = oBuffer.Add(ByteTag); if (Encrypt) { SetTag(); } else { AssertAuthentication(); } return(output); }
/// <summary> /// 1: X0 = 0 /// 2: For i = 1; i <= m; i++ /// Xi = (Xi-1 XOR Ai) * H /// </summary> private void CreateByteTagWithAAD() { ByteTag = new byte[OutputBlockSize]; int blocks = (AdditionalData.Length % 16) == 0 ? AdditionalData.Length / 16 : AdditionalData.Length / 16 + 1; byte[] temp = new byte[OutputBlockSize]; for (int i = 1; i <= blocks; i++) { byte[] aadBlock = new byte[OutputBlockSize]; int length = AdditionalData.Length - ((i - 1) * 16) > 16 ? 16 : AdditionalData.Length - ((i - 1) * 16); Array.Copy(AdditionalData, (i - 1) * 16, aadBlock, 0, length); temp = GaloisMultiplication.GMul128(temp.Add(aadBlock), H); } Array.Copy(temp, 0, ByteTag, 0, OutputBlockSize); }
/// <summary> /// 3: For i = 1; i <= n; i++ /// Xi = (Xi-1 XOR IV) * H /// 4: T = (Xn XOR (0 || length(IV))) * H /// </summary> /// <param name="H"></param> /// <param name="IV"></param> /// <returns></returns> private byte[] GHashIV(byte[] H, byte[] IV) { int blocks = IV.Length / 16; blocks += IV.Length % 16 == 0 ? 1 : 2; byte[] temp = new byte[OutputBlockSize]; for (int i = 1; i < blocks; i++) { byte[] IVBlock = new byte[OutputBlockSize]; int cpLength = IV.Length - ((i - 1) * 16); cpLength = cpLength > 16 ? 16 : cpLength; Array.Copy(IV, (i - 1) * 16, IVBlock, 0, cpLength); temp = GaloisMultiplication.GMul128(temp.Add(IVBlock), H); } return(GaloisMultiplication.GMul128(temp.Add(ConvertToByteArray(IV.Length * 8)), H)); }