11'use strict'
22
3- const setImmediate = require ( 'async/setImmediate' )
4- const series = require ( 'async/series' )
5- const detect = require ( 'async/detect' )
6- const waterfall = require ( 'async/waterfall' )
73require ( 'node-forge/lib/pkcs7' )
84require ( 'node-forge/lib/pbe' )
95const forge = require ( 'node-forge/lib/forge' )
10- const util = require ( './util' )
6+ const { certificateForKey , findAsync } = require ( './util' )
117const errcode = require ( 'err-code' )
128
139/**
@@ -40,44 +36,29 @@ class CMS {
4036 *
4137 * @param {string } name - The local key name.
4238 * @param {Buffer } plain - The data to encrypt.
43- * @param {function(Error, Buffer) } callback
4439 * @returns {undefined }
4540 */
46- encrypt ( name , plain , callback ) {
41+ async encrypt ( name , plain ) {
4742 const self = this
48- const done = ( err , result ) => setImmediate ( ( ) => callback ( err , result ) )
4943
5044 if ( ! Buffer . isBuffer ( plain ) ) {
51- return done ( errcode ( new Error ( 'Plain data must be a Buffer' ) , 'ERR_INVALID_PARAMS' ) )
45+ throw errcode ( new Error ( 'Plain data must be a Buffer' ) , 'ERR_INVALID_PARAMS' )
5246 }
5347
54- series ( [
55- ( cb ) => self . keychain . findKeyByName ( name , cb ) ,
56- ( cb ) => self . keychain . _getPrivateKey ( name , cb )
57- ] , ( err , results ) => {
58- if ( err ) return done ( err )
48+ const key = await self . keychain . findKeyByName ( name )
49+ const pem = await self . keychain . _getPrivateKey ( name )
50+ const privateKey = forge . pki . decryptRsaPrivateKey ( pem , self . keychain . _ ( ) )
51+ const certificate = await certificateForKey ( key , privateKey )
5952
60- let key = results [ 0 ]
61- let pem = results [ 1 ]
62- try {
63- const privateKey = forge . pki . decryptRsaPrivateKey ( pem , self . keychain . _ ( ) )
64- util . certificateForKey ( key , privateKey , ( err , certificate ) => {
65- if ( err ) return callback ( err )
66-
67- // create a p7 enveloped message
68- const p7 = forge . pkcs7 . createEnvelopedData ( )
69- p7 . addRecipient ( certificate )
70- p7 . content = forge . util . createBuffer ( plain )
71- p7 . encrypt ( )
53+ // create a p7 enveloped message
54+ const p7 = forge . pkcs7 . createEnvelopedData ( )
55+ p7 . addRecipient ( certificate )
56+ p7 . content = forge . util . createBuffer ( plain )
57+ p7 . encrypt ( )
7258
73- // convert message to DER
74- const der = forge . asn1 . toDer ( p7 . toAsn1 ( ) ) . getBytes ( )
75- done ( null , Buffer . from ( der , 'binary' ) )
76- } )
77- } catch ( err ) {
78- done ( err )
79- }
80- } )
59+ // convert message to DER
60+ const der = forge . asn1 . toDer ( p7 . toAsn1 ( ) ) . getBytes ( )
61+ return Buffer . from ( der , 'binary' )
8162 }
8263
8364 /**
@@ -87,14 +68,11 @@ class CMS {
8768 * exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
8869 *
8970 * @param {Buffer } cmsData - The CMS encrypted data to decrypt.
90- * @param {function(Error, Buffer) } callback
9171 * @returns {undefined }
9272 */
93- decrypt ( cmsData , callback ) {
94- const done = ( err , result ) => setImmediate ( ( ) => callback ( err , result ) )
95-
73+ async decrypt ( cmsData ) {
9674 if ( ! Buffer . isBuffer ( cmsData ) ) {
97- return done ( errcode ( new Error ( 'CMS data is required' ) , 'ERR_INVALID_PARAMS' ) )
75+ throw errcode ( new Error ( 'CMS data is required' ) , 'ERR_INVALID_PARAMS' )
9876 }
9977
10078 const self = this
@@ -104,7 +82,7 @@ class CMS {
10482 const obj = forge . asn1 . fromDer ( buf )
10583 cms = forge . pkcs7 . messageFromAsn1 ( obj )
10684 } catch ( err ) {
107- return done ( errcode ( new Error ( 'Invalid CMS: ' + err . message ) , 'ERR_INVALID_CMS' ) )
85+ throw errcode ( new Error ( 'Invalid CMS: ' + err . message ) , 'ERR_INVALID_CMS' )
10886 }
10987
11088 // Find a recipient whose key we hold. We only deal with recipient certs
@@ -118,31 +96,29 @@ class CMS {
11896 keyId : r . issuer . find ( a => a . shortName === 'CN' ) . value
11997 }
12098 } )
121- detect (
122- recipients ,
123- ( r , cb ) => self . keychain . findKeyById ( r . keyId , ( err , info ) => cb ( null , ! err && info ) ) ,
124- ( err , r ) => {
125- if ( err ) return done ( err )
126- if ( ! r ) {
127- const missingKeys = recipients . map ( r => r . keyId )
128- err = errcode ( new Error ( 'Decryption needs one of the key(s): ' + missingKeys . join ( ', ' ) ) , 'ERR_MISSING_KEYS' , {
129- missingKeys
130- } )
131- return done ( err )
132- }
133-
134- waterfall ( [
135- ( cb ) => self . keychain . findKeyById ( r . keyId , cb ) ,
136- ( key , cb ) => self . keychain . _getPrivateKey ( key . name , cb )
137- ] , ( err , pem ) => {
138- if ( err ) return done ( err )
13999
140- const privateKey = forge . pki . decryptRsaPrivateKey ( pem , self . keychain . _ ( ) )
141- cms . decrypt ( r . recipient , privateKey )
142- done ( null , Buffer . from ( cms . content . getBytes ( ) , 'binary' ) )
143- } )
100+ const r = await findAsync ( recipients , async ( recipient ) => {
101+ try {
102+ const key = await self . keychain . findKeyById ( recipient . keyId )
103+ if ( key ) return true
104+ } catch ( err ) {
105+ return false
144106 }
145- )
107+ return false
108+ } )
109+
110+ if ( ! r ) {
111+ const missingKeys = recipients . map ( r => r . keyId )
112+ throw errcode ( new Error ( 'Decryption needs one of the key(s): ' + missingKeys . join ( ', ' ) ) , 'ERR_MISSING_KEYS' , {
113+ missingKeys
114+ } )
115+ }
116+
117+ const key = await self . keychain . findKeyById ( r . keyId )
118+ const pem = await self . keychain . _getPrivateKey ( key . name )
119+ const privateKey = forge . pki . decryptRsaPrivateKey ( pem , self . keychain . _ ( ) )
120+ cms . decrypt ( r . recipient , privateKey )
121+ return Buffer . from ( cms . content . getBytes ( ) , 'binary' )
146122 }
147123}
148124
0 commit comments