{"action":"created","issue":{"url":"https://api.github.com/repos/nodejs/node-v0.x-archive/issues/7994","repository_url":"https://api.github.com/repos/nodejs/node-v0.x-archive","labels_url":"https://api.github.com/repos/nodejs/node-v0.x-archive/issues/7994/labels{/name}","comments_url":"https://api.github.com/repos/nodejs/node-v0.x-archive/issues/7994/comments","events_url":"https://api.github.com/repos/nodejs/node-v0.x-archive/issues/7994/events","html_url":"https://github.com/nodejs/node-v0.x-archive/issues/7994","id":38665468,"number":7994,"title":"Crypto hash synchronicity and blocking","user":{"login":"skeggse","id":1348991,"avatar_url":"https://avatars.githubusercontent.com/u/1348991?v=3","gravatar_id":"","url":"https://api.github.com/users/skeggse","html_url":"https://github.com/skeggse","followers_url":"https://api.github.com/users/skeggse/followers","following_url":"https://api.github.com/users/skeggse/following{/other_user}","gists_url":"https://api.github.com/users/skeggse/gists{/gist_id}","starred_url":"https://api.github.com/users/skeggse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/skeggse/subscriptions","organizations_url":"https://api.github.com/users/skeggse/orgs","repos_url":"https://api.github.com/users/skeggse/repos","events_url":"https://api.github.com/users/skeggse/events{/privacy}","received_events_url":"https://api.github.com/users/skeggse/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2014-07-24T19:27:17Z","updated_at":"2016-10-13T14:10:25Z","closed_at":"2014-07-25T02:43:48Z","body":"I've started to notice the impacts of #5015 as I optimize other parts of our infrastructure, and as I'm profiling, I notice that the crypto's hash object is consuming upwards of 80% of the total processing time. We're using crypto's hash for hashing passwords, and while it makes sense that hashing passwords is time-consuming, it's also blocking, which means that a synchronous interface isn't always the right approach.\r\n\r\nLet me be clear: a synchronous Hash object with `update` and `digest` methods are absolutely useful when hashing contents of a stream without a huge memory overhead (especially if you're only handling one stream at a time with minimal other tasks in the \"background\"). However, another use-case for hash (when circumstances do not allow the use of pbkdf2), is hashing passwords. Passwords are generally short, and I have yet to see a streamed password.\r\n\r\nI propose we add an asynchronous hash interface to the crypto library: one that does not allow multiple updates and digests exactly once. I'm not fond of adding functionality, but I don't want to implement this in raw javascript--I'd much prefer a solution that works with openssl. I also don't want to implement a userland addon which binds to openssl, because node's core already binds to openssl, and that's a lot of crap to throw in an separate addon. I don't think the resolution of #5015 will fix things either, even if we get the performance of 0.8, it's still blocking the entire process. I could solve this with `cluster`, but we don't use `cluster` right now and that's a lot of infrastructure (and failure potential) just for password hashing. An asynchronous interface would move the bulk of the processing into the thread pool, allowing other operations to continue as normal.\r\n\r\n#### Proposed Interface\r\n\r\n##### digestHash(algorithm, data, [input_encoding], [output_encoding], callback)\r\n\r\n(that's a lot of parameters, so an object might also work, at least for the encodings)\r\n\r\n```js\r\ncrypto.digestHash('sha256', 'th1s*IzaPA$$word?', 'utf-8', 'hex', function(err, hash) {\r\n  if (err) throw err; // :|\r\n  // hash => 'e2895271801a043c785d405c0d588043e6e558c49513bb3a5480536fe69b7ca4'\r\n});\r\n```\r\n\r\nPlease please please if you have a better solution I'd love to hear it, I'd much rather avoid changing node's api if possible."},"comment":{"url":"https://api.github.com/repos/nodejs/node-v0.x-archive/issues/comments/253524195","html_url":"https://github.com/nodejs/node-v0.x-archive/issues/7994#issuecomment-253524195","issue_url":"https://api.github.com/repos/nodejs/node-v0.x-archive/issues/7994","id":253524195,"user":{"login":"jorangreef","id":413206,"avatar_url":"https://avatars.githubusercontent.com/u/413206?v=3","gravatar_id":"","url":"https://api.github.com/users/jorangreef","html_url":"https://github.com/jorangreef","followers_url":"https://api.github.com/users/jorangreef/followers","following_url":"https://api.github.com/users/jorangreef/following{/other_user}","gists_url":"https://api.github.com/users/jorangreef/gists{/gist_id}","starred_url":"https://api.github.com/users/jorangreef/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jorangreef/subscriptions","organizations_url":"https://api.github.com/users/jorangreef/orgs","repos_url":"https://api.github.com/users/jorangreef/repos","events_url":"https://api.github.com/users/jorangreef/events{/privacy}","received_events_url":"https://api.github.com/users/jorangreef/received_events","type":"User","site_admin":false},"created_at":"2016-10-13T14:10:25Z","updated_at":"2016-10-13T14:10:25Z","body":"> Naturally, algorithms like sha256 are sub-millisecond, so the overhead of putting it into the thread pool actually makes it longer, and increases the duration of the above hashing algorithm.\r\n\r\n@skeggse I spent some time benchmarking asynchronous ciphers and hashes executed in the threadpool and released a module [`crypto-async`](https://github.com/jorangreef/crypto-async) to do this. For buffers larger than 1024 bytes, latency is roughly the same or only slightly slower, but throughput is up to 3x better so I think your idea is actually worthwhile for applications that process buffers of 1024 bytes or more. See the included benchmark in the [readme](https://github.com/jorangreef/crypto-async#performance)."}}
{"actor":{"display_login":"jorangreef"}}