Skip to content

.NET 6 : Aes.EncryptEcb one-shot is slower than ICryptoTransform.TransformFinalBlock #58784

@sdrapkin

Description

@sdrapkin

Description

void Main() => BenchmarkRunner.Run<Bench>();

public class Bench
{
	byte[] _key, _plaintext, _ciphertext;

	[GlobalSetup]
	public void Setup()
	{
		_key = RandomNumberGenerator.GetBytes(32);
		_plaintext = Encoding.UTF8.GetBytes("This is a test. This is a test. ");

		using var tempAes = Aes.Create();
		tempAes.Key = _key;
		_ciphertext = tempAes.EncryptEcb(_plaintext, PaddingMode.None);
	}

	[Benchmark(Baseline = true)]
	public byte[] Old_Enc()
	{
		using Aes aes = Aes.Create();
		aes.Padding = PaddingMode.None;
		aes.Mode = CipherMode.ECB;

		using var transform = aes.CreateEncryptor(_key, null);
		return transform.TransformFinalBlock(_plaintext, 0, _plaintext.Length);
	}

	[Benchmark]
	public byte[] Old_Dec()
	{
		using Aes aes = Aes.Create();
		aes.Padding = PaddingMode.None;
		aes.Mode = CipherMode.ECB;

		using var transform = aes.CreateDecryptor(_key, null);
		return transform.TransformFinalBlock(_ciphertext, 0, _ciphertext.Length);
	}

	[Benchmark]
	public byte[] New_Enc()
	{
		using Aes aes = Aes.Create();
		aes.Key = _key;
		return aes.EncryptEcb((ReadOnlySpan<byte>)_plaintext, PaddingMode.None);
	}

	[Benchmark]
	public byte[] New_Dec()
	{
		using Aes aes = Aes.Create();
		aes.Key = _key;
		return aes.DecryptEcb((ReadOnlySpan<byte>)_ciphertext, PaddingMode.None);
	}
}

Configuration

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19042.1202 (20H2/October2020Update)
Intel Core i7-10510U CPU 1.80GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK=6.0.100-preview.7.21379.14
  [Host] : .NET 6.0.0 (6.0.21.37719), X64 RyuJIT

Results

Method Mean Error StdDev Ratio RatioSD
Old_Enc 725.8 ns 7.82 ns 6.53 ns 1.00 0.00
Old_Dec 805.9 ns 15.83 ns 16.25 ns 1.11 0.02
New_Enc 977.5 ns 7.90 ns 6.60 ns 1.35 0.02
New_Dec 1,016.8 ns 14.85 ns 13.16 ns 1.40 0.02

Analysis

EncryptEcb and DecryptEcb appear to be consistently 30~35% slower than the old approach of ICryptoTransform.TransformFinalBlock.

The bench code is a slightly modified version of @stephentoub example from his "Performance Improvements in .NET 6" post, which seems to suggest that these new one-shot methods are supposed to be faster - not slower.

@GrabYourPitchforks @bartonjs

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions