Skip to content

Commit cfd0dca

Browse files
committed
crypto: make getCiphers() return non-SSL ciphers
Commit f53441a added crypto.getCiphers() as a function that returns the names of SSL ciphers. Commit 14a6c4e then added crypto.getHashes(), which returns the names of digest algorithms, but that creates a subtle inconsistency: the return values of crypto.getHashes() are valid arguments to crypto.createHash() but that is not true for crypto.getCiphers() - the returned values are only valid for SSL/TLS functions. Rectify that by adding tls.getCiphers() and making crypto.getCiphers() return proper cipher names.
1 parent 488b74d commit cfd0dca

6 files changed

Lines changed: 60 additions & 23 deletions

File tree

doc/api/crypto.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Returns an array with the names of the supported ciphers.
1919
Example:
2020

2121
var ciphers = crypto.getCiphers();
22-
console.log(ciphers); // ['AES128-SHA', 'AES256-SHA', ...]
22+
console.log(ciphers); // ['AES-128-CBC', 'AES-128-CBC-HMAC-SHA1', ...]
2323

2424

2525
## crypto.getHashes()

doc/api/tls.markdown

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ handshake extensions allowing you:
7676
certificates.
7777

7878

79+
## tls.getCiphers()
80+
81+
Returns an array with the names of the supported SSL ciphers.
82+
83+
Example:
84+
85+
var ciphers = tls.getCiphers();
86+
console.log(ciphers); // ['AES128-SHA', 'AES256-SHA', ...]
87+
88+
7989
## tls.createServer(options, [secureConnectionListener])
8090

8191
Creates a new [tls.Server][]. The `connectionListener` argument is

lib/crypto.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -576,21 +576,23 @@ exports.prng = pseudoRandomBytes;
576576

577577

578578
exports.getCiphers = function() {
579-
return getCiphers.call(null, arguments).sort();
579+
return filterDuplicates(getCiphers.call(null, arguments));
580580
};
581581

582582

583583
exports.getHashes = function() {
584-
var names = getHashes.call(null, arguments);
584+
return filterDuplicates(getHashes.call(null, arguments));
585585

586+
};
587+
588+
589+
function filterDuplicates(names) {
586590
// Drop all-caps names in favor of their lowercase aliases,
587591
// for example, 'sha1' instead of 'SHA1'.
588592
var ctx = {};
589-
names = names.forEach(function(name) {
593+
names.forEach(function(name) {
590594
if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase();
591595
ctx[name] = true;
592596
});
593-
names = Object.getOwnPropertyNames(ctx);
594-
595-
return names.sort();
596-
};
597+
return Object.getOwnPropertyNames(ctx).sort();
598+
}

lib/tls.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ exports.CLIENT_RENEG_WINDOW = 600;
4040

4141
exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024;
4242

43+
exports.getCiphers = function() {
44+
var names = process.binding('crypto').getSSLCiphers();
45+
// Drop all-caps names in favor of their lowercase aliases,
46+
var ctx = {};
47+
names.forEach(function(name) {
48+
if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase();
49+
ctx[name] = true;
50+
});
51+
return Object.getOwnPropertyNames(ctx).sort();
52+
};
53+
4354

4455
var debug;
4556
if (process.env.NODE_DEBUG && /tls/.test(process.env.NODE_DEBUG)) {

src/node_crypto.cc

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3948,7 +3948,7 @@ Handle<Value> RandomBytes(const Arguments& args) {
39483948
}
39493949

39503950

3951-
Handle<Value> GetCiphers(const Arguments& args) {
3951+
Handle<Value> GetSSLCiphers(const Arguments& args) {
39523952
HandleScope scope;
39533953

39543954
SSL_CTX* ctx = SSL_CTX_new(TLSv1_server_method());
@@ -3977,19 +3977,28 @@ Handle<Value> GetCiphers(const Arguments& args) {
39773977
}
39783978

39793979

3980-
static void add_hash_to_array(const EVP_MD* md,
3981-
const char* from,
3982-
const char* to,
3983-
void* arg) {
3980+
template <class TypeName>
3981+
static void array_push_back(const TypeName* md,
3982+
const char* from,
3983+
const char* to,
3984+
void* arg) {
39843985
Local<Array>& arr = *static_cast<Local<Array>*>(arg);
39853986
arr->Set(arr->Length(), String::New(from));
39863987
}
39873988

39883989

3990+
Handle<Value> GetCiphers(const Arguments& args) {
3991+
HandleScope scope;
3992+
Local<Array> arr = Array::New();
3993+
EVP_CIPHER_do_all_sorted(array_push_back<EVP_CIPHER>, &arr);
3994+
return scope.Close(arr);
3995+
}
3996+
3997+
39893998
Handle<Value> GetHashes(const Arguments& args) {
39903999
HandleScope scope;
39914000
Local<Array> arr = Array::New();
3992-
EVP_MD_do_all_sorted(add_hash_to_array, &arr);
4001+
EVP_MD_do_all_sorted(array_push_back<EVP_MD>, &arr);
39934002
return scope.Close(arr);
39944003
}
39954004

@@ -4033,6 +4042,7 @@ void InitCrypto(Handle<Object> target) {
40334042
NODE_SET_METHOD(target, "PBKDF2", PBKDF2);
40344043
NODE_SET_METHOD(target, "randomBytes", RandomBytes<false>);
40354044
NODE_SET_METHOD(target, "pseudoRandomBytes", RandomBytes<true>);
4045+
NODE_SET_METHOD(target, "getSSLCiphers", GetSSLCiphers);
40364046
NODE_SET_METHOD(target, "getCiphers", GetCiphers);
40374047
NODE_SET_METHOD(target, "getHashes", GetHashes);
40384048

test/simple/test-crypto.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -834,20 +834,24 @@ testPBKDF2('pass\0word', 'sa\0lt', 4096, 16,
834834
'\x25\xe0\xc3');
835835

836836
function assertSorted(list) {
837-
for (var i = 0, k = list.length - 1; i < k; ++i) {
838-
var a = list[i + 0];
839-
var b = list[i + 1];
840-
assert(a <= b);
841-
}
837+
assert.deepEqual(list, list.sort());
842838
}
843839

844-
// Assume that we have at least AES256-SHA.
845-
assert.notEqual(0, crypto.getCiphers());
846-
assert.notEqual(-1, crypto.getCiphers().indexOf('AES256-SHA'));
840+
// Assume that we have at least AES-128-CBC.
841+
assert.notEqual(0, crypto.getCiphers().length);
842+
assert.notEqual(-1, crypto.getCiphers().indexOf('aes-128-cbc'));
843+
assert.equal(-1, crypto.getCiphers().indexOf('AES-128-CBC'));
847844
assertSorted(crypto.getCiphers());
848845

846+
// Assume that we have at least AES256-SHA.
847+
var tls = require('tls');
848+
assert.notEqual(0, tls.getCiphers().length);
849+
assert.notEqual(-1, tls.getCiphers().indexOf('aes256-sha'));
850+
assert.equal(-1, tls.getCiphers().indexOf('AES256-SHA'));
851+
assertSorted(tls.getCiphers());
852+
849853
// Assert that we have sha and sha1 but not SHA and SHA1.
850-
assert.notEqual(0, crypto.getHashes());
854+
assert.notEqual(0, crypto.getHashes().length);
851855
assert.notEqual(-1, crypto.getHashes().indexOf('sha1'));
852856
assert.notEqual(-1, crypto.getHashes().indexOf('sha'));
853857
assert.equal(-1, crypto.getHashes().indexOf('SHA1'));

0 commit comments

Comments
 (0)