Skip to content
This repository has been archived by the owner on Jun 15, 2023. It is now read-only.

Commit

Permalink
refactor: use async/await instead of callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobheun committed Aug 13, 2019
1 parent 70c33c2 commit bbfb00c
Show file tree
Hide file tree
Showing 9 changed files with 454 additions and 658 deletions.
31 changes: 14 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@
"test:browser": "aegir test -t browser",
"release": "aegir release",
"release-minor": "aegir release --type minor",
"release-major": "aegir release --type major",
"coverage": "aegir coverage",
"coverage-publish": "aegir coverage publish"
"release-major": "aegir release --type major"
},
"pre-push": [
"lint"
],
"engines": {
"node": ">=6.0.0",
"node": ">=10.0.0",
"npm": ">=3.0.0"
},
"repository": {
Expand All @@ -41,26 +39,25 @@
},
"homepage": "https://github.com/libp2p/js-libp2p-keychain#readme",
"dependencies": {
"async": "^2.6.2",
"err-code": "^1.1.2",
"interface-datastore": "~0.6.0",
"libp2p-crypto": "~0.16.1",
"err-code": "^2.0.0",
"interface-datastore": "^0.7.0",
"libp2p-crypto": "^0.17.0",
"merge-options": "^1.0.1",
"node-forge": "~0.7.6",
"pull-stream": "^3.6.9",
"node-forge": "^0.8.5",
"promisify-es6": "^1.0.3",
"sanitize-filename": "^1.6.1"
},
"devDependencies": {
"aegir": "^18.2.1",
"aegir": "^20.0.0",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"chai-string": "^1.5.0",
"datastore-fs": "~0.8.0",
"datastore-level": "~0.10.0",
"datastore-fs": "^0.9.0",
"datastore-level": "^0.12.1",
"dirty-chai": "^2.0.1",
"level-js": "^4.0.1",
"mocha": "^5.2.0",
"multihashes": "~0.4.14",
"peer-id": "~0.12.2",
"level": "^5.0.1",
"multihashes": "^0.4.15",
"peer-id": "^0.13.2",
"rimraf": "^2.6.3"
},
"contributors": [
Expand Down
102 changes: 39 additions & 63 deletions src/cms.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
'use strict'

const setImmediate = require('async/setImmediate')
const series = require('async/series')
const detect = require('async/detect')
const waterfall = require('async/waterfall')
require('node-forge/lib/pkcs7')
require('node-forge/lib/pbe')
const forge = require('node-forge/lib/forge')
const util = require('./util')
const { certificateForKey, findAsync } = require('./util')
const errcode = require('err-code')

/**
Expand Down Expand Up @@ -40,44 +36,29 @@ class CMS {
*
* @param {string} name - The local key name.
* @param {Buffer} plain - The data to encrypt.
* @param {function(Error, Buffer)} callback
* @returns {undefined}
*/
encrypt (name, plain, callback) {
async encrypt (name, plain) {
const self = this
const done = (err, result) => setImmediate(() => callback(err, result))

if (!Buffer.isBuffer(plain)) {
return done(errcode(new Error('Plain data must be a Buffer'), 'ERR_INVALID_PARAMS'))
throw errcode(new Error('Plain data must be a Buffer'), 'ERR_INVALID_PARAMS')
}

series([
(cb) => self.keychain.findKeyByName(name, cb),
(cb) => self.keychain._getPrivateKey(name, cb)
], (err, results) => {
if (err) return done(err)
const key = await self.keychain.findKeyByName(name)
const pem = await self.keychain._getPrivateKey(name)
const privateKey = forge.pki.decryptRsaPrivateKey(pem, self.keychain._())
const certificate = await certificateForKey(key, privateKey)

let key = results[0]
let pem = results[1]
try {
const privateKey = forge.pki.decryptRsaPrivateKey(pem, self.keychain._())
util.certificateForKey(key, privateKey, (err, certificate) => {
if (err) return callback(err)

// create a p7 enveloped message
const p7 = forge.pkcs7.createEnvelopedData()
p7.addRecipient(certificate)
p7.content = forge.util.createBuffer(plain)
p7.encrypt()
// create a p7 enveloped message
const p7 = forge.pkcs7.createEnvelopedData()
p7.addRecipient(certificate)
p7.content = forge.util.createBuffer(plain)
p7.encrypt()

// convert message to DER
const der = forge.asn1.toDer(p7.toAsn1()).getBytes()
done(null, Buffer.from(der, 'binary'))
})
} catch (err) {
done(err)
}
})
// convert message to DER
const der = forge.asn1.toDer(p7.toAsn1()).getBytes()
return Buffer.from(der, 'binary')
}

/**
Expand All @@ -87,14 +68,11 @@ class CMS {
* exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
*
* @param {Buffer} cmsData - The CMS encrypted data to decrypt.
* @param {function(Error, Buffer)} callback
* @returns {undefined}
*/
decrypt (cmsData, callback) {
const done = (err, result) => setImmediate(() => callback(err, result))

async decrypt (cmsData) {
if (!Buffer.isBuffer(cmsData)) {
return done(errcode(new Error('CMS data is required'), 'ERR_INVALID_PARAMS'))
throw errcode(new Error('CMS data is required'), 'ERR_INVALID_PARAMS')
}

const self = this
Expand All @@ -104,7 +82,7 @@ class CMS {
const obj = forge.asn1.fromDer(buf)
cms = forge.pkcs7.messageFromAsn1(obj)
} catch (err) {
return done(errcode(new Error('Invalid CMS: ' + err.message), 'ERR_INVALID_CMS'))
throw errcode(new Error('Invalid CMS: ' + err.message), 'ERR_INVALID_CMS')
}

// Find a recipient whose key we hold. We only deal with recipient certs
Expand All @@ -118,31 +96,29 @@ class CMS {
keyId: r.issuer.find(a => a.shortName === 'CN').value
}
})
detect(
recipients,
(r, cb) => self.keychain.findKeyById(r.keyId, (err, info) => cb(null, !err && info)),
(err, r) => {
if (err) return done(err)
if (!r) {
const missingKeys = recipients.map(r => r.keyId)
err = errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), 'ERR_MISSING_KEYS', {
missingKeys
})
return done(err)
}

waterfall([
(cb) => self.keychain.findKeyById(r.keyId, cb),
(key, cb) => self.keychain._getPrivateKey(key.name, cb)
], (err, pem) => {
if (err) return done(err)

const privateKey = forge.pki.decryptRsaPrivateKey(pem, self.keychain._())
cms.decrypt(r.recipient, privateKey)
done(null, Buffer.from(cms.content.getBytes(), 'binary'))
})
const r = await findAsync(recipients, async (recipient) => {
try {
const key = await self.keychain.findKeyById(recipient.keyId)
if (key) return true
} catch (err) {
return false
}
)
return false
})

if (!r) {
const missingKeys = recipients.map(r => r.keyId)
throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), 'ERR_MISSING_KEYS', {
missingKeys
})
}

const key = await self.keychain.findKeyById(r.keyId)
const pem = await self.keychain._getPrivateKey(key.name)
const privateKey = forge.pki.decryptRsaPrivateKey(pem, self.keychain._())
cms.decrypt(r.recipient, privateKey)
return Buffer.from(cms.content.getBytes(), 'binary')
}
}

Expand Down
Loading

0 comments on commit bbfb00c

Please sign in to comment.