@@ -176,7 +176,13 @@ function webpushSecret(header, mode) {
176176 SHA_256_LENGTH ) ) ;
177177}
178178
179- function extractSecret ( header , mode ) {
179+ function extractSecret ( header , mode , keyLookupCallback ) {
180+ if ( keyLookupCallback ) {
181+ if ( ! isFunction ( keyLookupCallback ) ) {
182+ throw new Error ( 'Callback is not a function' )
183+ }
184+ }
185+
180186 if ( header . key ) {
181187 if ( header . key . length !== KEY_LENGTH ) {
182188 throw new Error ( 'An explicit key must be ' + KEY_LENGTH + ' bytes' ) ;
@@ -186,7 +192,11 @@ function extractSecret(header, mode) {
186192
187193 if ( ! header . privateKey ) {
188194 // Lookup based on keyid
189- var key = header . keymap && header . keymap [ header . keyid ] ;
195+ if ( ! keyLookupCallback ) {
196+ var key = header . keymap && header . keymap [ header . keyid ] ;
197+ } else {
198+ var key = keyLookupCallback ( header . keyid )
199+ }
190200 if ( ! key ) {
191201 throw new Error ( 'No saved key (keyid: "' + header . keyid + '")' ) ;
192202 }
@@ -196,7 +206,7 @@ function extractSecret(header, mode) {
196206 return webpushSecret ( header , mode ) ;
197207}
198208
199- function deriveKeyAndNonce ( header , mode ) {
209+ function deriveKeyAndNonce ( header , mode , lookupKeyCallback ) {
200210 if ( ! header . salt ) {
201211 throw new Error ( 'must include a salt parameter for ' + header . version ) ;
202212 }
@@ -207,18 +217,18 @@ function deriveKeyAndNonce(header, mode) {
207217 // really old
208218 keyInfo = 'Content-Encoding: aesgcm128' ;
209219 nonceInfo = 'Content-Encoding: nonce' ;
210- secret = extractSecretAndContext ( header , mode ) . secret ;
220+ secret = extractSecretAndContext ( header , mode , lookupKeyCallback ) . secret ;
211221 } else if ( header . version === 'aesgcm' ) {
212222 // old
213- var s = extractSecretAndContext ( header , mode ) ;
223+ var s = extractSecretAndContext ( header , mode , lookupKeyCallback ) ;
214224 keyInfo = info ( 'aesgcm' , s . context ) ;
215225 nonceInfo = info ( 'nonce' , s . context ) ;
216226 secret = s . secret ;
217227 } else if ( header . version === 'aes128gcm' ) {
218228 // latest
219229 keyInfo = Buffer . from ( 'Content-Encoding: aes128gcm\0' ) ;
220230 nonceInfo = Buffer . from ( 'Content-Encoding: nonce\0' ) ;
221- secret = extractSecret ( header , mode ) ;
231+ secret = extractSecret ( header , mode , lookupKeyCallback ) ;
222232 } else {
223233 throw new Error ( 'Unable to set context for mode ' + params . version ) ;
224234 }
@@ -361,13 +371,13 @@ function decryptRecord(key, counter, buffer, header, last) {
361371 *
362372 * The |params.privateKey| includes the private key of the receiver.
363373 */
364- function decrypt ( buffer , params ) {
374+ function decrypt ( buffer , params , keyLookupCallback ) {
365375 var header = parseParams ( params ) ;
366376 if ( header . version === 'aes128gcm' ) {
367377 var headerLength = readHeader ( buffer , header ) ;
368378 buffer = buffer . slice ( headerLength ) ;
369379 }
370- var key = deriveKeyAndNonce ( header , MODE_DECRYPT ) ;
380+ var key = deriveKeyAndNonce ( header , MODE_DECRYPT , keyLookupCallback ) ;
371381 var start = 0 ;
372382 var result = new Buffer ( 0 ) ;
373383
@@ -454,7 +464,7 @@ function writeHeader(header) {
454464 * receiver. |params.privateKey| is used to establish a shared secret. Key
455465 * pairs can be created using |crypto.createECDH()|.
456466 */
457- function encrypt ( buffer , params ) {
467+ function encrypt ( buffer , params , keyLookupCallback ) {
458468 if ( ! Buffer . isBuffer ( buffer ) ) {
459469 throw new Error ( 'buffer argument must be a Buffer' ) ;
460470 }
@@ -475,7 +485,7 @@ function encrypt(buffer, params) {
475485 result = new Buffer ( 0 ) ;
476486 }
477487
478- var key = deriveKeyAndNonce ( header , MODE_ENCRYPT ) ;
488+ var key = deriveKeyAndNonce ( header , MODE_ENCRYPT , keyLookupCallback ) ;
479489 var start = 0 ;
480490 var padSize = PAD_SIZE [ header . version ] ;
481491 var overhead = padSize ;
@@ -516,6 +526,11 @@ function encrypt(buffer, params) {
516526 return result ;
517527}
518528
529+
530+ function isFunction ( object ) {
531+ return typeof ( object ) === 'function' ;
532+ }
533+
519534module . exports = {
520535 decrypt : decrypt ,
521536 encrypt : encrypt
0 commit comments