private static byte[] TransformRecordBytes(BulkCipherAlgorithmType cipherType, ICryptoTransform transform, byte[] input)
{
if (cipherType != BulkCipherAlgorithmType.AEAD) {
// In case of non-AEAD cipher algorithm, check that data matches block size
if (input.Length % transform.InputBlockSize != 0) {
throw new Exception("Input data size doesn't match block size");
}
}
int blockCount = input.Length / transform.InputBlockSize;
if (cipherType == BulkCipherAlgorithmType.AEAD) {
// Make sure there is enough data at TransformFinalBlock, because
// decryption requires that the authentication tag is present
if (blockCount > 0) {
blockCount--;
}
}
byte[] output = new byte[blockCount * transform.OutputBlockSize];
if (transform.CanTransformMultipleBlocks) {
transform.TransformBlock(input, 0, blockCount*transform.InputBlockSize, output, 0);
} else {
for (int i=0; i<blockCount; i++) {
transform.TransformBlock(input, i*transform.InputBlockSize,
transform.InputBlockSize,
output, i*transform.OutputBlockSize);
}
}
if (cipherType == BulkCipherAlgorithmType.AEAD) {
int currentPosition = blockCount*transform.InputBlockSize;
// Transfer the last block when encrypting or authentication tag when decrypting
byte[] finalBytes = transform.TransformFinalBlock(input, currentPosition, input.Length-currentPosition);
if (finalBytes == null) {
return null;
} else if (finalBytes.Length > 0) {
byte[] finalOutput = new byte[output.Length + finalBytes.Length];
Buffer.BlockCopy(output, 0, finalOutput, 0, output.Length);
Buffer.BlockCopy(finalBytes, 0, finalOutput, output.Length, finalBytes.Length);
output = finalOutput;
}
}
return output;
}