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,27 @@ 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 ) {
47- const self = this
48- const done = ( err , result ) => setImmediate ( ( ) => callback ( err , result ) )
49-
41+ async encrypt ( name , plain ) {
5042 if ( ! Buffer . isBuffer ( plain ) ) {
51- return done ( errcode ( new Error ( 'Plain data must be a Buffer' ) , 'ERR_INVALID_PARAMS' ) )
43+ throw errcode ( new Error ( 'Plain data must be a Buffer' ) , 'ERR_INVALID_PARAMS' )
5244 }
5345
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 )
59-
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 )
46+ const key = await this . keychain . findKeyByName ( name )
47+ const pem = await this . keychain . _getPrivateKey ( name )
48+ const privateKey = forge . pki . decryptRsaPrivateKey ( pem , this . keychain . _ ( ) )
49+ const certificate = await certificateForKey ( key , privateKey )
6650
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 ( )
51+ // create a p7 enveloped message
52+ const p7 = forge . pkcs7 . createEnvelopedData ( )
53+ p7 . addRecipient ( certificate )
54+ p7 . content = forge . util . createBuffer ( plain )
55+ p7 . encrypt ( )
7256
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- } )
57+ // convert message to DER
58+ const der = forge . asn1 . toDer ( p7 . toAsn1 ( ) ) . getBytes ( )
59+ return Buffer . from ( der , 'binary' )
8160 }
8261
8362 /**
@@ -87,24 +66,20 @@ class CMS {
8766 * exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
8867 *
8968 * @param {Buffer } cmsData - The CMS encrypted data to decrypt.
90- * @param {function(Error, Buffer) } callback
9169 * @returns {undefined }
9270 */
93- decrypt ( cmsData , callback ) {
94- const done = ( err , result ) => setImmediate ( ( ) => callback ( err , result ) )
95-
71+ async decrypt ( cmsData ) {
9672 if ( ! Buffer . isBuffer ( cmsData ) ) {
97- return done ( errcode ( new Error ( 'CMS data is required' ) , 'ERR_INVALID_PARAMS' ) )
73+ throw errcode ( new Error ( 'CMS data is required' ) , 'ERR_INVALID_PARAMS' )
9874 }
9975
100- const self = this
10176 let cms
10277 try {
10378 const buf = forge . util . createBuffer ( cmsData . toString ( 'binary' ) )
10479 const obj = forge . asn1 . fromDer ( buf )
10580 cms = forge . pkcs7 . messageFromAsn1 ( obj )
10681 } catch ( err ) {
107- return done ( errcode ( new Error ( 'Invalid CMS: ' + err . message ) , 'ERR_INVALID_CMS' ) )
82+ throw errcode ( new Error ( 'Invalid CMS: ' + err . message ) , 'ERR_INVALID_CMS' )
10883 }
10984
11085 // Find a recipient whose key we hold. We only deal with recipient certs
@@ -118,31 +93,29 @@ class CMS {
11893 keyId : r . issuer . find ( a => a . shortName === 'CN' ) . value
11994 }
12095 } )
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- }
13396
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 )
139-
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- } )
97+ const r = await findAsync ( recipients , async ( recipient ) => {
98+ try {
99+ const key = await this . keychain . findKeyById ( recipient . keyId )
100+ if ( key ) return true
101+ } catch ( err ) {
102+ return false
144103 }
145- )
104+ return false
105+ } )
106+
107+ if ( ! r ) {
108+ const missingKeys = recipients . map ( r => r . keyId )
109+ throw errcode ( new Error ( 'Decryption needs one of the key(s): ' + missingKeys . join ( ', ' ) ) , 'ERR_MISSING_KEYS' , {
110+ missingKeys
111+ } )
112+ }
113+
114+ const key = await this . keychain . findKeyById ( r . keyId )
115+ const pem = await this . keychain . _getPrivateKey ( key . name )
116+ const privateKey = forge . pki . decryptRsaPrivateKey ( pem , this . keychain . _ ( ) )
117+ cms . decrypt ( r . recipient , privateKey )
118+ return Buffer . from ( cms . content . getBytes ( ) , 'binary' )
146119 }
147120}
148121
0 commit comments