1
1
'use strict'
2
2
3
- const setImmediate = require ( 'async/setImmediate' )
4
- const series = require ( 'async/series' )
5
- const detect = require ( 'async/detect' )
6
- const waterfall = require ( 'async/waterfall' )
7
3
require ( 'node-forge/lib/pkcs7' )
8
4
require ( 'node-forge/lib/pbe' )
9
5
const forge = require ( 'node-forge/lib/forge' )
10
- const util = require ( './util' )
6
+ const { certificateForKey , findAsync } = require ( './util' )
11
7
const errcode = require ( 'err-code' )
12
8
13
9
/**
@@ -40,44 +36,29 @@ class CMS {
40
36
*
41
37
* @param {string } name - The local key name.
42
38
* @param {Buffer } plain - The data to encrypt.
43
- * @param {function(Error, Buffer) } callback
44
39
* @returns {undefined }
45
40
*/
46
- encrypt ( name , plain , callback ) {
41
+ async encrypt ( name , plain ) {
47
42
const self = this
48
- const done = ( err , result ) => setImmediate ( ( ) => callback ( err , result ) )
49
43
50
44
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' )
52
46
}
53
47
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 )
59
52
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 ( )
72
58
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' )
81
62
}
82
63
83
64
/**
@@ -87,14 +68,11 @@ class CMS {
87
68
* exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
88
69
*
89
70
* @param {Buffer } cmsData - The CMS encrypted data to decrypt.
90
- * @param {function(Error, Buffer) } callback
91
71
* @returns {undefined }
92
72
*/
93
- decrypt ( cmsData , callback ) {
94
- const done = ( err , result ) => setImmediate ( ( ) => callback ( err , result ) )
95
-
73
+ async decrypt ( cmsData ) {
96
74
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' )
98
76
}
99
77
100
78
const self = this
@@ -104,7 +82,7 @@ class CMS {
104
82
const obj = forge . asn1 . fromDer ( buf )
105
83
cms = forge . pkcs7 . messageFromAsn1 ( obj )
106
84
} 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' )
108
86
}
109
87
110
88
// Find a recipient whose key we hold. We only deal with recipient certs
@@ -118,31 +96,29 @@ class CMS {
118
96
keyId : r . issuer . find ( a => a . shortName === 'CN' ) . value
119
97
}
120
98
} )
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 )
139
99
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
144
106
}
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' )
146
122
}
147
123
}
148
124
0 commit comments