Skip to content
This repository was archived by the owner on Jul 21, 2023. It is now read-only.

Catch error when unmarshaling instead of crashing #113

Merged
merged 7 commits into from
Dec 1, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 42 additions & 15 deletions src/keys/rsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,34 @@ exports.generateKey = function (bits, callback) {
return done(err)
}

done(null, {
privateKey: pemToJwk(key.private),
publicKey: pemToJwk(key.public)
})
let res
try {
res = {
privateKey: pemToJwk(key.private),
publicKey: pemToJwk(key.public)
}
} catch (err) {
return done(err)
}

done(null, res)
}

// Takes a jwk key
exports.unmarshalPrivateKey = function (key, callback) {
callback(null, {
privateKey: key,
publicKey: {
kty: key.kty,
n: key.n,
e: key.e
try {
key = {
privateKey: key,
publicKey: {
kty: key.kty,
n: key.n,
e: key.e
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where would an exception be thrown in this operation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never underestimate the power of undefined: TypeError: Cannot read property 'e' of undefined

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but in this case, it would never through that error, only if you did something like key.e.something. As long as if key exists and it is an object, key.e will never throw

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverted this, but now inside a setImmediate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And what about unmarshalPrivateKey(undefined, (err, res) => {}) ??

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkg20001 good point, fixing.

}
})
} catch (err) {
callback(new Error('Key is invalid!'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs a return

}
callback(null, key)
}

exports.getRandomValues = function (arr) {
Expand All @@ -43,14 +55,29 @@ exports.getRandomValues = function (arr) {
exports.hashAndSign = function (key, msg, callback) {
const sign = crypto.createSign('RSA-SHA256')

sign.update(msg)
setImmediate(() => callback(null, sign.sign(jwkToPem(key))))
let pem

try {
sign.update(msg)
pem = jwkToPem(key)
} catch (err) {
return callback(new Error('Key or message is invalid!'))
}

setImmediate(() => callback(null, sign.sign(pem)))
}

exports.hashAndVerify = function (key, sig, msg, callback) {
const verify = crypto.createVerify('RSA-SHA256')

verify.update(msg)
let pem

try {
verify.update(msg)
pem = jwkToPem(key)
} catch (err) {
return callback(new Error('Key or message is invalid!'))
}

setImmediate(() => callback(null, verify.verify(jwkToPem(key), sig)))
setImmediate(() => callback(null, verify.verify(pem, sig)))
}
8 changes: 8 additions & 0 deletions test/keys/ed25519.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const crypto = require('../../src')
const ed25519 = crypto.keys.supportedKeys.ed25519
const fixtures = require('../fixtures/go-key-ed25519')

const testCb = require('../testCb')

describe('ed25519', () => {
let key
before((done) => {
Expand Down Expand Up @@ -176,6 +178,12 @@ describe('ed25519', () => {
})
})

describe('returns error via cb instead of crashing', () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
testCb.doTests('key.verify', key.verify.bind(key), 2)
testCb.doTests('crypto.keys.unmarshalPrivateKey', crypto.keys.unmarshalPrivateKey.bind(crypto.keys))
})

describe('go interop', () => {
let privateKey

Expand Down
8 changes: 8 additions & 0 deletions test/keys/rsa.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const crypto = require('../../src')
const rsa = crypto.keys.supportedKeys.rsa
const fixtures = require('../fixtures/go-key-rsa')

const testCb = require('../testCb')

describe('RSA', () => {
let key

Expand Down Expand Up @@ -131,6 +133,12 @@ describe('RSA', () => {
})
})

describe('returns error via cb instead of crashing', () => {
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
testCb.doTests('key.verify', key.verify.bind(key), 2)
testCb.doTests('crypto.keys.unmarshalPrivateKey', crypto.keys.unmarshalPrivateKey.bind(crypto.keys))
})

describe('go interop', () => {
it('verifies with data from go', (done) => {
const key = crypto.keys.unmarshalPublicKey(fixtures.verify.publicKey)
Expand Down
6 changes: 3 additions & 3 deletions test/keys/secp256k1.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const mockSecp256k1Module = {
}

describe('without libp2p-crypto-secp256k1 module present', () => {
crypto.keys.supportedKeys['secp256k1'] = undefined
crypto.keys.supportedKeys.secp256k1 = undefined

it('fails to generate a secp256k1 key', (done) => {
crypto.keys.generateKeyPair('secp256k1', 256, (err, key) => {
Expand Down Expand Up @@ -61,7 +61,7 @@ describe('with libp2p-crypto-secp256k1 module present', () => {
let key

before((done) => {
crypto.keys.supportedKeys['secp256k1'] = mockSecp256k1Module
crypto.keys.supportedKeys.secp256k1 = mockSecp256k1Module
crypto.keys.generateKeyPair('secp256k1', 256, (err, _key) => {
if (err) return done(err)
key = _key
Expand All @@ -70,7 +70,7 @@ describe('with libp2p-crypto-secp256k1 module present', () => {
})

after((done) => {
delete crypto.keys['secp256k1']
delete crypto.keys.secp256k1
done()
})

Expand Down
42 changes: 42 additions & 0 deletions test/testCb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* eslint-env mocha */
'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)

const util = require('util')
const garbage = [Buffer.from('00010203040506070809', 'hex'), {}, null, false, undefined, true, 1, 0, Buffer.from(''), 'aGVsbG93b3JsZA==', 'helloworld', '']

function doTests (fncName, fnc, num) {
if (!num) {
num = 1
}

garbage.forEach(garbage => {
let args = []
for (let i = 0; i < num; i++) {
args.push(garbage)
}
it(fncName + '(' + args.map(garbage => util.inspect(garbage)).join(', ') + ')', cb => {
args.push((err, res) => {
expect(err).to.exist()
expect(res).to.not.exist()
cb()
})

fnc(...args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not use this operator for now (we are still avoiding some ES6 features)

})
})
}

module.exports = (obj, fncs, num) => {
describe('returns error via cb instead of crashing', () => {
fncs.forEach(fnc => {
doTests(fnc, obj[fnc], num)
})
})
}

module.exports.doTests = doTests