File tree Expand file tree Collapse file tree 5 files changed +57
-2
lines changed Expand file tree Collapse file tree 5 files changed +57
-2
lines changed Original file line number Diff line number Diff line change 11{
22 "name" : " bitgo" ,
3- "version" : " 3.4.9 " ,
3+ "version" : " 3.4.10 " ,
44 "description" : " BitGo Javascript SDK" ,
55 "main" : " ./src/index.js" ,
66 "keywords" : [
Original file line number Diff line number Diff line change @@ -105,6 +105,21 @@ BaseCoin.prototype.toJSON = function() {
105105 return undefined ;
106106} ;
107107
108+ BaseCoin . prototype . deriveKeyWithSeed = function ( { key, seed } ) {
109+ const derivationPathInput = bitcoin . crypto . hash256 ( `${ seed } ` ) . toString ( 'hex' ) ;
110+ const derivationPathParts = [
111+ parseInt ( derivationPathInput . slice ( 0 , 7 ) , 16 ) ,
112+ parseInt ( derivationPathInput . slice ( 7 , 14 ) , 16 )
113+ ] ;
114+ const derivationPath = 'm/999999/' + derivationPathParts . join ( '/' ) ;
115+ const keyNode = bitcoin . HDNode . fromBase58 ( key ) ;
116+ const derivedKeyNode = bitcoin . hdPath ( keyNode ) . derive ( derivationPath ) ;
117+ return {
118+ key : derivedKeyNode . toBase58 ( ) ,
119+ derivationPath : derivationPath
120+ } ;
121+ } ;
122+
108123BaseCoin . prototype . initiateRecovery = function ( params ) {
109124 const keys = [ ] ;
110125 const userKey = params . userKey ; // Box A
Original file line number Diff line number Diff line change @@ -522,9 +522,14 @@ Wallet.prototype.signTransaction = function(params, callback) {
522522 if ( ! txPrebuild || typeof txPrebuild !== 'object' ) {
523523 throw new Error ( 'txPrebuild must be an object' ) ;
524524 }
525- var userPrv = params . prv ;
525+ let userPrv = params . prv ;
526526 if ( userPrv && typeof userPrv !== 'string' ) {
527527 throw new Error ( 'prv must be a string' ) ;
528+ }
529+ if ( userPrv && params . coldDerivationSeed ) {
530+ // the derivation only makes sense when a key already exists
531+ const derivation = this . baseCoin . deriveKeyWithSeed ( { key : userPrv , seed : params . coldDerivationSeed } ) ;
532+ userPrv = derivation . key ;
528533 } else if ( ! userPrv ) {
529534 if ( ! userKeychain || typeof userKeychain !== 'object' ) {
530535 throw new Error ( 'keychain must be an object' ) ;
Original file line number Diff line number Diff line change @@ -183,6 +183,7 @@ Wallets.prototype.generateWallet = function(params, callback) {
183183 let backupKeychain ;
184184 let bitgoKeychain ;
185185 let userKeychainParams ;
186+ let derivationPath ;
186187
187188 const passphrase = params . passphrase ;
188189 const canEncrypt = ( ! ! passphrase && typeof passphrase === 'string' ) ;
@@ -195,6 +196,12 @@ Wallets.prototype.generateWallet = function(params, callback) {
195196 if ( params . userKey ) {
196197 userKeychain = { 'pub' : params . userKey } ;
197198 userKeychainParams = userKeychain ;
199+ if ( params . coldDerivationSeed ) {
200+ // the derivation only makes sense when a key already exists
201+ const derivation = self . baseCoin . deriveKeyWithSeed ( { key : params . userKey , seed : params . coldDerivationSeed } ) ;
202+ derivationPath = derivation . derivationPath ;
203+ userKeychain . pub = derivation . key ;
204+ }
198205 } else {
199206 if ( ! canEncrypt ) {
200207 throw new Error ( 'cannot generate user keypair without passphrase' ) ;
@@ -296,6 +303,10 @@ Wallets.prototype.generateWallet = function(params, callback) {
296303 result . warning = 'Be sure to backup the backup keychain -- it is not stored anywhere else!' ;
297304 }
298305
306+ if ( derivationPath ) {
307+ userKeychain . derivationPath = derivationPath ;
308+ }
309+
299310 return result ;
300311 } )
301312 . nodeify ( callback ) ;
Original file line number Diff line number Diff line change @@ -171,6 +171,30 @@ describe('V2 Wallets:', function() {
171171 } ) ;
172172 } ) ;
173173
174+ it ( 'should make wallet with provided user key and custom derivation path' , function ( ) {
175+ var userXpub = keychains . create ( ) . pub ; // random xpub
176+ var params = {
177+ label : label ,
178+ userKey : userXpub ,
179+ coldDerivationSeed : 'custom-derivation-seed' ,
180+ passphrase : passphrase
181+ } ;
182+
183+ return wallets . generateWallet ( params )
184+ . then ( function ( res ) {
185+ res . should . have . property ( 'wallet' ) ;
186+ res . should . have . property ( 'userKeychain' ) ;
187+ res . should . have . property ( 'backupKeychain' ) ;
188+ res . should . have . property ( 'bitgoKeychain' ) ;
189+
190+ res . userKeychain . should . have . property ( 'pub' ) ;
191+ res . userKeychain . should . have . property ( 'derivationPath' ) ;
192+ res . userKeychain . derivationPath . should . equal ( 'm/999999/112305623/88990619' ) ;
193+ res . userKeychain . should . not . have . property ( 'prv' ) ;
194+ res . userKeychain . should . not . have . property ( 'encryptedPrv' ) ;
195+ } ) ;
196+ } ) ;
197+
174198 it ( 'should generate wallet and freeze it' , function ( ) {
175199 var backupXpub = keychains . create ( ) . pub ; // random xpub
176200 var userXpub = keychains . create ( ) . pub ; // random xpub
You can’t perform that action at this time.
0 commit comments