diff --git a/browser/lib/util/crypto.js b/browser/lib/util/crypto.js index 07e2c4340c..5c4d18a108 100644 --- a/browser/lib/util/crypto.js +++ b/browser/lib/util/crypto.js @@ -1,6 +1,7 @@ var Crypto = (function() { var DEFAULT_ALGORITHM = 'aes'; var DEFAULT_KEYLENGTH = 128; // bits + var DEFAULT_MODE = 'cbc'; var DEFAULT_BLOCKLENGTH = 16; // bytes var DEFAULT_BLOCKLENGTH_WORDS = 4; // 32-bit words var VAL32 = 0x100000000; @@ -102,6 +103,8 @@ var Crypto = (function() { */ function CipherParams() { this.algorithm = null; + this.keyLength = null; + this.mode = null; this.key = null; this.iv = null; } @@ -138,8 +141,10 @@ var Crypto = (function() { key = BufferUtils.toWordArray(key); // Expect key to be an Array, ArrayBuffer, or WordArray at this point var params = new CipherParams(); - params.algorithm = DEFAULT_ALGORITHM + '-' + String(key.words.length * (4 * 8)); + params.algorithm = DEFAULT_ALGORITHM; params.key = key; + params.keyLength = key.words.length * (4 * 8); + params.mode = DEFAULT_MODE; generateRandom(DEFAULT_BLOCKLENGTH, function(err, buf) { params.iv = buf; callback(null, params); @@ -154,10 +159,7 @@ var Crypto = (function() { Crypto.getCipher = function(channelOpts, callback) { var params = channelOpts && channelOpts.cipherParams; if(params) { - if(params instanceof CipherParams) - callback(null, new CBCCipher(params)); - else - callback(new Error("ChannelOptions not supported")); + callback(null, new CBCCipher(params)); return; } Crypto.getDefaultParams(function(err, params) { @@ -170,7 +172,7 @@ var Crypto = (function() { }; function CBCCipher(params) { - this.algorithm = params.algorithm + '-cbc'; + this.algorithm = params.algorithm + '-' + String(params.keyLength) + '-' + params.mode; var cjsAlgorithm = this.cjsAlgorithm = params.algorithm.toUpperCase().replace(/-\d+$/, ''); var key = this.key = BufferUtils.toWordArray(params.key); var iv = this.iv = BufferUtils.toWordArray(params.iv); diff --git a/nodejs/lib/util/crypto.js b/nodejs/lib/util/crypto.js index 337056098c..5d35fd30a7 100644 --- a/nodejs/lib/util/crypto.js +++ b/nodejs/lib/util/crypto.js @@ -6,6 +6,7 @@ var Crypto = (function() { var DEFAULT_ALGORITHM = 'aes'; var DEFAULT_KEYLENGTH = 128; // bits + var DEFAULT_MODE = 'cbc'; var DEFAULT_BLOCKLENGTH = 16; // bytes /** @@ -80,6 +81,8 @@ var Crypto = (function() { */ function CipherParams() { this.algorithm = null; + this.keyLength = null; + this.mode = null; this.key = null; this.iv = null; } @@ -112,8 +115,11 @@ var Crypto = (function() { } var params = new CipherParams(); - params.algorithm = DEFAULT_ALGORITHM + '-' + String(key.length * 8); + params.algorithm = DEFAULT_ALGORITHM; params.key = key; + params.keyLength = key.length * 8; + params.mode = DEFAULT_MODE; + params.algorithm = DEFAULT_ALGORITHM; generateRandom(DEFAULT_BLOCKLENGTH, function(err, buf) { params.iv = buf; callback(null, params); @@ -128,10 +134,7 @@ var Crypto = (function() { Crypto.getCipher = function(channelOpts, callback) { var params = channelOpts && channelOpts.cipherParams; if(params) { - if(params instanceof CipherParams) - callback(null, new CBCCipher(params)); - else - callback(new Error("ChannelOptions not supported")); + callback(null, new CBCCipher(params)); return; } Crypto.getDefaultParams(function(err, params) { @@ -144,7 +147,7 @@ var Crypto = (function() { }; function CBCCipher(params) { - var algorithm = this.algorithm = params.algorithm + '-cbc'; + var algorithm = this.algorithm = params.algorithm + '-' + String(params.keyLength) + '-' + params.mode; var key = this.key = params.key; var iv = this.iv = params.iv; this.encryptCipher = crypto.createCipheriv(algorithm, key, iv); diff --git a/spec/realtime/crypto.test.js b/spec/realtime/crypto.test.js index ce8424c511..006e8c031d 100644 --- a/spec/realtime/crypto.test.js +++ b/spec/realtime/crypto.test.js @@ -229,7 +229,7 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { } var realtime = helper.AblyRealtime({ transports: ['web_socket'] }); - test.expect(2); + test.expect(3); var channel = realtime.channels.get('single_send_binary'), messageText = 'Test message (single_send_binary)'; @@ -240,7 +240,8 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { return; } - test.equal(params.algorithm, 'aes-128'); + test.equal(params.algorithm, 'aes'); + test.equal(params.keyLength, 128); channel.setOptions({encrypted:true, cipherParams: params}); channel.subscribe('event0', function(msg) { test.ok(msg.data == messageText); @@ -261,12 +262,13 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { } var realtime = helper.AblyRealtime({ transports: ['web_socket'], useBinaryProtocol: false }); - test.expect(2); + test.expect(3); var channel = realtime.channels.get('single_send_text'), messageText = 'Test message (single_send_text)'; Crypto.getDefaultParams(function(err, params) { - test.equal(params.algorithm, 'aes-128'); + test.equal(params.algorithm, 'aes'); + test.equal(params.keyLength, 128); if(err) { test.ok(false, 'Unable to get cipher params; err = ' + err); closeAndFinish(test, realtime); @@ -292,13 +294,14 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { } var realtime = helper.AblyRealtime({ transports: ['web_socket'] }); - test.expect(2); + test.expect(3); var channel = realtime.channels.get('single_send_binary_256'), messageText = 'Test message (single_send_binary_256)'; Crypto.generateRandom(256 / 8, function(err, key) { Crypto.getDefaultParams(key, function(err, params) { - test.equal(params.algorithm, 'aes-256'); + test.equal(params.algorithm, 'aes'); + test.equal(params.keyLength, 256); if(err) { test.ok(false, 'Unable to get cipher params; err = ' + err); closeAndFinish(test, realtime); @@ -325,13 +328,14 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { } var realtime = helper.AblyRealtime({ transports: ['web_socket'], useBinaryProtocol: false }); - test.expect(2); + test.expect(3); var channel = realtime.channels.get('single_send_text_256'), messageText = 'Test message (single_send_text_256)'; Crypto.generateRandom(256 / 8, function(err, key) { Crypto.getDefaultParams(key, function(err, params) { - test.equal(params.algorithm, 'aes-256'); + test.equal(params.algorithm, 'aes'); + test.equal(params.keyLength, 256); if(err) { test.ok(false, 'Unable to get cipher params; err = ' + err); closeAndFinish(test, realtime); @@ -355,14 +359,15 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { } var realtime = helper.AblyRealtime({ transports: ['web_socket'], useBinaryProtocol: !text}); - test.expect(iterations + 2); + test.expect(iterations + 3); var channelName = 'multiple_send_' + (text ? 'text_' : 'binary_') + iterations + '_' + delay, channel = realtime.channels.get(channelName), messageText = 'Test message (' + channelName + ')'; Crypto.generateRandom(128 / 8, function(err, key) { Crypto.getDefaultParams(key, function(err, params) { - test.equal(params.algorithm, 'aes-128'); + test.equal(params.algorithm, 'aes'); + test.equal(params.keyLength, 128); if(err) { test.ok(false, 'Unable to get cipher params; err = ' + err); closeAndFinish(test, realtime); @@ -419,7 +424,7 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { var txRealtime = helper.AblyRealtime({ transports: ['web_socket'] }); var rxRealtime = helper.AblyRealtime({ transports: ['web_socket'], useBinaryProtocol: false }); - test.expect(2); + test.expect(3); var channelName = 'single_send_binary_text', messageText = 'Test message (' + channelName + ')', txChannel = txRealtime.channels.get(channelName), @@ -435,7 +440,8 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { return; } var params = res[0]; - test.equal(params.algorithm, 'aes-128'); + test.equal(params.algorithm, 'aes'); + test.equal(params.keyLength, 128); txChannel.setOptions({encrypted:true, cipherParams: params}); rxChannel.setOptions({encrypted:true, cipherParams: params}); @@ -462,7 +468,7 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { var txRealtime = helper.AblyRealtime({ transports: ['web_socket'], useBinaryProtocol: false }); var rxRealtime = helper.AblyRealtime({ transports: ['web_socket'] }); - test.expect(2); + test.expect(3); var channelName = 'single_send_text_binary', messageText = 'Test message (' + channelName + ')', txChannel = txRealtime.channels.get(channelName), @@ -478,7 +484,8 @@ define(['ably', 'shared_helper', 'async'], function(Ably, helper, async) { return; } var params = res[0]; - test.equal(params.algorithm, 'aes-128'); + test.equal(params.algorithm, 'aes'); + test.equal(params.keyLength, 128); txChannel.setOptions({encrypted:true, cipherParams: params}); rxChannel.setOptions({encrypted:true, cipherParams: params});