diff --git a/doc/api/crypto.markdown b/doc/api/crypto.markdown index 3270808a27a..e4d43467b4a 100644 --- a/doc/api/crypto.markdown +++ b/doc/api/crypto.markdown @@ -21,6 +21,16 @@ Example: console.log(ciphers); // ['AES128-SHA', 'AES256-SHA', ...] +## crypto.getHashes() + +Returns an array with the names of the supported hash algorithms. + +Example: + + var hashes = crypto.getHashes(); + console.log(hashes); // ['sha', 'sha1', 'sha1WithRSAEncryption', ...] + + ## crypto.createCredentials(details) Creates a credentials object, with the optional details being a dictionary with keys: diff --git a/lib/crypto.js b/lib/crypto.js index 6d1cae51bc8..52774907a89 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -35,6 +35,7 @@ try { var randomBytes = binding.randomBytes; var pseudoRandomBytes = binding.pseudoRandomBytes; var getCiphers = binding.getCiphers; + var getHashes = binding.getHashes; var crypto = true; } catch (e) { @@ -196,3 +197,18 @@ exports.rng = randomBytes; exports.prng = pseudoRandomBytes; exports.getCiphers = getCiphers; + +exports.getHashes = function() { + var names = getHashes.call(null, arguments); + + // Drop all-caps names in favor of their lowercase aliases, + // for example, 'sha1' instead of 'SHA1'. + var ctx = {}; + names = names.forEach(function(name) { + if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase(); + ctx[name] = true; + }); + names = Object.getOwnPropertyNames(ctx); + + return names; +}; diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 2244a9fcfd0..ae4b67e2fa1 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -4646,6 +4646,23 @@ Handle GetCiphers(const Arguments& args) { } +static void add_hash_to_array(const EVP_MD* md, + const char* from, + const char* to, + void* arg) { + Local& arr = *static_cast*>(arg); + arr->Set(arr->Length(), String::New(from)); +} + + +Handle GetHashes(const Arguments& args) { + HandleScope scope; + Local arr = Array::New(); + EVP_MD_do_all_sorted(add_hash_to_array, &arr); + return scope.Close(arr); +} + + void InitCrypto(Handle target) { HandleScope scope; @@ -4686,6 +4703,7 @@ void InitCrypto(Handle target) { NODE_SET_METHOD(target, "randomBytes", RandomBytes); NODE_SET_METHOD(target, "pseudoRandomBytes", RandomBytes); NODE_SET_METHOD(target, "getCiphers", GetCiphers); + NODE_SET_METHOD(target, "getHashes", GetHashes); subject_symbol = NODE_PSYMBOL("subject"); issuer_symbol = NODE_PSYMBOL("issuer"); diff --git a/test/simple/test-crypto.js b/test/simple/test-crypto.js index 49bb90b401e..e88c1dc0a23 100644 --- a/test/simple/test-crypto.js +++ b/test/simple/test-crypto.js @@ -687,3 +687,10 @@ testPBKDF2('pass\0word', 'sa\0lt', 4096, 16, // Assume that we have at least AES256-SHA. assert.notEqual(0, crypto.getCiphers()); assert.notEqual(-1, crypto.getCiphers().indexOf('AES256-SHA')); + +// Assert that we have sha and sha1 but not SHA and SHA1. +assert.notEqual(0, crypto.getHashes()); +assert.notEqual(-1, crypto.getHashes().indexOf('sha1')); +assert.notEqual(-1, crypto.getHashes().indexOf('sha')); +assert.equal(-1, crypto.getHashes().indexOf('SHA1')); +assert.equal(-1, crypto.getHashes().indexOf('SHA'));