-
Notifications
You must be signed in to change notification settings - Fork 60
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
Performance worse than sjcl lib #18
Comments
ping @feross, thoughts on whether this might be a Buffer issue before I dig into it deeper? |
You can check if the buffer instances are based on Safari 7 and below has a bug in |
I'm willing to look into this soon. |
Safari 5-7 get the Uint8Array implementation as of the latest buffer version! So you might not even need to fix this anymore. |
@feross it actually seems related to the fact that I'm not sure if this is avoidable without breaking compliance in the |
Not sure what you're trying to do, but if you want to create a buffer without allocating a whole new Uint8Array, you can now do this in node.js and the browser:
|
@feross no no, my point is, look at |
Since iojs v3 and node v4, |
@feross I don't understand. |
I'm talking about |
In https://github.com/crypto-browserify/sha.js/blob/master/hash.js#L41, Hash.prototype.digest = function (enc) { Would have to become Hash.prototype.digest = function (enc, target) { Where |
I'm probably misunderstanding something here, just ignore me. |
Ah, I see your point. Yeah that sounds like it's an API modification. |
@rubensayshi our only options at this point would be to replace the entire underlying implementation with a different HMAC stack. I'm not really keen on that. How are the benchmarks holding up? |
Results with improved sha.js (2.4.5), pbkdf2 (3.0.4) Google Chrome Version 49.0.2623.63 beta (64-bit)
Firefox 44.0.2 (64-bit)
node.js v5.6.0 (using browser version)
|
Awesome. |
ping @fanatid we could also improve speed by somehow caching the |
@fanatid thoughts? #include <cassert>
#include <cstdint>
#include <cstring>
#include <openssl/sha.h>
#include <openssl/evp.h>
#define SHA256_DIGEST_LENGTH 32
void pbkdf2_hmac_sha256 (const uint8_t* password, const size_t passwordLength, const uint8_t* salt, const size_t saltLength, const size_t iterations, uint8_t* key, size_t keyLength) {
SHA256_CTX ipadCtx, opadCtx;
// pre-calculate the HMAC blocks to avoid constant re-calculation
{
uint8_t ipad[SHA256_CBLOCK], opad[SHA256_CBLOCK];
memset(ipad, 0x36, SHA256_CBLOCK);
memset(opad, 0x5C, SHA256_CBLOCK);
if (passwordLength > SHA256_CBLOCK) {
uint8_t tmp[SHA256_DIGEST_LENGTH];
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, password, passwordLength);
SHA256_Final(tmp, &ctx);
for (size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
ipad[i] ^= tmp[i];
opad[i] ^= tmp[i];
}
} else {
for (size_t i = 0; i < passwordLength; i++) {
ipad[i] ^= password[i];
opad[i] ^= password[i];
}
}
SHA256_Init(&ipadCtx);
SHA256_Init(&opadCtx);
SHA256_Update(&ipadCtx, ipad, SHA256_CBLOCK);
SHA256_Update(&opadCtx, opad, SHA256_CBLOCK);
}
// divide and round upwards
auto l = keyLength / SHA256_DIGEST_LENGTH;
if (keyLength % SHA256_DIGEST_LENGTH != 0) l += 1;
const auto r = keyLength - (l - 1) * SHA256_DIGEST_LENGTH;
uint8_t T[SHA256_DIGEST_LENGTH], U[SHA256_DIGEST_LENGTH];
// TODO: REMOVE write32BE 8-bit shortcut
uint8_t uint32BE[4] = {};
for (size_t i = 1; i <= l; i++) {
// TODO: REMOVE write32BE 8-bit shortcut
assert(i < 256);
uint32BE[3] = (uint8_t) i;
SHA256_CTX ctx;
memcpy(&ctx, &ipadCtx, sizeof(SHA256_CTX));
SHA256_Update(&ctx, salt, saltLength);
SHA256_Update(&ctx, &uint32BE, sizeof(uint32BE));
SHA256_Final(U, &ctx);
memcpy(&ctx, &opadCtx, sizeof(SHA256_CTX));
SHA256_Update(&ctx, U, SHA256_DIGEST_LENGTH);
SHA256_Final(U, &ctx);
memcpy(T, U, SHA256_DIGEST_LENGTH);
for (size_t j = 1; j < iterations; j++) {
memcpy(&ctx, &ipadCtx, sizeof(SHA256_CTX));
SHA256_Update(&ctx, U, SHA256_DIGEST_LENGTH);
SHA256_Final(U, &ctx);
memcpy(&ctx, &opadCtx, sizeof(SHA256_CTX));
SHA256_Update(&ctx, U, SHA256_DIGEST_LENGTH);
SHA256_Final(U, &ctx);
for (size_t k = 0; k < SHA256_DIGEST_LENGTH; k++) T[k] ^= U[k];
}
const auto destPos = (i - 1) * SHA256_DIGEST_LENGTH;
const auto len = (i == l ? r : SHA256_DIGEST_LENGTH);
memcpy(key + destPos, T, len);
}
}
#include <iomanip>
#include <iostream>
int main (int argc, char** argv) {
const uint8_t k[] = "password_________________________________________________________________________________________________________________________";
const uint8_t s[] = "salt bbbbbbbbbbbbbb";
const int kl = sizeof(k) - 1;
const int sl = sizeof(s) - 1;
// ours
{
uint8_t buffer[10];
pbkdf2_hmac_sha256(k, kl, s, sl, 2000, buffer, sizeof(buffer));
for (size_t i = 0; i < sizeof(buffer); ++i) {
std::cout << std::hex << std::setfill('0') << std::setw(2) << (unsigned) buffer[i] << ' ';
}
std::cout << std::endl;
}
// openssl
{
uint8_t buffer[10];
PKCS5_PBKDF2_HMAC(
(const char*) k, kl,
s, sl,
2000,
EVP_sha256(),
sizeof(buffer),
buffer
);
for (size_t i = 0; i < sizeof(buffer); ++i) {
std::cout << std::hex << std::setfill('0') << std::setw(2) << (unsigned) buffer[i] << ' ';
}
std::cout << std::endl;
}
return 0;
} |
@dcousens yep, we can cache it and I sure that it gives significant performance improvement, but it will be not easy and could be easily broken by |
@fanatid granted, but this doesn't have to rely on |
we could also look back into using subtle crypto in the places that support it |
@calvinmetcalf is that faster? |
it's native so yes it would be, you could test with native-crypto which (in the browser) uses that if it's available and then this if not |
Is this still a concern? |
not for me, using asmcrypto.js ;) |
Can you post a bench? It might be worth dropping it in. |
with #59 we should get a speedup |
Thanks @calvinmetcalf , forgot about it. Still be worth comparing though :) |
oh yes I agree, I think I'll also publish all 3 of the updates we have in the wings |
Tested this today.
If we omit the new changes, Win! |
I don't think we'd ever beat It inlines the |
are you testing async in a browser because I bet we're faster there |
@calvinmetcalf because of |
yeah plus it's actually async (where supported)
…On Fri, May 19, 2017 at 8:47 AM Daniel Cousens ***@***.***> wrote:
@calvinmetcalf <https://github.com/calvinmetcalf> because of webcrypto?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#18 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABE4nxHl_fzIYEbB_YZRQ_vw0iflJI2Cks5r7Y9WgaJpZM4Fkj8y>
.
|
oh wow seems I've missed the webcrypto support addition, nice! |
Closing in favour of #75 |
@dcousens asked for a ticket ;)
performance on various engines is a lot worse compared to the 'sjcl' package.
see benchmarking test repo: https://github.com/rubensayshi/pbkdf2-benchmark
the most significant one is when using the old UIWebView on IOS (currently still the default for cordova apps without using a 3rd party plugin to upgrade to WKWebView) where it's close to a 10x difference.
but for the future WKWebView will not become the default to use in cordova 4.0.0+.
for chrome (on all platforms) there's also a significant difference between the 2 libs.
for w/e reason firefox sjcl is actually slower ... but (my) firefox is scrap xD
The text was updated successfully, but these errors were encountered: