Notice (2018-05-24): bugzilla.xamarin.com is now in
Please join us on
Visual Studio Developer Community and in the
Mono organizations on
GitHub to continue tracking issues. Bugzilla will remain
available for reference in read-only mode. We will continue to work
on open Bugzilla bugs, copy them to the new locations
as needed for follow-up, and add the new items under Related
Our sincere thanks to everyone who has contributed on this bug
tracker over the years. Thanks also for your understanding as we
make these adjustments and improvements for the future.
Please create a new report on
Developer Community or GitHub with
your current version information, steps to reproduce, and relevant error
messages or log files if you are hitting an issue that looks similar to
this resolved bug and you do not yet see a matching new report.
Created attachment 461 [details]
Demo code of slow encryption
Encrption code works and is reliable. Performance is adequate on Emulator. On device, encryption performance is very poor. This is a Hard-Stop issue. Our app performs quite well until we activate the encryption, which is a deal-breaker. Response time of a few seconds goes to 90sec encryption overhead on transitions.
Same code works adequately on WP7 with lag times for a call ~2 sec/per encryption job. On iOS,same calls are 10+ secs /call. Demo shows load/save time sample. Due to caching nature of DB, start app once. reset device and start again to see realistic load times. 8 secs on load/12 secs on Save. I have tried all the available encryption libraries (AES is required for our work) best performance in TripleDES. Encryption can be turned off/on in Project Model; Sterling/EncryptedSerilizer, Line 19. Currently Encrypts. Remove ||iOS to turn off Encryption and see the perf delta.
Mono's cryptographic stack is entirely managed. It's no bad in a full desktop environment (e.g. simulator) but it fail any comparison to native, hand-coded or hardware accelerated implementations of similar algorithm. However there are some alternatives, from easier to harder:
1) try different options, e.g.
a) make sure debug is off (as it slow down execution);
b) use the LLVM compiler (that will ensure debug is off) and it's different targets (you'll have better code generation, which should help performance). YMMV but it's easy
2) review your code, e.g.
a) why is AesManagedFactory called 3 times ? instead of 1 ? it's perfectly correct to cache it as long as you create new ICryptoTransform (Decryptor/Encryptor) for each invocation.
E.g. If you cache one AesManaged instance (and you should since it's costly to create due to PKCS#5 iterations involved) the number are much better:
2nd run* before/after
Save: 11297 6147
Load: 0 0
Save: 10559 179
Load: 0 0
Save: 10566 173
* to ensure database was created
b) your TripleDES code is very different from your AES code, you're likely not comparing the same thing (since key generation is totally different, the one from AES, using PKCS#5, being much better)
c) your 'stopwatch' is not Reset'ed between the "Load" and "Save" so I think your Save time includes your Load time.
3) go native and bind the CommonCrypto API. AFAIK some devices have hardware acceleration for some algorithms (e.g. AES) and that's unbeatable.
note: we plan to offer access to native crypto in the future, i.e. what iOS offers with CommonCrypto, but there's no ETA for this.
4) ask yourself why...
a) you're using a 4 characters PIN ? that's 10000 possible values (just a bit over 2^13) if numbers are used (a bit more if any printable characters are available but less than 2^32). An attacker will have no problem pre-computing all possible keys (whatever the cryptographic algorithms and key length you're using)
b) you're iterating a lot (10000) to create the key/iv from the password/PIN ? you're hurting your users (on mobile devices), not any attacker (which will use much more powerful computers). You could use other strategy (e.g. varying salt and/or iteration count to make it harder to pre-compute all keys)
2nd run* when 1000 (instead of 10000 iterations are used)
note: the time differences are smaller because the above numbers are using the 'cached' AesManaged (so the iterations are done a single time, not 3 times)
c) you're using a 256 bits key based on a 4 characters PIN ? e.g. AES 128 bits will be faster (than 256 bits) and still way more secure than the PIN. E.g.
2nd run* when a 128 bits key is used (1000 iterations, cached Aes instance)
I don't believe the above suggestions are making the attached code less secure (it's all limited by the PIN) but it makes it much faster.
The using the AESManaged as a cached item, only doing 1000 interations for IV and reducing the encryption to AES-192, the federal Standard dramatically improved performance. Now encryption performance hit is not notcible. Thankyou.