-
Notifications
You must be signed in to change notification settings - Fork 50
Conversation
Sha384 and Sha512 share the same implementation and differ only in the initailization vectors and the digest concatentation. The algorithm from from rfc6234 calls for 64bit words and operations and to remain dart2js friendly, BigInt was used. INPUT REQUESTED: I'm not sure where the test vectors came from; but a simple comparison to sha384 and sha512 command line methods shows it matching. If you can point me to them, then I can write a better test.
Solves Issue dart-lang/core#181 |
@lrhn – thoughts here? |
Note: this (truncation, different initialization values) should work for sha-224 as well to fully support RFC 6234. Happy to put up a cl for that as well. |
Do something less stupid; use _Sha32BitSink and _Sha64BitSink to have class heirarchies make better sense.
I'm worried that using What throughput do you get for the various hash functions (say, 1MB digests per second) on the VM and dart2js (-O3)? Ideally, in the browser the crypto library should be using the Web Crypto API. |
vm, "real" 16MB buffer of random. Instance of 'Sha224' warmup: 0:00:00.008122 ~5.5MB/sec I'll experiment with just using ints and addressing only the lower 32. |
I have no experience with the |
We can't expose Web Crypto through the current synchronous APIs, as Web Crypto is asynchronous. As for the low-level implementation of primitives I'm not an expert, if publishing from the dart-lang organization might be wise to have someone with expertise review that. |
Two modes of operation: if you're in a browser, you get the slower 32bit algorithm because you only have 2^53 bits. If you are on the VM / Flutter, you'll have 64bit operations wich is *much* faster: 32BIT NUMBERS: ~20MB/s hashing Removing BigInt has some good results: Instance of 'Sha224' warmup: 0:00:00.015599 Instance of 'Sha256' warmup: 0:00:00.002325 Instance of 'Sha384' warmup: 0:00:00.019082 Instance of 'Sha512' warmup: 0:00:00.010288 Instance of 'Sha224' real: 0:00:00.092928 Instance of 'Sha256' real: 0:00:00.093426 Instance of 'Sha384' real: 0:00:00.823335 Instance of 'Sha512' real: 0:00:00.807871 64BIT NUMBERS: ~236MB/s hashing On the VM, this is much faster with 64bit operations. Instance of 'Sha224' warmup: 0:00:00.013285 Instance of 'Sha256' warmup: 0:00:00.002443 Instance of 'Sha384' warmup: 0:00:00.020954 Instance of 'Sha512' warmup: 0:00:00.005616 Instance of 'Sha224' real: 0:00:00.097196 Instance of 'Sha256' real: 0:00:00.094167 Instance of 'Sha384' real: 0:00:00.067605 Instance of 'Sha512' real: 0:00:00.067564 NOTE: Compiles with dart2js - cannot reference 64bit hex as the compiler just vomits... but you can left shift by 32.
As requested; removal of BigInt() - except doing pure 32bit math was still underwhelming. This switches between 32bit and 64bit depending on where you're running... and you get a 10x speed up on the VM. |
dart2js -O3:
dart:crypto has never been async. if you are doing any sha over a large sum of data, you should use a webworker. |
var e = _digest[4]; | ||
var f = _digest[5]; | ||
var g = _digest[6]; | ||
var h = _digest[7]; | ||
|
||
for (var i = 0; i < 64; i++) { | ||
var temp1 = add32(add32(h, _bsig1(e)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a 64-bit JS VM, it's likely that signed 32-bit numbers are efficient. Unsigned are not (but for addition and multiplication, you can use signed values without changing the outcome mod 2^32).
On a 32-bit JS VM, even 32 bit integers may be heap allocated, and only signed 31-bit integers get the full performance from "Smi" optimization.
Consider using configurable imports to switch between different implementations. It might reduce code size unless the compiler can efficiently tree-shake the unused branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added the conditional import for vm/js implementations. Are you suggesting fixednum for the js version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think fixednum might be more efficient, but it depends a lot on details. Maybe three smi multiplications are more efficient than two heap-number multiplications. Maybe they're not. Maybe it's sufficient to use Int32 values instead of Uint32 values for JS on 64-bit platforms.
Maybe just commit something that works, and then we can optimize it later :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just commit something that works, and then we can optimize it later :)
Indeed, make sure the tests are right, and that we have plenty of test vectors, I would rather have a few too many than later be optimizing an incorrect implementation :) hehe
Speed is still meh in dart2js: 384/512 numbers: Instance of 'minified:a2' real: 0:00:02.203820 Instance of 'minified:aO' real: 0:00:02.192515
No clue about Travis... |
Downloaded dart 2.0.0 for windows 64bit - was able to reproduce the travis errors. It's only the monte tests, so I'll try to figure out what is wrong with those... |
I'm going on vacation, so I might not get much traction on this. I feel its pretty important to figure out what is wrong - and I suspect its 64bit bit shifting differences (but I have no evidence). |
well, my evidence is: slowsinks works on 2.0 :) |
Odd evidence: while doing a binary search to figure out where the corruption lies... I noticed the VM flipped from giving good answers to giving bad ones at random on the same file. inputs: dartsdk.zip (windows 64bit version)
|
E.g.:
|
Running the monte test and hashing the dart-sdk with other official releases found here: https://dart.dev/tools/sdk/archive shows no faults. I'm not going to debug this further: there's clearly something wrong with dartvm 2.0.0 and zero change that'll get patched. Suggested the minimum dart-sdk to be ^2.1.0. 2.0.0: fails monte; odd corruption between runs. command line:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks sane to me :)
LGTM if it works. |
Is there anything else needed to merge this? |
@lrhn : I think you're the only one with write access to this repo. |
Still looking for some love... |
@sethladd, @sigmundch, you two seems to have uploader permissions on pub.dev/packages/crypto, would either if you like to merge and publish this PR? |
Apologies, I'm not longer working on this library. Maybe @kevmoo can help find a way to nudge this along? |
Okay, I've looked over this, and can merge since I have TEH POWER, but I'm relying on @lrhn @rakudrama @jonasfj and @kevmoo to follow up with the questions they raised about this on performance/testing. |
- 2.0.0 | ||
- dev | ||
- 2.1.0 | ||
- stable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have stayed dev
– keeps us honest about upcoming SDKs!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
..... should I send a follow-up PR? It's only been up for a few min!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a different between dartvm 2.1.0 stable and dartvm 2.1.0 dev?
@jtmcdole @efortuna 👋 This release broke all of our Dart builds:
Thanks for taking a look! |
Earlier I had a quick hack check to decide which files to include. It was suggested I use this line instead:
|
It appears that upgrading to build_web_compilers ^2.0.0 fixes the issue. If there's any way to make this change backwards compatible with BWC <2.0.0 that'd be awesome. We have 10s of packages that use BWC <2.0.0 at the moment. |
Hey folks -- thanks for the report of the issues! I'm discussing with Nate and we're going to submit a fix right away |
New version pushed. Apologies for the disruption! We do recommend upgrading to using build_web_compilers to 2.0.0+, but I committed a workaround that should work for everyone, regardless of whether you do that o rnot. |
lib/src/sha384_512.dart
Outdated
/// new instance. | ||
class Sha384 extends Hash { | ||
@override | ||
final int blockSize = 16 * bytesPerWord; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks wrong to me. According to https://en.wikipedia.org/wiki/SHA-2, SHA512 has 1024 bits internal block size, i.e. 128 bytes. 16 * 4
is only 64.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On this note, that should have failed HMAC-SHA512 test, had there been one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're commenting on an outdated commit. Also, this is not HMAC-512, its just Sha512.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you're getting at though - I did not update the HMAC. That can be easily done (pull requests welcome ;) )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One trivial error and a request for HMAC-SHA512 test ;-).
* Add SHA384 and SHA512 Sha384 and Sha512 share the same implementation and differ only in the initailization vectors and the digest concatentation. The algorithm from from rfc6234 calls for 64bit words and operations and to remain dart2js friendly, BigInt was used. INPUT REQUESTED: I'm not sure where the test vectors came from; but a simple comparison to sha384 and sha512 command line methods shows it matching. If you can point me to them, then I can write a better test. * Add Sha224 + Refactor Do something less stupid; use _Sha32BitSink and _Sha64BitSink to have class heirarchies make better sense. * Support 32bit and 64bit operations for SHA384/512 Two modes of operation: if you're in a browser, you get the slower 32bit algorithm because you only have 2^53 bits. If you are on the VM / Flutter, you'll have 64bit operations wich is *much* faster: 32BIT NUMBERS: ~20MB/s hashing Removing BigInt has some good results: Instance of 'Sha224' warmup: 0:00:00.015599 Instance of 'Sha256' warmup: 0:00:00.002325 Instance of 'Sha384' warmup: 0:00:00.019082 Instance of 'Sha512' warmup: 0:00:00.010288 Instance of 'Sha224' real: 0:00:00.092928 Instance of 'Sha256' real: 0:00:00.093426 Instance of 'Sha384' real: 0:00:00.823335 Instance of 'Sha512' real: 0:00:00.807871 64BIT NUMBERS: ~236MB/s hashing On the VM, this is much faster with 64bit operations. Instance of 'Sha224' warmup: 0:00:00.013285 Instance of 'Sha256' warmup: 0:00:00.002443 Instance of 'Sha384' warmup: 0:00:00.020954 Instance of 'Sha512' warmup: 0:00:00.005616 Instance of 'Sha224' real: 0:00:00.097196 Instance of 'Sha256' real: 0:00:00.094167 Instance of 'Sha384' real: 0:00:00.067605 Instance of 'Sha512' real: 0:00:00.067564 NOTE: Compiles with dart2js - cannot reference 64bit hex as the compiler just vomits... but you can left shift by 32. * Fix comment * Add conditional imports * De-listify 32bit allocations Speed is still meh in dart2js: 384/512 numbers: Instance of 'minified:a2' real: 0:00:02.203820 Instance of 'minified:aO' real: 0:00:02.192515 * Add sha monte tests for 224,256,384, and 512 RSP values came from http://csrc.nist.gov/groups/STM/cavp/documents/shs/shabytetestvectors.zip * Fix formattting of lib/crypto.dart * Bump version (adding new features) + min sdk * Bump travis (hidden file) * Rework monte test to function-only.
Sha384 and Sha512 share the same implementation and differ only in the
initialization vectors and the digest concatenation. The algorithm from
from rfc6234 calls for 64bit words and operations and to remain dart2js
friendly, BigInt was used.
INPUT REQUESTED
I'm not sure where the test vectors came from; but a simple comparison
to sha384 and sha512 command line methods shows it matching. If you
can point me to them, then I can write a better test.