fix(aes): replace subtle.crypto with browserify-aes

Due to the design of `AES-CTR` in the webcrypto spec, there
is no streaming mode provided. This results in the counter
not being reused between subsequent calls to `encrypt` or
`decrypt`. As both the node.js and the go implementation rely
on this webcrypto had to be replaced.
This commit is contained in:
Friedel Ziegelmayer 2016-11-10 17:19:45 +01:00
parent 393fa17512
commit 9994023490
6 changed files with 26 additions and 61 deletions

View File

@ -7,7 +7,7 @@
"node-webcrypto-ossl": false, "node-webcrypto-ossl": false,
"./src/crypto/webcrypto.js": "./src/crypto/webcrypto-browser.js", "./src/crypto/webcrypto.js": "./src/crypto/webcrypto-browser.js",
"./src/crypto/hmac.js": "./src/crypto/hmac-browser.js", "./src/crypto/hmac.js": "./src/crypto/hmac-browser.js",
"./src/crypto/aes.js": "./src/crypto/aes-browser.js" "./src/crypto/ciphers.js": "./src/crypto/ciphers-browser.js"
}, },
"scripts": { "scripts": {
"lint": "aegir-lint", "lint": "aegir-lint",
@ -32,6 +32,7 @@
"dependencies": { "dependencies": {
"asn1.js": "^4.8.1", "asn1.js": "^4.8.1",
"async": "^2.1.2", "async": "^2.1.2",
"browserify-aes": "^1.0.6",
"multihashing-async": "^0.2.0", "multihashing-async": "^0.2.0",
"node-webcrypto-ossl": "^1.0.7", "node-webcrypto-ossl": "^1.0.7",
"nodeify": "^1.0.0", "nodeify": "^1.0.0",
@ -66,4 +67,4 @@
"greenkeeperio-bot <support@greenkeeper.io>", "greenkeeperio-bot <support@greenkeeper.io>",
"nikuda <nikuda@gmail.com>" "nikuda <nikuda@gmail.com>"
] ]
} }

View File

@ -1,52 +0,0 @@
'use strict'
const nodeify = require('nodeify')
const crypto = require('./webcrypto')()
exports.create = function (key, iv, callback) {
nodeify(crypto.subtle.importKey(
'raw',
key,
{
name: 'AES-CTR'
},
false,
['encrypt', 'decrypt']
).then((key) => {
const counter = copy(iv)
return {
encrypt (data, cb) {
nodeify(crypto.subtle.encrypt(
{
name: 'AES-CTR',
counter: counter,
length: 128
},
key,
data
).then((raw) => Buffer.from(raw)), cb)
},
decrypt (data, cb) {
nodeify(crypto.subtle.decrypt(
{
name: 'AES-CTR',
counter: counter,
length: 128
},
key,
data
).then((raw) => Buffer.from(raw)), cb)
}
}
}), callback)
}
function copy (buf) {
const fresh = new Buffer(buf.length)
buf.copy(fresh)
return fresh
}

View File

@ -1,20 +1,20 @@
'use strict' 'use strict'
const crypto = require('crypto') const ciphers = require('./ciphers')
const ciphers = { const CIPHER_MODES = {
16: 'aes-128-ctr', 16: 'aes-128-ctr',
32: 'aes-256-ctr' 32: 'aes-256-ctr'
} }
exports.create = function (key, iv, callback) { exports.create = function (key, iv, callback) {
const name = ciphers[key.length] const mode = CIPHER_MODES[key.length]
if (!name) { if (!mode) {
return callback(new Error('Invalid key length')) return callback(new Error('Invalid key length'))
} }
const cipher = crypto.createCipheriv(name, key, iv) const cipher = ciphers.createCipheriv(mode, key, iv)
const decipher = crypto.createDecipheriv(name, key, iv) const decipher = ciphers.createDecipheriv(mode, key, iv)
const res = { const res = {
encrypt (data, cb) { encrypt (data, cb) {

View File

@ -0,0 +1,8 @@
'use strict'
const crypto = require('browserify-aes')
module.exports = {
createCipheriv: crypto.createCipheriv,
createDecipheriv: crypto.createDecipheriv
}

8
src/crypto/ciphers.js Normal file
View File

@ -0,0 +1,8 @@
'use strict'
const crypto = require('crypto')
module.exports = {
createCipheriv: crypto.createCipheriv,
createDecipheriv: crypto.createDecipheriv
}

View File

@ -14,7 +14,7 @@ const bytes = {
32: 'AES-256' 32: 'AES-256'
} }
describe.only('AES-CTR', () => { describe('AES-CTR', () => {
Object.keys(bytes).forEach((byte) => { Object.keys(bytes).forEach((byte) => {
it(`${bytes[byte]} - encrypt and decrypt`, (done) => { it(`${bytes[byte]} - encrypt and decrypt`, (done) => {
const key = new Buffer(parseInt(byte, 10)) const key = new Buffer(parseInt(byte, 10))