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,27 @@ 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 ) {
47
- const self = this
48
- const done = ( err , result ) => setImmediate ( ( ) => callback ( err , result ) )
49
-
41
+ async encrypt ( name , plain ) {
50
42
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' )
52
44
}
53
45
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 )
66
50
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 ( )
72
56
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' )
81
60
}
82
61
83
62
/**
@@ -87,24 +66,20 @@ class CMS {
87
66
* exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
88
67
*
89
68
* @param {Buffer } cmsData - The CMS encrypted data to decrypt.
90
- * @param {function(Error, Buffer) } callback
91
69
* @returns {undefined }
92
70
*/
93
- decrypt ( cmsData , callback ) {
94
- const done = ( err , result ) => setImmediate ( ( ) => callback ( err , result ) )
95
-
71
+ async decrypt ( cmsData ) {
96
72
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' )
98
74
}
99
75
100
- const self = this
101
76
let cms
102
77
try {
103
78
const buf = forge . util . createBuffer ( cmsData . toString ( 'binary' ) )
104
79
const obj = forge . asn1 . fromDer ( buf )
105
80
cms = forge . pkcs7 . messageFromAsn1 ( obj )
106
81
} 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' )
108
83
}
109
84
110
85
// Find a recipient whose key we hold. We only deal with recipient certs
@@ -118,31 +93,29 @@ class CMS {
118
93
keyId : r . issuer . find ( a => a . shortName === 'CN' ) . value
119
94
}
120
95
} )
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
96
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
144
103
}
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' )
146
119
}
147
120
}
148
121
0 commit comments