Giter Site home page Giter Site logo

dchest / scrypt-async-js Goto Github PK

View Code? Open in Web Editor NEW
139.0 12.0 26.0 189 KB

Fast "async" scrypt implementation in JavaScript

Home Page: http://dchest.github.io/scrypt-async-js/

License: BSD 2-Clause "Simplified" License

HTML 8.31% JavaScript 91.69%
scrypt javascript crypto kdf pbkdf2 cperciva

scrypt-async-js's Introduction

scrypt-async

Build Status Coverage Status

Saucelabs Test Status

Fast "async" scrypt implementation in JavaScript.

Works in browsers without throwing "kill slow script" warnings due to configurable interruptStep, which yields from calculation. Compatible even with old versions of IE. Also works with Node.js (but you should really use the C implementation for that).

Installation

You can install it via a package manager:

NPM:

$ npm install scrypt-async

Yarn:

$ yarn add scrypt-async

or download source code.

To improve performance with small interruptStep values, use setImmediate shim, such as https://github.com/YuzuJS/setImmediate.

Usage

Modern API

scrypt(password, salt, options, callback)

Derives a key from password and salt and calls callback with derived key as the only argument.

If interruptStep is set, calculations are interrupted with setImmediate (or zero setTimeout) at the given interruptSteps to avoid freezing the browser. If it's not set or set to zero, the callback is called immediately after the calculation, avoiding setImmediate.

Arguments:

  • password — password (string or Array of bytes or Uint8Array)
  • salt — salt (string or Array of bytes or Uint8Array)
  • options — object with key derivation options
  • callback — callback function receiving result (function (Array|Uint8Array|string))
Options:
  • N — CPU/memory cost parameter (must be power of two; alternatively, you can specify logN where N = 2^logN).
  • r — block size parameter
  • p — parallelization parameter (default is 1)
  • dkLen — derived key length (default is 32)
  • interruptStep — (optional) the amount of loop cycles to execute before the next setImmediate/setTimeout (defaults to 0)
  • encoding — (optional) result encoding 'base64' or 'hex' (result will be a string), 'binary' (result will be a Uint8Array) or undefined (result will be an Array of bytes).

Example:

scrypt('mypassword', 'saltysalt', {
    N: 16384,
    r: 8,
    p: 1,
    dkLen: 16,
    encoding: 'hex'
}, function(derivedKey) {
    console.log(derivedKey); // "5012b74fca8ec8a4a0a62ffdeeee959d"
});

Legacy API (deprecated)

scrypt(password, salt, logN, r, dkLen, [interruptStep], callback, [encoding])

Legacy API doesn't support parallelization parameter greater than 1.

Arguments:
  • password — password (string or Array of bytes or Uint8Array)
  • salt — salt (string or Array of bytes or Uint8Array)
  • logN — CPU/memory cost parameter (1 to 31)
  • r — block size parameter
  • dkLen — length of derived key
  • interruptStep — (optional) the amount of loop cycles to execute before the next setImmediate/setTimeout (defaults to 1000)
  • callback — callback function receiving result (function (Array|Uint8Array|string))
  • encoding — (optional) result encoding ('base64', 'hex', 'binary' or undefined).

When encoding is not set, the result is an Array of bytes.

License

BSD-like, see LICENSE file or MIT license at your choice.

scrypt-async-js's People

Contributors

dchest avatar evilaliv3 avatar jedie avatar totaltechgeek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scrypt-async-js's Issues

What is the best value of R parameter?

Most of the examples the value is 8, but when I decrease the number ('till 1) the execution time it goes down considerably.

Can someone explain to me what incidence R has and what is the lowest number to use it?

Thanks!

synchronous version?

I really like this code, but I want to use it in a program where the KDF needs to be called several times for different strings. Waiting is a plus, since I want to encourage users to use high-entropy passwords, and I add rounds of KDF for low entropy.

Is there a way to use your function synchronously, without callbacks?

Various memory allocations inefficiencies prevents real use case scenarios

Scrypt is an algorithm designed cause lots of memory allocations by itself, but it seems that the current scrypt-async-js design contains a lot of additional memory allocations inefficiencies that prevent to use it in the real with the suggested LogN=20 that was proposed in 2009 as the right LogN for file encryption.

https://www.tarsnap.com/scrypt/scrypt-slides.pdf

For example running Scrypt with LogN=20 on Chrome seems to allocate more than 2GB for a sigle run;

This is due to the fact of various variable allocations inside loops and mix javascript sintaxes that could be avoided like:

  • new Array inside functions when the variable could be allocated one time outside
  • return [x, y, z] inside functions reallocating every time a new array for the return

npm package

I need this in npm.

Would you like me to add a package.json and make a pull so that you can publish the package? Or do you prefer not to maintain the npm package, in which case I would publish a fork by myself?

Thanks for your great work!

base64url encoding (url safe base64)

It would be nice if base64url encoding can be added.
Reference: https://www.ietf.org/rfc/rfc4648.txt

Encoding
Replace + with -
Replace / with _

var enc = ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +
    '0123456789-_').split('');

Delete the padding section:

if (len % 3 > 0) {
  arr[arr.length-1] = '=';
  if (len % 3 === 1) arr[arr.length-2] = '=';
}

Decoding:
The padding can be reconstructed with the modulus 4 from the data length.
Here is a PHP example:

function base64url_decode($data) {
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}

Performance becomes very bad after tens of calls of scrypt()

I encountered performance issue when using scrypt-async to crypt the password, following is the test code

var scrypt = require('scrypt-async');

var i = 0;
var count = 50;
while (i <= count) {
  var res;
  var start = Date.now();
  scrypt('HelloWorld', '39wiYWT7TxX6aflvCUk840nqmY8pm0EaC5plkK+SVyg=', {"N": 32768, "r": 8, "p": 1, dkLen: 32, encoding: 'base64', interruptStep: 0}, (derivedKey) => {
    res = derivedKey;
  });
  var end = Date.now();
  console.info('Count: ' + i + ' Time: ' + (end - start) + 'ms');
  i++;
}

After tens of calling of scrypt, the encryption time becomes 15 times more, following is the output:

Count:	0	Time:	147ms
Count:	1	Time:	145ms
Count:	2	Time:	130ms
Count:	3	Time:	125ms
Count:	4	Time:	227ms
Count:	5	Time:	165ms
Count:	6	Time:	145ms
Count:	7	Time:	148ms
Count:	8	Time:	132ms
Count:	9	Time:	119ms
Count:	10	Time:	120ms
Count:	11	Time:	137ms
Count:	12	Time:	134ms
Count:	13	Time:	149ms
Count:	14	Time:	129ms
Count:	15	Time:	143ms
Count:	16	Time:	137ms
Count:	17	Time:	134ms
Count:	18	Time:	122ms
Count:	19	Time:	126ms
Count:	20	Time:	118ms
Count:	21	Time:	128ms
Count:	22	Time:	158ms
Count:	23	Time:	139ms
Count:	24	Time:	137ms
Count:	25	Time:	127ms
Count:	26	Time:	125ms
Count:	27	Time:	124ms
Count:	28	Time:	127ms
Count:	29	Time:	125ms
Count:	30	Time:	145ms
Count:	31	Time:	159ms
Count:	32	Time:	127ms
Count:	33	Time:	126ms
Count:	34	Time:	121ms
Count:	35	Time:	131ms
Count:	36	Time:	146ms
Count:	37	Time:	128ms
Count:	38	Time:	144ms
Count:	39	Time:	154ms
Count:	40	Time:	156ms
Count:	41	Time:	161ms
Count:	42	Time:	174ms
Count:	43	Time:	2302ms
Count:	44	Time:	2333ms
Count:	45	Time:	2308ms
Count:	46	Time:	2313ms
Count:	47	Time:	2384ms
Count:	48	Time:	2291ms
Count:	49	Time:	2300ms
Count:	50	Time:	2363ms

As you can see, the beginning 43 calls just cost about 150ms in average, but from the 44th call, the time increased to 2300ms.

The scrypt-async version is 1.3.1, nodejs version 4.4.5
I'm using a MacOS, version 10.12.4 (16E195), Processor 2.8 GHz Intel Core i7, Memory 16 GB 1600 MHz DDR3.

The hash output does not match with those of node-scrypt

First of all, I have to say that this scrypt implementation is a very impressive piece of software and I wanted to thank you for sharing it with everyone.

I've been using it for a project of mine on the client side, and I've noticed that the results that I get from it differ from those that I get from the scrypt npm (https://github.com/barrysteyn/node-scrypt) while providing the exact same settings.

My code base is in Meteor so there's no easy way to share it, but please take a look at these two snippets of code and let me know if it's me doing something wrong, or there's something wrong with the code of the library that I could perhaps pinpoint and issue a patch for?

Front-end:

Tinytest.addAsync("app:encryption scrypt.js vs scrypt NPM", function (test, onComplete) {
  var inputString = "string!";
  var salt = "boo";

  scrypt(inputString, salt, 8, 1, 16, 1, function (res) {

    Meteor.call('scrypt-npm-hash', inputString, { N: 8, r: 1, p: 1 }, 16, salt, function (error, result) {
      test.equal(result, res, 'Expected the values to be equal');
      onComplete();
    });
  }, 'hex');
});

Back-end (to run the NPM):

var scrypt = Npm.require("scrypt");

Meteor.methods({
  'scrypt-npm-hash': function (input, options, length, salt) {
    return scrypt.hashSync(input, options, length, salt).toString("hex");
  }
});

The hashes that I get on the front end and from the back end are 0c6d9c3df862dc8abbdae7623367066e and 4e58712e98444c547d1e3b710fc79afe respectively. I assume they have to be equal since the input parameters are the same for both.

Thanks.

[RESEARCH] Результат в переменную

Дмитрий, я прям теряюсь при знакомстве с вашими инструментами. :)
Сейчас вот гадал, чего это Scrypt не работает.

var result = scrypt(masterkey, salt, cost, blocksize, dklen, step, null, "hex");
object is not a function

var result = scrypt(masterkey, salt, cost, blocksize, dklen, step, function(){}, "hex");
undefined

scrypt(masterkey, salt, cost, blocksize, dklen, step, function(res){document.getElementById("result").value = res;}, "hex");
ура, получилось

Главный вопрос: можно ли допилить scrypt, чтобы привычно получать результат в переменную?
Или, может быть, я придерживаюсь устаревшей практики, тогда подскажите, как грамотнее.

Второстепенный: если вместо hex указать null, то приходят числа через запятую, примерно так 223,167,126,190,189,229,104,254,42,238,248,65,167,36,135,41,113,133,212,189,192,108,199,187,160,239,56,7,100,124,89,143, а что это? Ожидал неразберихи, которую можно сконвертировать по своему вкусу, необязательно в hex или base64 (например, в base85 zeromq, где спецсимволов больше или в base32/58, где спецсимволы отсутствуют).

P.S. Приятно, что сюда вы включили перевод строки в UTF8, т.е. masterkey, salt пишу без обёртки.

Verifying password

How can I verify password hashed by scrypt-async?
How is scrypt-async hash different from node-scrypt hash? Are they compatible?

Improve performance by using WebCrypto API?

Hi,
i was wondering if the performance of this scrypt implementation cannot be improved by leveraging existing WebCrypto API primitives (https://www.chromium.org/blink/webcrypto)

I don't know, from a performance profiling perspective how does the library behave, but in WebCrypto API there are those ones that maybe suitable for use in scrypt-async:

Do you think it does make sense as a possible significant performance improvement of the library?

Maybe would it make sense to customize scrypt algorithm itself in order to maximize it's use of Native code when run in an HTML5 browser?

Speed up travis testing by caching node_modules directory

TravisCI allows to speed up unit tests by permitting to cache directories.

In relation to scrypt-js library it would be valuable to cache the node_modules directory used by npm.

It would be simply required to add the following lines to .travis.yml:

cache:
  directories:
    - node_modules

it's blocking in IE 11

I used it with react . it is fun on Chrome but UI blocking so long time on ie 11

function handleSubmit(e) {
    e.preventDefault();

    validateFieldsAndScroll((err, values) => {
      if (err) {
        return;
      }
      const username = values.username;
      const password = values.password;
 
        scrypt(password, username + siteId, scryptParam,
          (derivedKey) => {
            onOk({ username, password: derivedKey , type: 'login'});
          })
      console.log('timeout Set');
    });
  }

how to migrate from node-scrypt to scrypt-async?

I am trying to read "old" hashes from node-scrypt. I can read the structure and parse it into individual things like logN, r, p, and so on. I still fail to verify a node-scrypt hash using scrypt-async. Can anyone help me achieve this?

Here's a short gist, including

  • parsing-code for node-scrypt hex output
  • creation of a node-scrypt hex hash
  • TRYING to verify this (which fails)

https://gist.github.com/ccoenen/3b228a32790ad0a5e1b29adfde963e96

Can anyone help me find my error?

Idea: Utilize SubtleCrypto when webcrypto is supported by the platform

I'd like to ask about the possibility of making scrypt-async-js to be taking advantage of window.crypto when it's available for calculating SHA-256, and possibly performing other cryptographic calculations for the sake of speeding up the performance on newer devices.

Related links:
https://www.w3.org/TR/WebCryptoAPI/
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
https://github.com/diafygi/webcrypto-examples

Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.