22 * Dependencies
33 */
44const supportedAlgorithms = require ( './algorithms' )
5+ const InvalidDescriptorError = require ( './errors/InvalidDescriptorError' )
56
67/**
78 * KeyChain
@@ -10,14 +11,21 @@ class KeyChain {
1011
1112 /**
1213 * constructor
14+ *
15+ * @param data {Object} Keychain data
16+ * @param options {Object} Optional configuration
17+ * @param options.crypto {Object} Optional crypto instance for cross-package compatibility
1318 */
14- constructor ( data ) {
19+ constructor ( data , options = { } ) {
1520 // use data as the descriptor if descriptor property is missing
1621 if ( ! data . descriptor ) {
1722 data = { descriptor : data }
1823 }
1924
2025 Object . assign ( this , data )
26+
27+ // Store crypto instance if provided
28+ this . _crypto = options . crypto
2129 }
2230
2331 /**
@@ -34,14 +42,14 @@ class KeyChain {
3442 * @param {Object } params
3543 * @return {Promise }
3644 */
37- static generateKey ( params ) {
45+ static generateKey ( params , crypto ) {
3846 let normalizedAlgorithm = supportedAlgorithms . normalize ( 'generateKey' , params . alg )
3947
4048 if ( normalizedAlgorithm instanceof Error ) {
4149 return Promise . reject ( normalizedAlgorithm )
4250 }
4351
44- let algorithm = new normalizedAlgorithm ( params )
52+ let algorithm = new normalizedAlgorithm ( { ... params , crypto } )
4553
4654 return algorithm . generateKey ( )
4755 }
@@ -53,24 +61,28 @@ class KeyChain {
5361 * @param {Object } jwk
5462 * @return {Promise }
5563 */
56- static importKey ( jwk ) {
64+ static importKey ( jwk , crypto ) {
5765 let { alg} = jwk
5866 let normalizedAlgorithm = supportedAlgorithms . normalize ( 'importKey' , alg )
5967
6068 if ( normalizedAlgorithm instanceof Error ) {
6169 return Promise . reject ( normalizedAlgorithm )
6270 }
6371
64- let algorithm = new normalizedAlgorithm ( { alg} )
72+ let algorithm = new normalizedAlgorithm ( { alg, crypto } )
6573
6674 return algorithm . importKey ( jwk )
6775 }
6876
6977 /**
7078 * restore
79+ *
80+ * @param data {Object} Keychain data
81+ * @param options {Object} Optional configuration
82+ * @param options.crypto {Object} Optional crypto instance for cross-package compatibility
7183 */
72- static restore ( data ) {
73- let keys = new KeyChain ( data )
84+ static restore ( data , options ) {
85+ let keys = new KeyChain ( data , options )
7486 return keys . importKeys ( ) . then ( ( ) => keys )
7587 }
7688
@@ -84,22 +96,44 @@ class KeyChain {
8496
8597 // import key
8698 if ( props . includes ( 'alg' ) ) {
87- return KeyChain . importKey ( object ) . then ( cryptoKey => {
88- if ( cryptoKey . type === 'private' ) {
99+ return KeyChain . importKey ( object , this . _crypto ) . then ( cryptoKey => {
100+ if ( cryptoKey . type === 'private' && ! container . privateKey ) {
89101 Object . defineProperty ( container , 'privateKey' , {
90102 enumerable : false ,
91103 value : cryptoKey
92104 } )
93105 }
94106
95- if ( cryptoKey . type === 'public' ) {
107+ if ( cryptoKey . type === 'public' && ! container . publicKey ) {
96108 Object . defineProperty ( container , 'publicKey' , {
97109 enumerable : false ,
98110 value : cryptoKey
99111 } )
100112 }
101113 } )
102114
115+ // import key pair structure (has privateJwk and publicJwk)
116+ } else if ( props . includes ( 'privateJwk' ) && props . includes ( 'publicJwk' ) ) {
117+ // Import both private and public keys
118+ return Promise . all ( [
119+ KeyChain . importKey ( object . privateJwk , this . _crypto ) ,
120+ KeyChain . importKey ( object . publicJwk , this . _crypto )
121+ ] ) . then ( ( [ privateKey , publicKey ] ) => {
122+ if ( ! object . privateKey ) {
123+ Object . defineProperty ( object , 'privateKey' , {
124+ enumerable : false ,
125+ value : privateKey
126+ } )
127+ }
128+
129+ if ( ! object . publicKey ) {
130+ Object . defineProperty ( object , 'publicKey' , {
131+ enumerable : false ,
132+ value : publicKey
133+ } )
134+ }
135+ } )
136+
103137 // recurse
104138 } else {
105139 return Promise . all (
@@ -109,7 +143,7 @@ class KeyChain {
109143 let subProps = Object . keys ( subObject )
110144 //console.log('RECURSE WITH', name, subDescriptor, subObject, subProps)
111145
112- this . importKeys ( {
146+ return this . importKeys ( {
113147 descriptor : subDescriptor ,
114148 object : subObject ,
115149 container : object ,
@@ -141,7 +175,7 @@ class KeyChain {
141175 // generate key(pair), assign resulting object to keychain,
142176 // and add JWK for public key to JWK Set
143177 if ( params . alg ) {
144- return KeyChain . generateKey ( params ) . then ( result => {
178+ return KeyChain . generateKey ( params , this . _crypto ) . then ( result => {
145179 container [ key ] = result
146180
147181 if ( result . publicJwk ) {
@@ -164,7 +198,7 @@ class KeyChain {
164198
165199 // invalid descriptor
166200 } else {
167- throw new InvalidDescriptorError ( key , value )
201+ throw new InvalidDescriptorError ( key , params )
168202 }
169203 } )
170204 ) . then ( ( ) => {
0 commit comments