Open hootyjeremy opened 1 year ago
Hello, you’re not alone :)
I use a similar implementation as you do and I also get similar results.
I’m getting around ~9 mb/s on my laptop (AES/CBC, 256 bits key, running flutter app in release mode, encryption itself in separate isolate), less than that on some slower phones, meanwhile AES/CBC in Java/Kotlin (same modes, same params, same devices) encrypts at 200-300+ mb/s (desktop) and 80+ mb/s (phones).
I have also tested the deprecated AESFastEngine engine. It can encrypt at ~20 mb/s on my machine.
Do we know what is the bottleneck in the current implementation of AESEngine?
Ah, I think I get it now after digging into the source code. aes.dart uses only one T-table, _T0
, while aes_fast.dart uses four _t0
, _t1
, _t2
, and _t3
where 1, 2, and 3 are rotated versions of _t0
. This gains a performance increase, apparently. The other package I was testing, which has pretty quick throughput, also does this. I will try aes_fast.dart and check the results. I didn't try it at first because of the warning that it was susceptible to side-channel attacks.
Check out section 5 Implementation aspects of the rijndael block cipher for more info. (this is a pdf) https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf
edit: I see that you are saying that aes_fast is also slow. Have you tried the package called "cryptography" yet? That's the fastest one I've come across. Does that give you faster speeds than aes_fast.dart?
How did you get aes_fast.dart to work? I can't seem to get it to work.
Also, what package are you using for Java/Kotlin? BouncyCastle or something else?
I have created gist for the "cryptography" package example if you want to try it. It will encrypt 100mb the same way as the gist provided in the original post for pointycastle (https://gist.github.com/hootyjeremy/97ccfe7b1203ac5160b4544a237b9b5a). I can't seem to get aes_fast.dart to work right now so I can't compare it to this other package.
"cryptography" package by dint.dev... https://gist.github.com/hootyjeremy/038f434e57aa4fd5765b7c63e70da7f3
Does that package provide faster results than aes_fast.dart for you?
I’ve modified your AES/CBC gist to run with AESFastEngine: https://gist.github.com/maxjaglak/65896f380d10027568c50b475d605d52
it gives me following results: //AES / CBC / pointy castle / AESFastEngine size: 100 mb time.elapsed: 0:00:03.209223 speed 29.72 [mbps]
For comparison, same test, but with standard AESEngine, from Pointy Castle: size: 100 mb time.elapsed: 0:00:12.970145 speed 7.35 [mbps]
with your cryptography test: //AES / CBC / https://pub.dev/packages/cryptography size: 100 mb time: 0:00:02.424923 speed 39.34 [mbps] (a little bit faster than AESFastEngine from Pointy Castle)
With java/kotlin I use javax.crypto API.
I guess I will end up writing native code for AES encryption / decryption (java / swift / other) and keep Pointy Castle as a fallback for platforms where I don’t have native implementation.
Thanks for the benchmarks. I'm not yet sure why pointycastle's implementation is slower than cryptography
's. I'm looking at that one right now and maybe I'll find something. The good thing about pointycastle is that padding is optional with aescbc which means I can process chunks and just pad the last block but the cryptography
package pads it all in one shot and doesn't let you do chunks as far as I can tell. But I'm starting to work on a PR for that one if I can figure out how to make padding optional for Aes Cbc.
I would like to be able to use aesni first and then fallback to a software implementation but I haven't found any packages that use CBC with aesni. Sodium will do aesni but only uses GCM which is fine except that it doesn't have a software fallback. But I've only found that the software implementations for GCM are even slower than CBC so I don't even want to use GCM.
If you don't mind my asking, what is the difference in writing it natively vs. with dart? Why is that faster if flutter/dart is said to compile to native code?
If you don't mind my asking, what is the difference in writing it natively vs. with dart? Why is that faster if flutter/dart is said to compile to native code?
I guess it’s about code optimization itself. I mean just compiling to native code doesn’t mean it’s optimal. javax.crypto uses implementation of different providers, so its performance is dependent on what is actually being used. I’ve found some posts that explains a little: https://stackoverflow.com/questions/6101565/is-there-a-practical-way-to-determine-which-jce-crypto-providers-are-in-use https://docs.oracle.com/en/java/javase/16/docs/api/java.base/javax/crypto/package-summary.html https://stackoverflow.com/a/3048593/5178627
I’m not sure what speed you require in your implementation, but for my use cases, javax.crypto + “whatever is selected by default” is usually enough. On iOS / macOS, you could use CryptoKit, which uses hardware acceleration; on newer machines it can reach 2000+ mb/s with AES GCM.
But I've only found that the software implementations for GCM are even slower than CBC so I don't even want to use GCM.
For CBC vs GCM, check this post: https://security.stackexchange.com/a/184307
Thanks for the info. I'll give these a read.
I am interested in using this package but when I test encrypting 100mb with AES/CBC, it takes about 7 seconds in release mode on my machine. I know that speed on machines are relative so I have a gist of the example code here which will print elapsed time:
https://gist.github.com/hootyjeremy/97ccfe7b1203ac5160b4544a237b9b5a
I can understand that this is software implemented AES and not aesni, but does this seem extremely slow for anybody else? Even that it is a software implementation, I wouldn't expect more than 0.5 to 1 seconds to encrypt 100mb.
Can anybody verify if I am getting acceptable speeds with this package or if this is an anomaly?