Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AES-GCM an order of magnitude slower than AES-CBC #89

Open
cachapa opened this issue Mar 16, 2021 · 7 comments
Open

AES-GCM an order of magnitude slower than AES-CBC #89

cachapa opened this issue Mar 16, 2021 · 7 comments

Comments

@cachapa
Copy link

cachapa commented Mar 16, 2021

In experimenting with this library I'm getting an order of magnitude lower performance when using AES-GCM compared to AES-CBC in both encoding and decoding.

Testing on my PC with a 1.7 MB image file I'm getting ~100ms with CBC and ~2s with GCM.

Here's the file I'm using for testing: https://upload.wikimedia.org/wikipedia/commons/4/4e/Macaca_nigra_self-portrait_large.jpg
And here's the code:

void main() {
  // Do not use math.Random to generate keys in real life
  final random = Random();
  final key = Uint8List.fromList(List<int>.generate(32, (_) => random.nextInt(256)));
  final iv = Uint8List.fromList(List<int>.generate(16, (_) => random.nextInt(256)));
  final nonce = Uint8List.fromList(List<int>.generate(12, (_) => random.nextInt(256)));
  final data = File('selfie.jpg').readAsBytesSync();

  final cipherGcm = PaddedBlockCipherImpl(PKCS7Padding(), GCMBlockCipher(AESFastEngine()));
  final paramsGcm = PaddedBlockCipherParameters(AEADParameters(KeyParameter(key), 128, nonce, Uint8List(0)), null);
  cipherGcm.init(true, paramsGcm);

  var start = DateTime.now().millisecondsSinceEpoch;
  cipherGcm.process(data);
  var end = DateTime.now().millisecondsSinceEpoch;
  print('GCM: ${end - start} ms');

  final cipherCbc =
      PaddedBlockCipherImpl(PKCS7Padding(), CBCBlockCipher(AESFastEngine()));
  final paramsCbc = PaddedBlockCipherParameters(
      ParametersWithIV(KeyParameter(key), iv), null);
  cipherCbc.init(true, paramsCbc);

  start = DateTime.now().millisecondsSinceEpoch;
  cipherCbc.process(data);
  end = DateTime.now().millisecondsSinceEpoch;
  print('CBC: ${end - start} ms');
}

Results on my machine:

GCM: 2123 ms
CBC: 73 ms

I'm concerned about this since online resources say GCM should be more efficient, if anything.

I'd be grateful for pointers if I'm doing something wrong here.

@AKushWarrior
Copy link
Contributor

Nope, that's concerning. I'll look into it when I have some time.

@redDwarf03
Copy link
Contributor

Hello @cachapa
maybe this question from stackoverflow can give you some answers
https://stackoverflow.com/questions/73067225/aes256-cbc-vs-aes256-gcm-performance

@cachapa
Copy link
Author

cachapa commented Mar 14, 2023

@redDwarf03 that's interesting. At the time when I was reading about both algorithms I was pretty convinced that GCM was supposed to be more efficient. Now the details are lost to me, so I can't have a meaningful discussion on it.

In any case the difference between 73 ms and 2 seconds is staggering. It reminds me of a Dart performance issue I read recently (sorry don't have the link right now) where reading a file is much faster with the sync method than with the async one.
The justification was that the async method has perform a lot more message passing between the native code and the VM, which adds a lot of overhead.

@redDwarf03
Copy link
Contributor

@cachapa How do you want to follow up on this issue ?

@cachapa
Copy link
Author

cachapa commented Mar 14, 2023

How do you mean?
Unfortunately I don't have the availability to contribute technically.

I believe the bug report is valid and have provided a test case, so it's up to the maintainers now.

@redDwarf03
Copy link
Contributor

sorry, I just wanted to know if there was still a need

@cachapa
Copy link
Author

cachapa commented Mar 14, 2023

I was forced to go with CBC on my implementation because of the performance issue.

Honestly the GCM performace makes it nearly unusable except for very small payloads, so I would say the need is very much there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants