Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions modules/bitgo/test/v2/unit/keychains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,25 @@ describe('V2 Keychains', function () {
scope.done();
});

it('should add a safe child keychain with derivedFromParentWithHardenedPath', async function () {
it('should add a safe child keychain with derivedFromParentWithPath', async function () {
const scope = nock(bgUrl)
.post('/api/v2/tltc/key', function (body) {
body.pub.should.equal('pub');
body.parent.should.equal('parent-key-id');
body.safeId.should.equal('safe-id');
body.derivedFromParentWithHardenedPath.should.equal("m/7'");
body.derivedFromParentWithPath.should.equal("m/7'");
should.equal(body.path, undefined);
should.equal(body.derivedFromParentWithSeed, undefined);
return true;
})
.reply(200, { id: 'child-key-id', derivedFromParentWithHardenedPath: "m/7'", path: '/0/0' });
.reply(200, { id: 'child-key-id', derivedFromParentWithPath: "m/7'", path: '/0/0' });
const result = await keychains.add({
pub: 'pub',
parent: 'parent-key-id',
safeId: 'safe-id',
derivedFromParentWithHardenedPath: "m/7'",
derivedFromParentWithPath: "m/7'",
});
result.derivedFromParentWithHardenedPath.should.equal("m/7'");
result.derivedFromParentWithPath.should.equal("m/7'");
scope.done();
});
});
Expand Down
4 changes: 2 additions & 2 deletions modules/sdk-core/src/bitgo/keychain/iKeychains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface Keychain {
derivationPath?: string;
derivedFromParentWithSeed?: string;
/** Hardened path from the safe parent (`m/<n>'`). @experimental */
derivedFromParentWithHardenedPath?: string;
derivedFromParentWithPath?: string;
/** Safe root key id this child key was derived from (WCN-1172). */
parent?: string;
commonPub?: string;
Expand Down Expand Up @@ -149,7 +149,7 @@ export interface AddKeychainOptions {
enterprise?: string;
derivedFromParentWithSeed?: string;
/** Hardened path from the safe parent (`m/<n>'`). @experimental */
derivedFromParentWithHardenedPath?: string;
derivedFromParentWithPath?: string;
/** Safe user-root key id this child was derived from. @experimental */
parent?: string;
disableKRSEmail?: boolean;
Expand Down
4 changes: 2 additions & 2 deletions modules/sdk-core/src/bitgo/keychain/keychains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ export class Keychains implements IKeychains {
'originalPasscodeEncryptionCode',
'enterprise',
'derivedFromParentWithSeed',
'derivedFromParentWithHardenedPath',
'derivedFromParentWithPath',
'parent',
'safeId',
]
Expand Down Expand Up @@ -297,7 +297,7 @@ export class Keychains implements IKeychains {
originalPasscodeEncryptionCode: params.originalPasscodeEncryptionCode,
enterprise: params.enterprise,
derivedFromParentWithSeed: params.derivedFromParentWithSeed,
derivedFromParentWithHardenedPath: params.derivedFromParentWithHardenedPath,
derivedFromParentWithPath: params.derivedFromParentWithPath,
parent: params.parent,
disableKRSEmail: params.disableKRSEmail,
krsSpecific: params.krsSpecific,
Expand Down
2 changes: 1 addition & 1 deletion modules/sdk-core/src/bitgo/safe/safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class Safe implements ISafe {
keyType: 'independent',
parent: userRootId,
safeId: this.id(),
derivedFromParentWithHardenedPath,
derivedFromParentWithPath: derivedFromParentWithHardenedPath,
});
const childId = child.id;
if (childId.length === 0) {
Expand Down
12 changes: 6 additions & 6 deletions modules/sdk-core/src/bitgo/wallet/safeKeychain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ type ResolveSafeKeyMaterialParams = SafeKeyMaterialBaseParams & {
* Shared core that resolves safe key material for a pub-only safe child. Returns the CHILD
* `{prv, pub}` only — never the root — so the root can never leak into a share document.
*
* Onchain secp256k1: decrypt root, hardened-derive at `derivedFromParentWithHardenedPath`
* Onchain secp256k1: decrypt root, hardened-derive at `derivedFromParentWithPath`
* (`m/<n>'`), and verify the registered pub. TSS and ed25519 onchain throw via
* `makeNotImplementedError` — the caller constructs its own error class + message, so the
* guard set stays shared while signing/sharing report their own errors.
Expand Down Expand Up @@ -142,13 +142,13 @@ async function resolveSafeKeyMaterial(params: ResolveSafeKeyMaterialParams): Pro
if (!childKeychain.pub) {
throw new Error(`Safe wallet ${walletId}: child keychain is missing pub for pre-sign verification`);
}
if (childKeychain.derivedFromParentWithHardenedPath === undefined) {
throw new Error(`Safe wallet ${walletId}: child keychain is missing derivedFromParentWithHardenedPath`);
if (childKeychain.derivedFromParentWithPath === undefined) {
throw new Error(`Safe wallet ${walletId}: child keychain is missing derivedFromParentWithPath`);
}

const derived = deriveSafeChildHardenedFromXprv(
rootPrv,
parseDerivedFromParentWithHardenedPath(childKeychain.derivedFromParentWithHardenedPath)
parseDerivedFromParentWithHardenedPath(childKeychain.derivedFromParentWithPath)
);
if (derived.pub !== childKeychain.pub) {
throw new SafeDerivedPublicKeyMismatchError(walletId, childKeychain.pub, derived.pub);
Expand All @@ -163,7 +163,7 @@ async function resolveSafeKeyMaterial(params: ResolveSafeKeyMaterialParams): Pro
/**
* Resolve signing material for a safe owner (child key has no encryptedPrv).
*
* Onchain secp256k1: decrypt root, hardened-derive at `derivedFromParentWithHardenedPath`
* Onchain secp256k1: decrypt root, hardened-derive at `derivedFromParentWithPath`
* (`m/<n>'`), and verify the registered pub.
* TSS and ed25519 onchain: throw — do not return root material or BIP32-derive the wrong curve.
*
Expand Down Expand Up @@ -205,7 +205,7 @@ function safeShareSlotDetail(slot: SafeKeyMaterialSlot, params: ResolveSafeChild
/**
* Resolve sharing material for a safe owner (child key has no encryptedPrv).
*
* Onchain secp256k1: decrypt root, hardened-derive at `derivedFromParentWithHardenedPath`
* Onchain secp256k1: decrypt root, hardened-derive at `derivedFromParentWithPath`
* (`m/<n>'`), verify the registered pub, and return the CHILD `{prv, pub}` — never the root.
* TSS and ed25519 onchain: throw `SafeShareNotImplementedError` naming the slot + blocker.
*
Expand Down
19 changes: 19 additions & 0 deletions modules/sdk-core/test/unit/bitgo/keychain/keychains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,25 @@ describe('Keychains.createBackup', function () {
keychains = buildKeychains();
});

describe('safe child key registration', function () {
it('serializes the hardened derivation path', async function () {
await keychains.add({
pub: XPUB,
source: 'user',
keyType: 'independent',
parent: 'user-root-id',
safeId: SAFE_ID,
derivedFromParentWithPath: "m/7'",
});

const derivedPath = sentBody().derivedFromParentWithPath;
if (typeof derivedPath !== 'string') {
throw new Error('expected derivedFromParentWithPath to be serialized');
}
derivedPath.should.equal("m/7'");
});
});

describe('safe ed25519Multisig root (slot ④)', function () {
it('posts a 108-char composite pub built from the generated key', async function () {
await keychains.createBackup({ passphrase: 'pw', safeId: SAFE_ID });
Expand Down
6 changes: 3 additions & 3 deletions modules/sdk-core/test/unit/bitgo/safe/safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ describe('Safe', function () {
keyType: 'independent',
parent: 'user-root-id',
safeId: 'test-safe-id',
derivedFromParentWithHardenedPath: "m/0'",
derivedFromParentWithPath: "m/0'",
});
addArgs.should.not.have.property('encryptedPrv');
addArgs.should.not.have.property('derivedFromParentWithSeed');
Expand All @@ -214,7 +214,7 @@ describe('Safe', function () {
mintedSafeId.should.equal('test-safe-id');
});

it('registers the child with derivedFromParentWithHardenedPath at a non-zero mint index', async function () {
it('registers the child with derivedFromParentWithPath at a non-zero mint index', async function () {
derivationQuery.returns({
result: sinon.stub().resolves({ slot: 'secp256k1Multisig', index: 7 }),
});
Expand All @@ -224,7 +224,7 @@ describe('Safe', function () {

const addArgs = keychainsAdd.firstCall.args[0];
addArgs.pub.should.equal(childAt7.pub);
addArgs.derivedFromParentWithHardenedPath.should.equal("m/7'");
addArgs.derivedFromParentWithPath.should.equal("m/7'");
addArgs.should.not.have.property('path');
addArgs.should.not.have.property('derivedFromParentWithSeed');
});
Expand Down
18 changes: 9 additions & 9 deletions modules/sdk-core/test/unit/bitgo/wallet/safeGetUserPrv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ describe('WCN-1200 safe child getUserPrv root-fetch detour', function () {
hardened.prv.should.not.eql(softDerivedPrv);
});

it('parses derivedFromParentWithHardenedPath as m/<n> primed', function () {
it('parses the hardened derivation path as m/<n> primed', function () {
parseDerivedFromParentWithHardenedPath("m/0'").should.eql(0);
parseDerivedFromParentWithHardenedPath("m/123'").should.eql(123);
(() => parseDerivedFromParentWithHardenedPath('m/0')).should.throw(/derivedFromParentWithHardenedPath/);
Expand Down Expand Up @@ -256,7 +256,7 @@ describe('WCN-1200 safe child getUserPrv root-fetch detour', function () {
pub: hardened.pub,
type: 'independent',
parent: rootKeyId,
derivedFromParentWithHardenedPath: "m/123'",
derivedFromParentWithPath: "m/123'",
},
walletPassphrase: passphrase,
});
Expand All @@ -267,7 +267,7 @@ describe('WCN-1200 safe child getUserPrv root-fetch detour', function () {
mockBaseCoin.deriveKeyWithSeed.notCalled.should.be.true();
});

it('requires derivedFromParentWithHardenedPath on the child keychain', async function () {
it('requires derivedFromParentWithPath on the child keychain', async function () {
const wallet = makeWallet({ safe: 'safe-id-1' });
keychainsGetStub.resolves({
id: rootKeyId,
Expand All @@ -287,10 +287,10 @@ describe('WCN-1200 safe child getUserPrv root-fetch detour', function () {
},
walletPassphrase: passphrase,
})
.should.be.rejectedWith(/missing derivedFromParentWithHardenedPath/);
.should.be.rejectedWith(/missing derivedFromParentWithPath/);
});

it('fails closed when derivedFromParentWithHardenedPath does not match the registered pub', async function () {
it('fails closed when derivedFromParentWithPath does not match the registered pub', async function () {
const wallet = makeWallet({ safe: 'safe-id-1' });
keychainsGetStub.resolves({
id: rootKeyId,
Expand All @@ -307,14 +307,14 @@ describe('WCN-1200 safe child getUserPrv root-fetch detour', function () {
pub: hardened.pub,
type: 'independent',
parent: rootKeyId,
derivedFromParentWithHardenedPath: "m/0'",
derivedFromParentWithPath: "m/0'",
},
walletPassphrase: passphrase,
})
.should.be.rejectedWith(SafeDerivedPublicKeyMismatchError);
});

it('rejects a malformed derivedFromParentWithHardenedPath', async function () {
it('rejects a malformed derivedFromParentWithPath', async function () {
const wallet = makeWallet({ safe: 'safe-id-1' });
keychainsGetStub.resolves({
id: rootKeyId,
Expand All @@ -331,7 +331,7 @@ describe('WCN-1200 safe child getUserPrv root-fetch detour', function () {
pub: hardened.pub,
type: 'independent',
parent: rootKeyId,
derivedFromParentWithHardenedPath: "not-a-path'",
derivedFromParentWithPath: "not-a-path'",
},
walletPassphrase: passphrase,
})
Expand Down Expand Up @@ -395,7 +395,7 @@ describe('WCN-1200 safe child getUserPrv root-fetch detour', function () {
pub: 'xpub-wrong-registered-key',
type: 'independent',
parent: rootKeyId,
derivedFromParentWithHardenedPath: "m/123'",
derivedFromParentWithPath: "m/123'",
},
walletPassphrase: passphrase,
})
Expand Down
4 changes: 2 additions & 2 deletions modules/sdk-core/test/unit/bitgo/wallet/safeShareWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ describe('Safe wallet spend sharing', function () {
pub: hardened.pub,
type: 'independent' as const,
parent: rootKeyId,
derivedFromParentWithHardenedPath: "m/123'",
derivedFromParentWithPath: "m/123'",
});
const publicOnlyKeychain = (id: string) => ({ id, pub: 'pub-' + id, type: 'independent' as const });
const rootKeychain = {
Expand Down Expand Up @@ -189,7 +189,7 @@ describe('Safe wallet spend sharing', function () {
id === rootKeyId
? rootKeychain
: id === 'user-key'
? { ...childKeychain(id), pub: 'wrong-child-pub', derivedFromParentWithHardenedPath: "m/123'" }
? { ...childKeychain(id), pub: 'wrong-child-pub', derivedFromParentWithPath: "m/123'" }
: publicOnlyKeychain(id)
)
);
Expand Down
Loading