@bitgo-beta/passkey-crypto 0.0.1-beta.4 → 0.0.1-beta.400
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/attachPasskeyToWallet.d.ts +11 -0
- package/dist/src/attachPasskeyToWallet.d.ts.map +1 -0
- package/dist/src/attachPasskeyToWallet.js +68 -0
- package/dist/src/derivePasskeyPrfKey.d.ts +14 -0
- package/dist/src/derivePasskeyPrfKey.d.ts.map +1 -0
- package/dist/src/derivePasskeyPrfKey.js +68 -0
- package/dist/src/index.d.ts +8 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +16 -6
- package/dist/src/prfHelpers.d.ts.map +1 -1
- package/dist/src/prfHelpers.js +19 -4
- package/dist/src/registerPasskey.d.ts +9 -0
- package/dist/src/registerPasskey.d.ts.map +1 -0
- package/dist/src/registerPasskey.js +93 -0
- package/dist/src/removePasskeyFromAccount.d.ts +11 -0
- package/dist/src/removePasskeyFromAccount.d.ts.map +1 -0
- package/dist/src/removePasskeyFromAccount.js +15 -0
- package/dist/src/removePasskeyFromWallet.d.ts +9 -0
- package/dist/src/removePasskeyFromWallet.d.ts.map +1 -0
- package/dist/src/removePasskeyFromWallet.js +22 -0
- package/dist/test/integration/helpers/fixtures.d.ts +12 -0
- package/dist/test/integration/helpers/fixtures.d.ts.map +1 -0
- package/dist/test/integration/helpers/fixtures.js +15 -0
- package/dist/test/integration/helpers/mockBitGo.d.ts +27 -0
- package/dist/test/integration/helpers/mockBitGo.d.ts.map +1 -0
- package/dist/test/integration/helpers/mockBitGo.js +148 -0
- package/dist/test/integration/helpers/mockProvider.d.ts +5 -0
- package/dist/test/integration/helpers/mockProvider.d.ts.map +1 -0
- package/dist/test/integration/helpers/mockProvider.js +37 -0
- package/dist/test/integration/passkeyLifecycle.test.d.ts +2 -0
- package/dist/test/integration/passkeyLifecycle.test.d.ts.map +1 -0
- package/dist/test/integration/passkeyLifecycle.test.js +152 -0
- package/dist/test/unit/attachPasskeyToWallet.test.d.ts +2 -0
- package/dist/test/unit/attachPasskeyToWallet.test.d.ts.map +1 -0
- package/dist/test/unit/attachPasskeyToWallet.test.js +224 -0
- package/dist/test/unit/base64url.test.d.ts +2 -0
- package/dist/test/unit/base64url.test.d.ts.map +1 -0
- package/dist/test/unit/base64url.test.js +75 -0
- package/dist/test/unit/deriveEnterpriseSalt.test.js +8 -4
- package/dist/test/unit/derivePasskeyPrfKey.test.d.ts +2 -0
- package/dist/test/unit/derivePasskeyPrfKey.test.d.ts.map +1 -0
- package/dist/test/unit/derivePasskeyPrfKey.test.js +152 -0
- package/dist/test/unit/registerPasskey.test.d.ts +2 -0
- package/dist/test/unit/registerPasskey.test.d.ts.map +1 -0
- package/dist/test/unit/registerPasskey.test.js +155 -0
- package/dist/test/unit/removePasskeyFromAccount.test.d.ts +2 -0
- package/dist/test/unit/removePasskeyFromAccount.test.d.ts.map +1 -0
- package/dist/test/unit/removePasskeyFromAccount.test.js +88 -0
- package/dist/test/unit/removePasskeyFromWallet.test.d.ts +2 -0
- package/dist/test/unit/removePasskeyFromWallet.test.d.ts.map +1 -0
- package/dist/test/unit/removePasskeyFromWallet.test.js +170 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -6
- package/LICENSE +0 -191
- package/dist/src/deriveEnterpriseSalt.d.ts +0 -12
- package/dist/src/deriveEnterpriseSalt.d.ts.map +0 -1
- package/dist/src/deriveEnterpriseSalt.js +0 -56
- package/dist/src/derivePassword.d.ts +0 -11
- package/dist/src/derivePassword.d.ts.map +0 -1
- package/dist/src/derivePassword.js +0 -16
- package/dist/src/webAuthnTypes.d.ts +0 -18
- package/dist/src/webAuthnTypes.d.ts.map +0 -1
- package/dist/src/webAuthnTypes.js +0 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BitGoBase, EncryptionVersion, Keychain, type WebAuthnOtpDevice, type WebAuthnProvider } from '@bitgo-beta/sdk-core';
|
|
2
|
+
export declare function attachPasskeyToWallet(params: {
|
|
3
|
+
bitgo: BitGoBase;
|
|
4
|
+
coin: string;
|
|
5
|
+
walletId: string;
|
|
6
|
+
device: WebAuthnOtpDevice;
|
|
7
|
+
existingPassphrase: string;
|
|
8
|
+
provider: WebAuthnProvider;
|
|
9
|
+
encryptionVersion?: EncryptionVersion;
|
|
10
|
+
}): Promise<Keychain>;
|
|
11
|
+
//# sourceMappingURL=attachPasskeyToWallet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachPasskeyToWallet.d.ts","sourceRoot":"","sources":["../../src/attachPasskeyToWallet.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,QAAQ,EAIR,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAE9B,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4EpB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.attachPasskeyToWallet = attachPasskeyToWallet;
|
|
4
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
5
|
+
async function attachPasskeyToWallet(params) {
|
|
6
|
+
const { bitgo, coin, walletId, device, existingPassphrase, provider, encryptionVersion } = params;
|
|
7
|
+
// Throw early if PRF extension is not supported
|
|
8
|
+
if (!device.prfSalt) {
|
|
9
|
+
throw new Error('PRF extension not supported by this device. Please use a different passkey.');
|
|
10
|
+
}
|
|
11
|
+
const baseCoin = bitgo.coin(coin);
|
|
12
|
+
// Fetch wallet and validate it is a hot wallet
|
|
13
|
+
const wallet = await baseCoin.wallets().get({ id: walletId });
|
|
14
|
+
if (wallet.type() !== 'hot') {
|
|
15
|
+
throw new Error(`Wallet ${walletId} is not a hot wallet. Only hot wallets support passkey attachment.`);
|
|
16
|
+
}
|
|
17
|
+
const walletData = wallet.toJSON();
|
|
18
|
+
const enterpriseId = walletData.enterprise;
|
|
19
|
+
if (!enterpriseId) {
|
|
20
|
+
throw new Error(`Wallet ${walletId} has no enterprise.`);
|
|
21
|
+
}
|
|
22
|
+
// Fetch the user keychain — iterates keys until it finds one with encryptedPrv
|
|
23
|
+
const keychain = await wallet.getEncryptedUserKeychain();
|
|
24
|
+
const keychainId = keychain.id;
|
|
25
|
+
// Derive enterprise-scoped salt (base64url; same encoding is used as the
|
|
26
|
+
// PRF eval input and as the server-stored prfSalt so the bytes fed to the
|
|
27
|
+
// authenticator match between attach and derive).
|
|
28
|
+
const prfSalt = (0, sdk_core_1.deriveEnterpriseSalt)(device.prfSalt, enterpriseId);
|
|
29
|
+
// Decrypt private key with existing passphrase
|
|
30
|
+
const privateKey = await bitgo.decrypt({ password: existingPassphrase, input: keychain.encryptedPrv });
|
|
31
|
+
// Decode credentialId from base64url to ArrayBuffer for allowCredentials.
|
|
32
|
+
// The WebAuthn spec requires allowCredentials to be non-empty when using evalByCredential,
|
|
33
|
+
// and each entry must correspond to a key in the evalByCredential map.
|
|
34
|
+
const credentialIdBuffer = (0, sdk_core_1.base64UrlToBuffer)(device.credentialId).buffer;
|
|
35
|
+
// PRF assertion — evalByCredential maps this device's credentialId to the
|
|
36
|
+
// base64url enterprise salt. The provider layer is responsible for decoding
|
|
37
|
+
// base64url to raw bytes before handing it to the WebAuthn PRF extension.
|
|
38
|
+
const authResult = await provider.get({
|
|
39
|
+
publicKey: {
|
|
40
|
+
allowCredentials: [{ type: 'public-key', id: credentialIdBuffer }],
|
|
41
|
+
},
|
|
42
|
+
evalByCredential: { [device.credentialId]: prfSalt },
|
|
43
|
+
});
|
|
44
|
+
if (!authResult.prfResult) {
|
|
45
|
+
throw new Error('PRF assertion did not return a result.');
|
|
46
|
+
}
|
|
47
|
+
const prfPassword = (0, sdk_core_1.derivePassword)(authResult.prfResult);
|
|
48
|
+
const encryptedPrv = await bitgo.encrypt({
|
|
49
|
+
password: prfPassword,
|
|
50
|
+
input: privateKey,
|
|
51
|
+
encryptionVersion,
|
|
52
|
+
// Bind to this enterprise via AES-GCM AAD — moving this blob to another enterprise
|
|
53
|
+
// or tampering with the stored adata field invalidates the GCM tag.
|
|
54
|
+
adata: enterpriseId,
|
|
55
|
+
});
|
|
56
|
+
const updatedKeychain = await bitgo
|
|
57
|
+
.put(bitgo.url(`/${coin}/key/${keychainId}`, 2))
|
|
58
|
+
.send({
|
|
59
|
+
webauthnInfo: {
|
|
60
|
+
prfSalt,
|
|
61
|
+
otpDeviceId: device.id,
|
|
62
|
+
encryptedPrv,
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
.result();
|
|
66
|
+
return updatedKeychain;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0YWNoUGFzc2tleVRvV2FsbGV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F0dGFjaFBhc3NrZXlUb1dhbGxldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVdBLHNEQW9GQztBQS9GRCxtREFTOEI7QUFFdkIsS0FBSyxVQUFVLHFCQUFxQixDQUFDLE1BUTNDO0lBQ0MsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsaUJBQWlCLEVBQUUsR0FBRyxNQUFNLENBQUM7SUFFbEcsZ0RBQWdEO0lBQ2hELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FBQyw2RUFBNkUsQ0FBQyxDQUFDO0lBQ2pHLENBQUM7SUFFRCxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRWxDLCtDQUErQztJQUMvQyxNQUFNLE1BQU0sR0FBRyxNQUFNLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUU5RCxJQUFJLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxLQUFLLEVBQUUsQ0FBQztRQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsUUFBUSxvRUFBb0UsQ0FBQyxDQUFDO0lBQzFHLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDbkMsTUFBTSxZQUFZLEdBQUcsVUFBVSxDQUFDLFVBQVUsQ0FBQztJQUMzQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLFFBQVEscUJBQXFCLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRUQsK0VBQStFO0lBQy9FLE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLHdCQUF3QixFQUFFLENBQUM7SUFDekQsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQztJQUUvQix5RUFBeUU7SUFDekUsMEVBQTBFO0lBQzFFLGtEQUFrRDtJQUNsRCxNQUFNLE9BQU8sR0FBRyxJQUFBLCtCQUFvQixFQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFFbkUsK0NBQStDO0lBQy9DLE1BQU0sVUFBVSxHQUFHLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLFFBQVEsRUFBRSxrQkFBa0IsRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUM7SUFFdkcsMEVBQTBFO0lBQzFFLDJGQUEyRjtJQUMzRix1RUFBdUU7SUFDdkUsTUFBTSxrQkFBa0IsR0FBRyxJQUFBLDRCQUFpQixFQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFFekUsMEVBQTBFO0lBQzFFLDRFQUE0RTtJQUM1RSwwRUFBMEU7SUFDMUUsTUFBTSxVQUFVLEdBQUcsTUFBTSxRQUFRLENBQUMsR0FBRyxDQUFDO1FBQ3BDLFNBQVMsRUFBRTtZQUNULGdCQUFnQixFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxDQUFDO1NBQzlCO1FBQ3RDLGdCQUFnQixFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLEVBQUUsT0FBTyxFQUFFO0tBQ3JELENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRCxNQUFNLFdBQVcsR0FBRyxJQUFBLHlCQUFjLEVBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3pELE1BQU0sWUFBWSxHQUFHLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQztRQUN2QyxRQUFRLEVBQUUsV0FBVztRQUNyQixLQUFLLEVBQUUsVUFBVTtRQUNqQixpQkFBaUI7UUFDakIsbUZBQW1GO1FBQ25GLG9FQUFvRTtRQUNwRSxLQUFLLEVBQUUsWUFBWTtLQUNwQixDQUFDLENBQUM7SUFFSCxNQUFNLGVBQWUsR0FBRyxNQUFNLEtBQUs7U0FDaEMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLFFBQVEsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDL0MsSUFBSSxDQUFDO1FBQ0osWUFBWSxFQUFFO1lBQ1osT0FBTztZQUNQLFdBQVcsRUFBRSxNQUFNLENBQUMsRUFBRTtZQUN0QixZQUFZO1NBQ2I7S0FDRixDQUFDO1NBQ0QsTUFBTSxFQUFFLENBQUM7SUFFWixPQUFPLGVBQTJCLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEJpdEdvQmFzZSxcbiAgRW5jcnlwdGlvblZlcnNpb24sXG4gIEtleWNoYWluLFxuICBiYXNlNjRVcmxUb0J1ZmZlcixcbiAgZGVyaXZlRW50ZXJwcmlzZVNhbHQsXG4gIGRlcml2ZVBhc3N3b3JkLFxuICB0eXBlIFdlYkF1dGhuT3RwRGV2aWNlLFxuICB0eXBlIFdlYkF1dGhuUHJvdmlkZXIsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGF0dGFjaFBhc3NrZXlUb1dhbGxldChwYXJhbXM6IHtcbiAgYml0Z286IEJpdEdvQmFzZTtcbiAgY29pbjogc3RyaW5nO1xuICB3YWxsZXRJZDogc3RyaW5nO1xuICBkZXZpY2U6IFdlYkF1dGhuT3RwRGV2aWNlO1xuICBleGlzdGluZ1Bhc3NwaHJhc2U6IHN0cmluZztcbiAgcHJvdmlkZXI6IFdlYkF1dGhuUHJvdmlkZXI7XG4gIGVuY3J5cHRpb25WZXJzaW9uPzogRW5jcnlwdGlvblZlcnNpb247XG59KTogUHJvbWlzZTxLZXljaGFpbj4ge1xuICBjb25zdCB7IGJpdGdvLCBjb2luLCB3YWxsZXRJZCwgZGV2aWNlLCBleGlzdGluZ1Bhc3NwaHJhc2UsIHByb3ZpZGVyLCBlbmNyeXB0aW9uVmVyc2lvbiB9ID0gcGFyYW1zO1xuXG4gIC8vIFRocm93IGVhcmx5IGlmIFBSRiBleHRlbnNpb24gaXMgbm90IHN1cHBvcnRlZFxuICBpZiAoIWRldmljZS5wcmZTYWx0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQUkYgZXh0ZW5zaW9uIG5vdCBzdXBwb3J0ZWQgYnkgdGhpcyBkZXZpY2UuIFBsZWFzZSB1c2UgYSBkaWZmZXJlbnQgcGFzc2tleS4nKTtcbiAgfVxuXG4gIGNvbnN0IGJhc2VDb2luID0gYml0Z28uY29pbihjb2luKTtcblxuICAvLyBGZXRjaCB3YWxsZXQgYW5kIHZhbGlkYXRlIGl0IGlzIGEgaG90IHdhbGxldFxuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBiYXNlQ29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHdhbGxldElkIH0pO1xuXG4gIGlmICh3YWxsZXQudHlwZSgpICE9PSAnaG90Jykge1xuICAgIHRocm93IG5ldyBFcnJvcihgV2FsbGV0ICR7d2FsbGV0SWR9IGlzIG5vdCBhIGhvdCB3YWxsZXQuIE9ubHkgaG90IHdhbGxldHMgc3VwcG9ydCBwYXNza2V5IGF0dGFjaG1lbnQuYCk7XG4gIH1cblxuICBjb25zdCB3YWxsZXREYXRhID0gd2FsbGV0LnRvSlNPTigpO1xuICBjb25zdCBlbnRlcnByaXNlSWQgPSB3YWxsZXREYXRhLmVudGVycHJpc2U7XG4gIGlmICghZW50ZXJwcmlzZUlkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBXYWxsZXQgJHt3YWxsZXRJZH0gaGFzIG5vIGVudGVycHJpc2UuYCk7XG4gIH1cblxuICAvLyBGZXRjaCB0aGUgdXNlciBrZXljaGFpbiDigJQgaXRlcmF0ZXMga2V5cyB1bnRpbCBpdCBmaW5kcyBvbmUgd2l0aCBlbmNyeXB0ZWRQcnZcbiAgY29uc3Qga2V5Y2hhaW4gPSBhd2FpdCB3YWxsZXQuZ2V0RW5jcnlwdGVkVXNlcktleWNoYWluKCk7XG4gIGNvbnN0IGtleWNoYWluSWQgPSBrZXljaGFpbi5pZDtcblxuICAvLyBEZXJpdmUgZW50ZXJwcmlzZS1zY29wZWQgc2FsdCAoYmFzZTY0dXJsOyBzYW1lIGVuY29kaW5nIGlzIHVzZWQgYXMgdGhlXG4gIC8vIFBSRiBldmFsIGlucHV0IGFuZCBhcyB0aGUgc2VydmVyLXN0b3JlZCBwcmZTYWx0IHNvIHRoZSBieXRlcyBmZWQgdG8gdGhlXG4gIC8vIGF1dGhlbnRpY2F0b3IgbWF0Y2ggYmV0d2VlbiBhdHRhY2ggYW5kIGRlcml2ZSkuXG4gIGNvbnN0IHByZlNhbHQgPSBkZXJpdmVFbnRlcnByaXNlU2FsdChkZXZpY2UucHJmU2FsdCwgZW50ZXJwcmlzZUlkKTtcblxuICAvLyBEZWNyeXB0IHByaXZhdGUga2V5IHdpdGggZXhpc3RpbmcgcGFzc3BocmFzZVxuICBjb25zdCBwcml2YXRlS2V5ID0gYXdhaXQgYml0Z28uZGVjcnlwdCh7IHBhc3N3b3JkOiBleGlzdGluZ1Bhc3NwaHJhc2UsIGlucHV0OiBrZXljaGFpbi5lbmNyeXB0ZWRQcnYgfSk7XG5cbiAgLy8gRGVjb2RlIGNyZWRlbnRpYWxJZCBmcm9tIGJhc2U2NHVybCB0byBBcnJheUJ1ZmZlciBmb3IgYWxsb3dDcmVkZW50aWFscy5cbiAgLy8gVGhlIFdlYkF1dGhuIHNwZWMgcmVxdWlyZXMgYWxsb3dDcmVkZW50aWFscyB0byBiZSBub24tZW1wdHkgd2hlbiB1c2luZyBldmFsQnlDcmVkZW50aWFsLFxuICAvLyBhbmQgZWFjaCBlbnRyeSBtdXN0IGNvcnJlc3BvbmQgdG8gYSBrZXkgaW4gdGhlIGV2YWxCeUNyZWRlbnRpYWwgbWFwLlxuICBjb25zdCBjcmVkZW50aWFsSWRCdWZmZXIgPSBiYXNlNjRVcmxUb0J1ZmZlcihkZXZpY2UuY3JlZGVudGlhbElkKS5idWZmZXI7XG5cbiAgLy8gUFJGIGFzc2VydGlvbiDigJQgZXZhbEJ5Q3JlZGVudGlhbCBtYXBzIHRoaXMgZGV2aWNlJ3MgY3JlZGVudGlhbElkIHRvIHRoZVxuICAvLyBiYXNlNjR1cmwgZW50ZXJwcmlzZSBzYWx0LiBUaGUgcHJvdmlkZXIgbGF5ZXIgaXMgcmVzcG9uc2libGUgZm9yIGRlY29kaW5nXG4gIC8vIGJhc2U2NHVybCB0byByYXcgYnl0ZXMgYmVmb3JlIGhhbmRpbmcgaXQgdG8gdGhlIFdlYkF1dGhuIFBSRiBleHRlbnNpb24uXG4gIGNvbnN0IGF1dGhSZXN1bHQgPSBhd2FpdCBwcm92aWRlci5nZXQoe1xuICAgIHB1YmxpY0tleToge1xuICAgICAgYWxsb3dDcmVkZW50aWFsczogW3sgdHlwZTogJ3B1YmxpYy1rZXknLCBpZDogY3JlZGVudGlhbElkQnVmZmVyIH1dLFxuICAgIH0gYXMgUHVibGljS2V5Q3JlZGVudGlhbFJlcXVlc3RPcHRpb25zLFxuICAgIGV2YWxCeUNyZWRlbnRpYWw6IHsgW2RldmljZS5jcmVkZW50aWFsSWRdOiBwcmZTYWx0IH0sXG4gIH0pO1xuXG4gIGlmICghYXV0aFJlc3VsdC5wcmZSZXN1bHQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1BSRiBhc3NlcnRpb24gZGlkIG5vdCByZXR1cm4gYSByZXN1bHQuJyk7XG4gIH1cblxuICBjb25zdCBwcmZQYXNzd29yZCA9IGRlcml2ZVBhc3N3b3JkKGF1dGhSZXN1bHQucHJmUmVzdWx0KTtcbiAgY29uc3QgZW5jcnlwdGVkUHJ2ID0gYXdhaXQgYml0Z28uZW5jcnlwdCh7XG4gICAgcGFzc3dvcmQ6IHByZlBhc3N3b3JkLFxuICAgIGlucHV0OiBwcml2YXRlS2V5LFxuICAgIGVuY3J5cHRpb25WZXJzaW9uLFxuICAgIC8vIEJpbmQgdG8gdGhpcyBlbnRlcnByaXNlIHZpYSBBRVMtR0NNIEFBRCDigJQgbW92aW5nIHRoaXMgYmxvYiB0byBhbm90aGVyIGVudGVycHJpc2VcbiAgICAvLyBvciB0YW1wZXJpbmcgd2l0aCB0aGUgc3RvcmVkIGFkYXRhIGZpZWxkIGludmFsaWRhdGVzIHRoZSBHQ00gdGFnLlxuICAgIGFkYXRhOiBlbnRlcnByaXNlSWQsXG4gIH0pO1xuXG4gIGNvbnN0IHVwZGF0ZWRLZXljaGFpbiA9IGF3YWl0IGJpdGdvXG4gICAgLnB1dChiaXRnby51cmwoYC8ke2NvaW59L2tleS8ke2tleWNoYWluSWR9YCwgMikpXG4gICAgLnNlbmQoe1xuICAgICAgd2ViYXV0aG5JbmZvOiB7XG4gICAgICAgIHByZlNhbHQsXG4gICAgICAgIG90cERldmljZUlkOiBkZXZpY2UuaWQsXG4gICAgICAgIGVuY3J5cHRlZFBydixcbiAgICAgIH0sXG4gICAgfSlcbiAgICAucmVzdWx0KCk7XG5cbiAgcmV0dXJuIHVwZGF0ZWRLZXljaGFpbiBhcyBLZXljaGFpbjtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type BitGoBase, type IWallet, type WebAuthnProvider } from '@bitgo-beta/sdk-core';
|
|
2
|
+
/**
|
|
3
|
+
* Derives a wallet passphrase from a passkey PRF output.
|
|
4
|
+
*
|
|
5
|
+
* Fetches the wallet's user keychain, triggers a WebAuthn assertion with PRF
|
|
6
|
+
* evaluation, and returns a hex-encoded passphrase suitable for use as
|
|
7
|
+
* walletPassphrase in signing calls.
|
|
8
|
+
*/
|
|
9
|
+
export declare function derivePasskeyPrfKey(params: {
|
|
10
|
+
bitgo: BitGoBase;
|
|
11
|
+
wallet: IWallet;
|
|
12
|
+
provider: WebAuthnProvider;
|
|
13
|
+
}): Promise<string>;
|
|
14
|
+
//# sourceMappingURL=derivePasskeyPrfKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derivePasskeyPrfKey.d.ts","sourceRoot":"","sources":["../../src/derivePasskeyPrfKey.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,OAAO,EAGZ,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AA+B9B;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,GAAG,OAAO,CAAC,MAAM,CAAC,CA4ClB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.derivePasskeyPrfKey = derivePasskeyPrfKey;
|
|
4
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
5
|
+
const prfHelpers_1 = require("./prfHelpers");
|
|
6
|
+
function webauthnDevicesFromKeychain(keychain) {
|
|
7
|
+
const lower = keychain.webauthnDevices;
|
|
8
|
+
if (lower !== undefined && lower.length > 0) {
|
|
9
|
+
return lower;
|
|
10
|
+
}
|
|
11
|
+
const upper = keychain.webAuthnDevices;
|
|
12
|
+
if (upper !== undefined && upper.length > 0) {
|
|
13
|
+
return upper;
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
function challengeFromAuthResponse(body) {
|
|
18
|
+
if (typeof body !== 'object' || body === null) {
|
|
19
|
+
throw new Error('Invalid assertion challenge response');
|
|
20
|
+
}
|
|
21
|
+
const rec = body;
|
|
22
|
+
if (typeof rec.challenge !== 'string') {
|
|
23
|
+
throw new Error('Invalid assertion challenge response');
|
|
24
|
+
}
|
|
25
|
+
return rec.challenge;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Derives a wallet passphrase from a passkey PRF output.
|
|
29
|
+
*
|
|
30
|
+
* Fetches the wallet's user keychain, triggers a WebAuthn assertion with PRF
|
|
31
|
+
* evaluation, and returns a hex-encoded passphrase suitable for use as
|
|
32
|
+
* walletPassphrase in signing calls.
|
|
33
|
+
*/
|
|
34
|
+
async function derivePasskeyPrfKey(params) {
|
|
35
|
+
const { bitgo, wallet, provider } = params;
|
|
36
|
+
const keychain = await wallet.getEncryptedUserKeychain();
|
|
37
|
+
const devices = webauthnDevicesFromKeychain(keychain);
|
|
38
|
+
if (!devices || devices.length === 0) {
|
|
39
|
+
throw new Error('No passkey devices available');
|
|
40
|
+
}
|
|
41
|
+
const { evalByCredential } = (0, prfHelpers_1.buildEvalByCredential)(devices);
|
|
42
|
+
if (Object.keys(evalByCredential).length === 0) {
|
|
43
|
+
throw new Error('No passkey devices available with a valid PRF salt');
|
|
44
|
+
}
|
|
45
|
+
const challenge = challengeFromAuthResponse(await bitgo.get(bitgo.url('/user/otp/webauthn/auth', 2)).result());
|
|
46
|
+
const allowCredentials = Object.keys(evalByCredential).map((credId) => {
|
|
47
|
+
const nodeBuf = Buffer.from(credId.replace(/-/g, '+').replace(/_/g, '/'), 'base64');
|
|
48
|
+
const id = nodeBuf.buffer.slice(nodeBuf.byteOffset, nodeBuf.byteOffset + nodeBuf.byteLength);
|
|
49
|
+
return {
|
|
50
|
+
type: 'public-key',
|
|
51
|
+
id,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
const publicKey = {
|
|
55
|
+
challenge: new Uint8Array(Buffer.from(challenge, 'base64')),
|
|
56
|
+
allowCredentials,
|
|
57
|
+
};
|
|
58
|
+
const result = await provider.get({
|
|
59
|
+
publicKey,
|
|
60
|
+
evalByCredential,
|
|
61
|
+
});
|
|
62
|
+
(0, prfHelpers_1.matchDeviceByCredentialId)(devices, result.credentialId);
|
|
63
|
+
if (!result.prfResult) {
|
|
64
|
+
throw new Error('PRF output was not returned by the authenticator');
|
|
65
|
+
}
|
|
66
|
+
return (0, sdk_core_1.derivePassword)(result.prfResult);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVyaXZlUGFzc2tleVByZktleS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kZXJpdmVQYXNza2V5UHJmS2V5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBNkNBLGtEQWdEQztBQTdGRCxtREFPOEI7QUFDOUIsNkNBQWdGO0FBT2hGLFNBQVMsMkJBQTJCLENBQUMsUUFBOEI7SUFDakUsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLGVBQWUsQ0FBQztJQUN2QyxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM1QyxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsZUFBZSxDQUFDO0lBQ3ZDLElBQUksS0FBSyxLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzVDLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUNELE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUM7QUFFRCxTQUFTLHlCQUF5QixDQUFDLElBQWE7SUFDOUMsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQzlDLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBQ0QsTUFBTSxHQUFHLEdBQUcsSUFBK0IsQ0FBQztJQUM1QyxJQUFJLE9BQU8sR0FBRyxDQUFDLFNBQVMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUN0QyxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDLFNBQVMsQ0FBQztBQUN2QixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0ksS0FBSyxVQUFVLG1CQUFtQixDQUFDLE1BSXpDO0lBQ0MsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBRTNDLE1BQU0sUUFBUSxHQUF5QixNQUFNLE1BQU0sQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO0lBQy9FLE1BQU0sT0FBTyxHQUFHLDJCQUEyQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRXRELElBQUksQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVELE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxHQUFHLElBQUEsa0NBQXFCLEVBQUMsT0FBTyxDQUFDLENBQUM7SUFFNUQsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQy9DLE1BQU0sSUFBSSxLQUFLLENBQUMsb0RBQW9ELENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBRUQsTUFBTSxTQUFTLEdBQUcseUJBQXlCLENBQUMsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMseUJBQXlCLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBRS9HLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1FBQ3BFLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNwRixNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzdGLE9BQU87WUFDTCxJQUFJLEVBQUUsWUFBcUI7WUFDM0IsRUFBRTtTQUNILENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztJQUVILE1BQU0sU0FBUyxHQUFzQztRQUNuRCxTQUFTLEVBQUUsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDM0QsZ0JBQWdCO0tBQ2pCLENBQUM7SUFFRixNQUFNLE1BQU0sR0FBRyxNQUFNLFFBQVEsQ0FBQyxHQUFHLENBQUM7UUFDaEMsU0FBUztRQUNULGdCQUFnQjtLQUNqQixDQUFDLENBQUM7SUFFSCxJQUFBLHNDQUF5QixFQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7SUFFeEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUVELE9BQU8sSUFBQSx5QkFBYyxFQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUMxQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgZGVyaXZlUGFzc3dvcmQsXG4gIHR5cGUgQml0R29CYXNlLFxuICB0eXBlIElXYWxsZXQsXG4gIHR5cGUgS2V5Y2hhaW5XZWJhdXRobkRldmljZSxcbiAgdHlwZSBLZXljaGFpbldpdGhFbmNyeXB0ZWRQcnYsXG4gIHR5cGUgV2ViQXV0aG5Qcm92aWRlcixcbn0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgYnVpbGRFdmFsQnlDcmVkZW50aWFsLCBtYXRjaERldmljZUJ5Q3JlZGVudGlhbElkIH0gZnJvbSAnLi9wcmZIZWxwZXJzJztcblxuLyoqIEFQSSBwYXlsb2FkcyBtYXkgdXNlIGVpdGhlciBzcGVsbGluZyBmb3IgdGhlIHdlYmF1dGhuIGRldmljZSBsaXN0LiAqL1xudHlwZSBVc2VyS2V5Y2hhaW5SZXNwb25zZSA9IEtleWNoYWluV2l0aEVuY3J5cHRlZFBydiAmIHtcbiAgd2ViQXV0aG5EZXZpY2VzPzogS2V5Y2hhaW5XZWJhdXRobkRldmljZVtdO1xufTtcblxuZnVuY3Rpb24gd2ViYXV0aG5EZXZpY2VzRnJvbUtleWNoYWluKGtleWNoYWluOiBVc2VyS2V5Y2hhaW5SZXNwb25zZSk6IEtleWNoYWluV2ViYXV0aG5EZXZpY2VbXSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGxvd2VyID0ga2V5Y2hhaW4ud2ViYXV0aG5EZXZpY2VzO1xuICBpZiAobG93ZXIgIT09IHVuZGVmaW5lZCAmJiBsb3dlci5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIGxvd2VyO1xuICB9XG4gIGNvbnN0IHVwcGVyID0ga2V5Y2hhaW4ud2ViQXV0aG5EZXZpY2VzO1xuICBpZiAodXBwZXIgIT09IHVuZGVmaW5lZCAmJiB1cHBlci5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIHVwcGVyO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGNoYWxsZW5nZUZyb21BdXRoUmVzcG9uc2UoYm9keTogdW5rbm93bik6IHN0cmluZyB7XG4gIGlmICh0eXBlb2YgYm9keSAhPT0gJ29iamVjdCcgfHwgYm9keSA9PT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBhc3NlcnRpb24gY2hhbGxlbmdlIHJlc3BvbnNlJyk7XG4gIH1cbiAgY29uc3QgcmVjID0gYm9keSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgaWYgKHR5cGVvZiByZWMuY2hhbGxlbmdlICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBhc3NlcnRpb24gY2hhbGxlbmdlIHJlc3BvbnNlJyk7XG4gIH1cbiAgcmV0dXJuIHJlYy5jaGFsbGVuZ2U7XG59XG5cbi8qKlxuICogRGVyaXZlcyBhIHdhbGxldCBwYXNzcGhyYXNlIGZyb20gYSBwYXNza2V5IFBSRiBvdXRwdXQuXG4gKlxuICogRmV0Y2hlcyB0aGUgd2FsbGV0J3MgdXNlciBrZXljaGFpbiwgdHJpZ2dlcnMgYSBXZWJBdXRobiBhc3NlcnRpb24gd2l0aCBQUkZcbiAqIGV2YWx1YXRpb24sIGFuZCByZXR1cm5zIGEgaGV4LWVuY29kZWQgcGFzc3BocmFzZSBzdWl0YWJsZSBmb3IgdXNlIGFzXG4gKiB3YWxsZXRQYXNzcGhyYXNlIGluIHNpZ25pbmcgY2FsbHMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZXJpdmVQYXNza2V5UHJmS2V5KHBhcmFtczoge1xuICBiaXRnbzogQml0R29CYXNlO1xuICB3YWxsZXQ6IElXYWxsZXQ7XG4gIHByb3ZpZGVyOiBXZWJBdXRoblByb3ZpZGVyO1xufSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHsgYml0Z28sIHdhbGxldCwgcHJvdmlkZXIgfSA9IHBhcmFtcztcblxuICBjb25zdCBrZXljaGFpbjogVXNlcktleWNoYWluUmVzcG9uc2UgPSBhd2FpdCB3YWxsZXQuZ2V0RW5jcnlwdGVkVXNlcktleWNoYWluKCk7XG4gIGNvbnN0IGRldmljZXMgPSB3ZWJhdXRobkRldmljZXNGcm9tS2V5Y2hhaW4oa2V5Y2hhaW4pO1xuXG4gIGlmICghZGV2aWNlcyB8fCBkZXZpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignTm8gcGFzc2tleSBkZXZpY2VzIGF2YWlsYWJsZScpO1xuICB9XG5cbiAgY29uc3QgeyBldmFsQnlDcmVkZW50aWFsIH0gPSBidWlsZEV2YWxCeUNyZWRlbnRpYWwoZGV2aWNlcyk7XG5cbiAgaWYgKE9iamVjdC5rZXlzKGV2YWxCeUNyZWRlbnRpYWwpLmxlbmd0aCA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignTm8gcGFzc2tleSBkZXZpY2VzIGF2YWlsYWJsZSB3aXRoIGEgdmFsaWQgUFJGIHNhbHQnKTtcbiAgfVxuXG4gIGNvbnN0IGNoYWxsZW5nZSA9IGNoYWxsZW5nZUZyb21BdXRoUmVzcG9uc2UoYXdhaXQgYml0Z28uZ2V0KGJpdGdvLnVybCgnL3VzZXIvb3RwL3dlYmF1dGhuL2F1dGgnLCAyKSkucmVzdWx0KCkpO1xuXG4gIGNvbnN0IGFsbG93Q3JlZGVudGlhbHMgPSBPYmplY3Qua2V5cyhldmFsQnlDcmVkZW50aWFsKS5tYXAoKGNyZWRJZCkgPT4ge1xuICAgIGNvbnN0IG5vZGVCdWYgPSBCdWZmZXIuZnJvbShjcmVkSWQucmVwbGFjZSgvLS9nLCAnKycpLnJlcGxhY2UoL18vZywgJy8nKSwgJ2Jhc2U2NCcpO1xuICAgIGNvbnN0IGlkID0gbm9kZUJ1Zi5idWZmZXIuc2xpY2Uobm9kZUJ1Zi5ieXRlT2Zmc2V0LCBub2RlQnVmLmJ5dGVPZmZzZXQgKyBub2RlQnVmLmJ5dGVMZW5ndGgpO1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAncHVibGljLWtleScgYXMgY29uc3QsXG4gICAgICBpZCxcbiAgICB9O1xuICB9KTtcblxuICBjb25zdCBwdWJsaWNLZXk6IFB1YmxpY0tleUNyZWRlbnRpYWxSZXF1ZXN0T3B0aW9ucyA9IHtcbiAgICBjaGFsbGVuZ2U6IG5ldyBVaW50OEFycmF5KEJ1ZmZlci5mcm9tKGNoYWxsZW5nZSwgJ2Jhc2U2NCcpKSxcbiAgICBhbGxvd0NyZWRlbnRpYWxzLFxuICB9O1xuXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHByb3ZpZGVyLmdldCh7XG4gICAgcHVibGljS2V5LFxuICAgIGV2YWxCeUNyZWRlbnRpYWwsXG4gIH0pO1xuXG4gIG1hdGNoRGV2aWNlQnlDcmVkZW50aWFsSWQoZGV2aWNlcywgcmVzdWx0LmNyZWRlbnRpYWxJZCk7XG5cbiAgaWYgKCFyZXN1bHQucHJmUmVzdWx0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQUkYgb3V0cHV0IHdhcyBub3QgcmV0dXJuZWQgYnkgdGhlIGF1dGhlbnRpY2F0b3InKTtcbiAgfVxuXG4gIHJldHVybiBkZXJpdmVQYXNzd29yZChyZXN1bHQucHJmUmVzdWx0KTtcbn1cbiJdfQ==
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
export { derivePassword } from '
|
|
2
|
-
export {
|
|
1
|
+
export { derivePassword } from '@bitgo-beta/sdk-core';
|
|
2
|
+
export { registerPasskey } from './registerPasskey';
|
|
3
|
+
export { deriveEnterpriseSalt } from '@bitgo-beta/sdk-core';
|
|
3
4
|
export { buildEvalByCredential, matchDeviceByCredentialId } from './prfHelpers';
|
|
4
|
-
export
|
|
5
|
+
export { removePasskeyFromAccount } from './removePasskeyFromAccount';
|
|
6
|
+
export type { WebAuthnOtpDevice, PasskeyAuthResult, PasskeyGetOptions, WebAuthnProvider } from '@bitgo-beta/sdk-core';
|
|
7
|
+
export { removePasskeyFromWallet } from './removePasskeyFromWallet';
|
|
8
|
+
export { attachPasskeyToWallet } from './attachPasskeyToWallet';
|
|
9
|
+
export { derivePasskeyPrfKey } from './derivePasskeyPrfKey';
|
|
5
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACtH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/src/index.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.matchDeviceByCredentialId = exports.buildEvalByCredential = exports.deriveEnterpriseSalt = exports.derivePassword = void 0;
|
|
4
|
-
var
|
|
5
|
-
Object.defineProperty(exports, "derivePassword", { enumerable: true, get: function () { return
|
|
6
|
-
var
|
|
7
|
-
Object.defineProperty(exports, "
|
|
3
|
+
exports.derivePasskeyPrfKey = exports.attachPasskeyToWallet = exports.removePasskeyFromWallet = exports.removePasskeyFromAccount = exports.matchDeviceByCredentialId = exports.buildEvalByCredential = exports.deriveEnterpriseSalt = exports.registerPasskey = exports.derivePassword = void 0;
|
|
4
|
+
var sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
5
|
+
Object.defineProperty(exports, "derivePassword", { enumerable: true, get: function () { return sdk_core_1.derivePassword; } });
|
|
6
|
+
var registerPasskey_1 = require("./registerPasskey");
|
|
7
|
+
Object.defineProperty(exports, "registerPasskey", { enumerable: true, get: function () { return registerPasskey_1.registerPasskey; } });
|
|
8
|
+
var sdk_core_2 = require("@bitgo-beta/sdk-core");
|
|
9
|
+
Object.defineProperty(exports, "deriveEnterpriseSalt", { enumerable: true, get: function () { return sdk_core_2.deriveEnterpriseSalt; } });
|
|
8
10
|
var prfHelpers_1 = require("./prfHelpers");
|
|
9
11
|
Object.defineProperty(exports, "buildEvalByCredential", { enumerable: true, get: function () { return prfHelpers_1.buildEvalByCredential; } });
|
|
10
12
|
Object.defineProperty(exports, "matchDeviceByCredentialId", { enumerable: true, get: function () { return prfHelpers_1.matchDeviceByCredentialId; } });
|
|
11
|
-
|
|
13
|
+
var removePasskeyFromAccount_1 = require("./removePasskeyFromAccount");
|
|
14
|
+
Object.defineProperty(exports, "removePasskeyFromAccount", { enumerable: true, get: function () { return removePasskeyFromAccount_1.removePasskeyFromAccount; } });
|
|
15
|
+
var removePasskeyFromWallet_1 = require("./removePasskeyFromWallet");
|
|
16
|
+
Object.defineProperty(exports, "removePasskeyFromWallet", { enumerable: true, get: function () { return removePasskeyFromWallet_1.removePasskeyFromWallet; } });
|
|
17
|
+
var attachPasskeyToWallet_1 = require("./attachPasskeyToWallet");
|
|
18
|
+
Object.defineProperty(exports, "attachPasskeyToWallet", { enumerable: true, get: function () { return attachPasskeyToWallet_1.attachPasskeyToWallet; } });
|
|
19
|
+
var derivePasskeyPrfKey_1 = require("./derivePasskeyPrfKey");
|
|
20
|
+
Object.defineProperty(exports, "derivePasskeyPrfKey", { enumerable: true, get: function () { return derivePasskeyPrfKey_1.derivePasskeyPrfKey; } });
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsaURBQXNEO0FBQTdDLDBHQUFBLGNBQWMsT0FBQTtBQUN2QixxREFBb0Q7QUFBM0Msa0hBQUEsZUFBZSxPQUFBO0FBQ3hCLGlEQUE0RDtBQUFuRCxnSEFBQSxvQkFBb0IsT0FBQTtBQUM3QiwyQ0FBZ0Y7QUFBdkUsbUhBQUEscUJBQXFCLE9BQUE7QUFBRSx1SEFBQSx5QkFBeUIsT0FBQTtBQUN6RCx1RUFBc0U7QUFBN0Qsb0lBQUEsd0JBQXdCLE9BQUE7QUFFakMscUVBQW9FO0FBQTNELGtJQUFBLHVCQUF1QixPQUFBO0FBQ2hDLGlFQUFnRTtBQUF2RCw4SEFBQSxxQkFBcUIsT0FBQTtBQUM5Qiw2REFBNEQ7QUFBbkQsMEhBQUEsbUJBQW1CLE9BQUEiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgeyBkZXJpdmVQYXNzd29yZCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmV4cG9ydCB7IHJlZ2lzdGVyUGFzc2tleSB9IGZyb20gJy4vcmVnaXN0ZXJQYXNza2V5JztcbmV4cG9ydCB7IGRlcml2ZUVudGVycHJpc2VTYWx0IH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuZXhwb3J0IHsgYnVpbGRFdmFsQnlDcmVkZW50aWFsLCBtYXRjaERldmljZUJ5Q3JlZGVudGlhbElkIH0gZnJvbSAnLi9wcmZIZWxwZXJzJztcbmV4cG9ydCB7IHJlbW92ZVBhc3NrZXlGcm9tQWNjb3VudCB9IGZyb20gJy4vcmVtb3ZlUGFzc2tleUZyb21BY2NvdW50JztcbmV4cG9ydCB0eXBlIHsgV2ViQXV0aG5PdHBEZXZpY2UsIFBhc3NrZXlBdXRoUmVzdWx0LCBQYXNza2V5R2V0T3B0aW9ucywgV2ViQXV0aG5Qcm92aWRlciB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmV4cG9ydCB7IHJlbW92ZVBhc3NrZXlGcm9tV2FsbGV0IH0gZnJvbSAnLi9yZW1vdmVQYXNza2V5RnJvbVdhbGxldCc7XG5leHBvcnQgeyBhdHRhY2hQYXNza2V5VG9XYWxsZXQgfSBmcm9tICcuL2F0dGFjaFBhc3NrZXlUb1dhbGxldCc7XG5leHBvcnQgeyBkZXJpdmVQYXNza2V5UHJmS2V5IH0gZnJvbSAnLi9kZXJpdmVQYXNza2V5UHJmS2V5JztcbiJdfQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prfHelpers.d.ts","sourceRoot":"","sources":["../../src/prfHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"prfHelpers.d.ts","sourceRoot":"","sources":["../../src/prfHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG;IAChE,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC7C,CA0BA;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,cAAc,CAQzG"}
|
package/dist/src/prfHelpers.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildEvalByCredential = buildEvalByCredential;
|
|
4
4
|
exports.matchDeviceByCredentialId = matchDeviceByCredentialId;
|
|
5
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
5
6
|
/**
|
|
6
7
|
* Builds the PRF eval map and credential-to-device lookup from a wallet
|
|
7
8
|
* keychain's webauthn devices. Devices without a prfSalt are skipped.
|
|
@@ -13,8 +14,20 @@ function buildEvalByCredential(devices) {
|
|
|
13
14
|
if (!device.prfSalt)
|
|
14
15
|
continue;
|
|
15
16
|
const { credID } = device.authenticatorInfo;
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
// Normalise credID to base64url (no padding, URL-safe chars) so it matches
|
|
18
|
+
// the key format used by attachPasskeyToWallet (device.credentialId from the
|
|
19
|
+
// browser, which is already base64url). The WebAuthn PRF extension looks up
|
|
20
|
+
// the selected credential's ID against evalByCredential keys — if the encoding
|
|
21
|
+
// differs (e.g. standard base64 with padding/+/), the lookup silently fails and
|
|
22
|
+
// PRF evaluates with no salt, producing a different output.
|
|
23
|
+
const credIdBase64url = (0, sdk_core_1.toBase64Url)(credID);
|
|
24
|
+
// Pass prfSalt through as-is (base64url). attachPasskeyToWallet writes the
|
|
25
|
+
// server-stored salt in the same encoding and feeds the same string to
|
|
26
|
+
// the PRF extension at attach time, so both paths produce the same salt
|
|
27
|
+
// bytes — provided the WebAuthn provider layer decodes base64url before
|
|
28
|
+
// handing the bytes to navigator.credentials.get.
|
|
29
|
+
evalByCredential[credIdBase64url] = device.prfSalt;
|
|
30
|
+
credIdToDevice.set(credIdBase64url, device);
|
|
18
31
|
}
|
|
19
32
|
return { evalByCredential, credIdToDevice };
|
|
20
33
|
}
|
|
@@ -23,10 +36,12 @@ function buildEvalByCredential(devices) {
|
|
|
23
36
|
* @throws if no matching device is found
|
|
24
37
|
*/
|
|
25
38
|
function matchDeviceByCredentialId(devices, credentialId) {
|
|
26
|
-
|
|
39
|
+
// Normalise both sides to base64url so padding/char differences don't break matching.
|
|
40
|
+
const needle = (0, sdk_core_1.toBase64Url)(credentialId);
|
|
41
|
+
const device = devices.find((d) => (0, sdk_core_1.toBase64Url)(d.authenticatorInfo.credID) === needle);
|
|
27
42
|
if (!device) {
|
|
28
43
|
throw new Error('Could not identify which passkey device was used');
|
|
29
44
|
}
|
|
30
45
|
return device;
|
|
31
46
|
}
|
|
32
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJmSGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcmZIZWxwZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBT0Esc0RBNkJDO0FBTUQsOERBUUM7QUFqREQsbURBQW1EO0FBRW5EOzs7R0FHRztBQUNILFNBQWdCLHFCQUFxQixDQUFDLE9BQXlCO0lBSTdELE1BQU0sZ0JBQWdCLEdBQTJCLEVBQUUsQ0FBQztJQUNwRCxNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsRUFBMEIsQ0FBQztJQUV6RCxLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTztZQUFFLFNBQVM7UUFDOUIsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUU1QywyRUFBMkU7UUFDM0UsNkVBQTZFO1FBQzdFLDRFQUE0RTtRQUM1RSwrRUFBK0U7UUFDL0UsZ0ZBQWdGO1FBQ2hGLDREQUE0RDtRQUM1RCxNQUFNLGVBQWUsR0FBRyxJQUFBLHNCQUFXLEVBQUMsTUFBTSxDQUFDLENBQUM7UUFFNUMsMkVBQTJFO1FBQzNFLHVFQUF1RTtRQUN2RSx3RUFBd0U7UUFDeEUsd0VBQXdFO1FBQ3hFLGtEQUFrRDtRQUNsRCxnQkFBZ0IsQ0FBQyxlQUFlLENBQUMsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDO1FBQ25ELGNBQWMsQ0FBQyxHQUFHLENBQUMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLENBQUM7QUFDOUMsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQWdCLHlCQUF5QixDQUFDLE9BQXlCLEVBQUUsWUFBb0I7SUFDdkYsc0ZBQXNGO0lBQ3RGLE1BQU0sTUFBTSxHQUFHLElBQUEsc0JBQVcsRUFBQyxZQUFZLENBQUMsQ0FBQztJQUN6QyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFBLHNCQUFXLEVBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxLQUFLLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZGLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsa0RBQWtELENBQUMsQ0FBQztJQUN0RSxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgV2ViYXV0aG5EZXZpY2UgfSBmcm9tICdAYml0Z28vcHVibGljLXR5cGVzJztcbmltcG9ydCB7IHRvQmFzZTY0VXJsIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuXG4vKipcbiAqIEJ1aWxkcyB0aGUgUFJGIGV2YWwgbWFwIGFuZCBjcmVkZW50aWFsLXRvLWRldmljZSBsb29rdXAgZnJvbSBhIHdhbGxldFxuICoga2V5Y2hhaW4ncyB3ZWJhdXRobiBkZXZpY2VzLiBEZXZpY2VzIHdpdGhvdXQgYSBwcmZTYWx0IGFyZSBza2lwcGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRFdmFsQnlDcmVkZW50aWFsKGRldmljZXM6IFdlYmF1dGhuRGV2aWNlW10pOiB7XG4gIGV2YWxCeUNyZWRlbnRpYWw6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGNyZWRJZFRvRGV2aWNlOiBNYXA8c3RyaW5nLCBXZWJhdXRobkRldmljZT47XG59IHtcbiAgY29uc3QgZXZhbEJ5Q3JlZGVudGlhbDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBjb25zdCBjcmVkSWRUb0RldmljZSA9IG5ldyBNYXA8c3RyaW5nLCBXZWJhdXRobkRldmljZT4oKTtcblxuICBmb3IgKGNvbnN0IGRldmljZSBvZiBkZXZpY2VzKSB7XG4gICAgaWYgKCFkZXZpY2UucHJmU2FsdCkgY29udGludWU7XG4gICAgY29uc3QgeyBjcmVkSUQgfSA9IGRldmljZS5hdXRoZW50aWNhdG9ySW5mbztcblxuICAgIC8vIE5vcm1hbGlzZSBjcmVkSUQgdG8gYmFzZTY0dXJsIChubyBwYWRkaW5nLCBVUkwtc2FmZSBjaGFycykgc28gaXQgbWF0Y2hlc1xuICAgIC8vIHRoZSBrZXkgZm9ybWF0IHVzZWQgYnkgYXR0YWNoUGFzc2tleVRvV2FsbGV0IChkZXZpY2UuY3JlZGVudGlhbElkIGZyb20gdGhlXG4gICAgLy8gYnJvd3Nlciwgd2hpY2ggaXMgYWxyZWFkeSBiYXNlNjR1cmwpLiBUaGUgV2ViQXV0aG4gUFJGIGV4dGVuc2lvbiBsb29rcyB1cFxuICAgIC8vIHRoZSBzZWxlY3RlZCBjcmVkZW50aWFsJ3MgSUQgYWdhaW5zdCBldmFsQnlDcmVkZW50aWFsIGtleXMg4oCUIGlmIHRoZSBlbmNvZGluZ1xuICAgIC8vIGRpZmZlcnMgKGUuZy4gc3RhbmRhcmQgYmFzZTY0IHdpdGggcGFkZGluZy8rLyksIHRoZSBsb29rdXAgc2lsZW50bHkgZmFpbHMgYW5kXG4gICAgLy8gUFJGIGV2YWx1YXRlcyB3aXRoIG5vIHNhbHQsIHByb2R1Y2luZyBhIGRpZmZlcmVudCBvdXRwdXQuXG4gICAgY29uc3QgY3JlZElkQmFzZTY0dXJsID0gdG9CYXNlNjRVcmwoY3JlZElEKTtcblxuICAgIC8vIFBhc3MgcHJmU2FsdCB0aHJvdWdoIGFzLWlzIChiYXNlNjR1cmwpLiBhdHRhY2hQYXNza2V5VG9XYWxsZXQgd3JpdGVzIHRoZVxuICAgIC8vIHNlcnZlci1zdG9yZWQgc2FsdCBpbiB0aGUgc2FtZSBlbmNvZGluZyBhbmQgZmVlZHMgdGhlIHNhbWUgc3RyaW5nIHRvXG4gICAgLy8gdGhlIFBSRiBleHRlbnNpb24gYXQgYXR0YWNoIHRpbWUsIHNvIGJvdGggcGF0aHMgcHJvZHVjZSB0aGUgc2FtZSBzYWx0XG4gICAgLy8gYnl0ZXMg4oCUIHByb3ZpZGVkIHRoZSBXZWJBdXRobiBwcm92aWRlciBsYXllciBkZWNvZGVzIGJhc2U2NHVybCBiZWZvcmVcbiAgICAvLyBoYW5kaW5nIHRoZSBieXRlcyB0byBuYXZpZ2F0b3IuY3JlZGVudGlhbHMuZ2V0LlxuICAgIGV2YWxCeUNyZWRlbnRpYWxbY3JlZElkQmFzZTY0dXJsXSA9IGRldmljZS5wcmZTYWx0O1xuICAgIGNyZWRJZFRvRGV2aWNlLnNldChjcmVkSWRCYXNlNjR1cmwsIGRldmljZSk7XG4gIH1cblxuICByZXR1cm4geyBldmFsQnlDcmVkZW50aWFsLCBjcmVkSWRUb0RldmljZSB9O1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIFdlYmF1dGhuRGV2aWNlIG1hdGNoaW5nIHRoZSBnaXZlbiBjcmVkZW50aWFsIElELlxuICogQHRocm93cyBpZiBubyBtYXRjaGluZyBkZXZpY2UgaXMgZm91bmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoRGV2aWNlQnlDcmVkZW50aWFsSWQoZGV2aWNlczogV2ViYXV0aG5EZXZpY2VbXSwgY3JlZGVudGlhbElkOiBzdHJpbmcpOiBXZWJhdXRobkRldmljZSB7XG4gIC8vIE5vcm1hbGlzZSBib3RoIHNpZGVzIHRvIGJhc2U2NHVybCBzbyBwYWRkaW5nL2NoYXIgZGlmZmVyZW5jZXMgZG9uJ3QgYnJlYWsgbWF0Y2hpbmcuXG4gIGNvbnN0IG5lZWRsZSA9IHRvQmFzZTY0VXJsKGNyZWRlbnRpYWxJZCk7XG4gIGNvbnN0IGRldmljZSA9IGRldmljZXMuZmluZCgoZCkgPT4gdG9CYXNlNjRVcmwoZC5hdXRoZW50aWNhdG9ySW5mby5jcmVkSUQpID09PSBuZWVkbGUpO1xuICBpZiAoIWRldmljZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGlkZW50aWZ5IHdoaWNoIHBhc3NrZXkgZGV2aWNlIHdhcyB1c2VkJyk7XG4gIH1cbiAgcmV0dXJuIGRldmljZTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BitGoBase, type WebAuthnOtpDevice, type WebAuthnProvider } from '@bitgo-beta/sdk-core';
|
|
2
|
+
export declare function registerPasskey(params: {
|
|
3
|
+
bitgo: BitGoBase;
|
|
4
|
+
provider: WebAuthnProvider;
|
|
5
|
+
label: string;
|
|
6
|
+
}): Promise<WebAuthnOtpDevice & {
|
|
7
|
+
prfSupported: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=registerPasskey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerPasskey.d.ts","sourceRoot":"","sources":["../../src/registerPasskey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAoEnH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,iBAAiB,GAAG;IAAE,YAAY,EAAE,OAAO,CAAA;CAAE,CAAC,CA8DzD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerPasskey = registerPasskey;
|
|
4
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
5
|
+
/**
|
|
6
|
+
* Recursively converts a PublicKeyCredential (or any value it contains) to a
|
|
7
|
+
* JSON-serialisable representation, encoding ArrayBuffers as base64url strings.
|
|
8
|
+
*/
|
|
9
|
+
function publicKeyCredentialToJSON(value) {
|
|
10
|
+
if (Array.isArray(value)) {
|
|
11
|
+
return value.map(publicKeyCredentialToJSON);
|
|
12
|
+
}
|
|
13
|
+
if (value instanceof ArrayBuffer) {
|
|
14
|
+
return (0, sdk_core_1.bufferToBase64Url)(value);
|
|
15
|
+
}
|
|
16
|
+
if (ArrayBuffer.isView(value)) {
|
|
17
|
+
return (0, sdk_core_1.bufferToBase64Url)(value.buffer);
|
|
18
|
+
}
|
|
19
|
+
if (value instanceof Object) {
|
|
20
|
+
const result = {};
|
|
21
|
+
// Use for...in to enumerate DOM object properties (non-enumerable own + inherited)
|
|
22
|
+
for (const key in value) {
|
|
23
|
+
result[key] = publicKeyCredentialToJSON(value[key]);
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Decodes excluded credential IDs from base64 strings to ArrayBuffers.
|
|
31
|
+
* The WebAuthn API requires BufferSource values, not base64 strings.
|
|
32
|
+
*/
|
|
33
|
+
function preformatExcludedCredentials(excludeCredentials) {
|
|
34
|
+
if (!excludeCredentials)
|
|
35
|
+
return [];
|
|
36
|
+
return excludeCredentials.map((cred) => ({
|
|
37
|
+
...cred,
|
|
38
|
+
id: Buffer.from(cred.id, 'base64'),
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
async function registerPasskey(params) {
|
|
42
|
+
const { bitgo, provider, label } = params;
|
|
43
|
+
// Step 1: Fetch server challenge (contains baseSalt)
|
|
44
|
+
const challenge = (await bitgo
|
|
45
|
+
.get(bitgo.url('/user/otp/webauthn/register', 2))
|
|
46
|
+
.result());
|
|
47
|
+
// Step 2: Pass formatted challenge to provider.create() — browser returns attestation
|
|
48
|
+
const attestation = await provider.create({
|
|
49
|
+
challenge: Buffer.from(challenge.challenge, 'base64'),
|
|
50
|
+
rp: challenge.rp,
|
|
51
|
+
user: challenge.user,
|
|
52
|
+
pubKeyCredParams: challenge.pubKeyCredParams,
|
|
53
|
+
timeout: challenge.timeout,
|
|
54
|
+
excludeCredentials: preformatExcludedCredentials(challenge.excludeCredentials),
|
|
55
|
+
authenticatorSelection: challenge.authenticatorSelection,
|
|
56
|
+
attestation: challenge.attestation,
|
|
57
|
+
extensions: challenge.extensions,
|
|
58
|
+
});
|
|
59
|
+
// Step 3: Check if PRF is supported — `prf.enabled` is set during registration
|
|
60
|
+
// (not `prf.results.first`, which is only present during authentication assertions)
|
|
61
|
+
const clientExtensionResults = attestation.getClientExtensionResults();
|
|
62
|
+
const prfEnabled = clientExtensionResults.prf;
|
|
63
|
+
const prfSupported = typeof prfEnabled === 'object' && prfEnabled !== null && prfEnabled.enabled === true;
|
|
64
|
+
// Step 4: Serialize the full credential using recursive base64url encoding
|
|
65
|
+
const otp = JSON.stringify(publicKeyCredentialToJSON(attestation));
|
|
66
|
+
const putBody = {
|
|
67
|
+
otp,
|
|
68
|
+
type: 'webauthn',
|
|
69
|
+
label,
|
|
70
|
+
};
|
|
71
|
+
if (prfSupported) {
|
|
72
|
+
putBody.extensions = ['prf'];
|
|
73
|
+
putBody.scopes = ['wallet_hot'];
|
|
74
|
+
}
|
|
75
|
+
// Step 5: PUT /api/v2/user/otp
|
|
76
|
+
const response = (await bitgo.put(bitgo.url('/user/otp', 2)).send(putBody).result());
|
|
77
|
+
// Step 6: Find the newly registered device by matching credentialId
|
|
78
|
+
const device = response.user.otpDevices.find((d) => d.credentialId === attestation.id);
|
|
79
|
+
if (!device) {
|
|
80
|
+
const available = response.user.otpDevices.map((d) => d.credentialId).join(', ');
|
|
81
|
+
throw new Error(`Registered device not found in response (credentialId: ${attestation.id}). Available: [${available}]`);
|
|
82
|
+
}
|
|
83
|
+
// Step 7: Return WebAuthnOtpDevice + prfSupported
|
|
84
|
+
return {
|
|
85
|
+
id: device.id,
|
|
86
|
+
credentialId: device.credentialId,
|
|
87
|
+
prfSalt: device.prfSalt,
|
|
88
|
+
isPasskey: device.isPasskey,
|
|
89
|
+
extensions: device.extensions,
|
|
90
|
+
prfSupported,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0ZXJQYXNza2V5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlZ2lzdGVyUGFzc2tleS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQW9FQSwwQ0FrRUM7QUF0SUQsbURBQW1IO0FBNkJuSDs7O0dBR0c7QUFDSCxTQUFTLHlCQUF5QixDQUFDLEtBQWM7SUFDL0MsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDekIsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUNELElBQUksS0FBSyxZQUFZLFdBQVcsRUFBRSxDQUFDO1FBQ2pDLE9BQU8sSUFBQSw0QkFBaUIsRUFBQyxLQUFLLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBQ0QsSUFBSSxXQUFXLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDOUIsT0FBTyxJQUFBLDRCQUFpQixFQUFDLEtBQUssQ0FBQyxNQUFxQixDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUNELElBQUksS0FBSyxZQUFZLE1BQU0sRUFBRSxDQUFDO1FBQzVCLE1BQU0sTUFBTSxHQUE0QixFQUFFLENBQUM7UUFDM0MsbUZBQW1GO1FBQ25GLEtBQUssTUFBTSxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7WUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLHlCQUF5QixDQUFFLEtBQWlDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNuRixDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsNEJBQTRCLENBQ25DLGtCQUErRDtJQUUvRCxJQUFJLENBQUMsa0JBQWtCO1FBQUUsT0FBTyxFQUFFLENBQUM7SUFDbkMsT0FBTyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdkMsR0FBRyxJQUFJO1FBQ1AsRUFBRSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQXVCLEVBQUUsUUFBUSxDQUEyQjtLQUNsRixDQUFDLENBQUMsQ0FBQztBQUNOLENBQUM7QUFFTSxLQUFLLFVBQVUsZUFBZSxDQUFDLE1BSXJDO0lBQ0MsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBRTFDLHFEQUFxRDtJQUNyRCxNQUFNLFNBQVMsR0FBRyxDQUFDLE1BQU0sS0FBSztTQUMzQixHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUNoRCxNQUFNLEVBQUUsQ0FBOEIsQ0FBQztJQUUxQyxzRkFBc0Y7SUFDdEYsTUFBTSxXQUFXLEdBQUcsTUFBTSxRQUFRLENBQUMsTUFBTSxDQUFDO1FBQ3hDLFNBQVMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDO1FBQ3JELEVBQUUsRUFBRSxTQUFTLENBQUMsRUFBRTtRQUNoQixJQUFJLEVBQUUsU0FBUyxDQUFDLElBQUk7UUFDcEIsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLGdCQUFnQjtRQUM1QyxPQUFPLEVBQUUsU0FBUyxDQUFDLE9BQU87UUFDMUIsa0JBQWtCLEVBQUUsNEJBQTRCLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDO1FBQzlFLHNCQUFzQixFQUFFLFNBQVMsQ0FBQyxzQkFBc0I7UUFDeEQsV0FBVyxFQUFFLFNBQVMsQ0FBQyxXQUFXO1FBQ2xDLFVBQVUsRUFBRSxTQUFTLENBQUMsVUFBVTtLQUNqQyxDQUFDLENBQUM7SUFFSCwrRUFBK0U7SUFDL0Usb0ZBQW9GO0lBQ3BGLE1BQU0sc0JBQXNCLEdBQTBDLFdBQVcsQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO0lBQzlHLE1BQU0sVUFBVSxHQUFHLHNCQUFzQixDQUFDLEdBQUcsQ0FBQztJQUM5QyxNQUFNLFlBQVksR0FBRyxPQUFPLFVBQVUsS0FBSyxRQUFRLElBQUksVUFBVSxLQUFLLElBQUksSUFBSSxVQUFVLENBQUMsT0FBTyxLQUFLLElBQUksQ0FBQztJQUUxRywyRUFBMkU7SUFDM0UsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyx5QkFBeUIsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO0lBRW5FLE1BQU0sT0FBTyxHQUE0QjtRQUN2QyxHQUFHO1FBQ0gsSUFBSSxFQUFFLFVBQVU7UUFDaEIsS0FBSztLQUNOLENBQUM7SUFFRixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ2pCLE9BQU8sQ0FBQyxVQUFVLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QixPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVELCtCQUErQjtJQUMvQixNQUFNLFFBQVEsR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBd0IsQ0FBQztJQUU1RyxvRUFBb0U7SUFDcEUsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsWUFBWSxLQUFLLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN2RixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDWixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakYsTUFBTSxJQUFJLEtBQUssQ0FDYiwwREFBMEQsV0FBVyxDQUFDLEVBQUUsa0JBQWtCLFNBQVMsR0FBRyxDQUN2RyxDQUFDO0lBQ0osQ0FBQztJQUVELGtEQUFrRDtJQUNsRCxPQUFPO1FBQ0wsRUFBRSxFQUFFLE1BQU0sQ0FBQyxFQUFFO1FBQ2IsWUFBWSxFQUFFLE1BQU0sQ0FBQyxZQUFZO1FBQ2pDLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztRQUN2QixTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7UUFDM0IsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO1FBQzdCLFlBQVk7S0FDYixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJpdEdvQmFzZSwgYnVmZmVyVG9CYXNlNjRVcmwsIHR5cGUgV2ViQXV0aG5PdHBEZXZpY2UsIHR5cGUgV2ViQXV0aG5Qcm92aWRlciB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcblxuaW50ZXJmYWNlIFJlZ2lzdGVyQ2hhbGxlbmdlUmVzcG9uc2Uge1xuICBjaGFsbGVuZ2U6IHN0cmluZztcbiAgYmFzZVNhbHQ6IHN0cmluZztcbiAgcnA6IFB1YmxpY0tleUNyZWRlbnRpYWxScEVudGl0eTtcbiAgdXNlcjogUHVibGljS2V5Q3JlZGVudGlhbFVzZXJFbnRpdHk7XG4gIHB1YktleUNyZWRQYXJhbXM6IFB1YmxpY0tleUNyZWRlbnRpYWxQYXJhbWV0ZXJzW107XG4gIHRpbWVvdXQ/OiBudW1iZXI7XG4gIGV4Y2x1ZGVDcmVkZW50aWFscz86IFB1YmxpY0tleUNyZWRlbnRpYWxEZXNjcmlwdG9yW107XG4gIGF1dGhlbnRpY2F0b3JTZWxlY3Rpb24/OiBBdXRoZW50aWNhdG9yU2VsZWN0aW9uQ3JpdGVyaWE7XG4gIGF0dGVzdGF0aW9uPzogQXR0ZXN0YXRpb25Db252ZXlhbmNlUHJlZmVyZW5jZTtcbiAgZXh0ZW5zaW9ucz86IEF1dGhlbnRpY2F0aW9uRXh0ZW5zaW9uc0NsaWVudElucHV0cztcbn1cblxuaW50ZXJmYWNlIE90cERldmljZSB7XG4gIGlkOiBzdHJpbmc7XG4gIGNyZWRlbnRpYWxJZDogc3RyaW5nO1xuICBwcmZTYWx0Pzogc3RyaW5nO1xuICBpc1Bhc3NrZXk/OiBib29sZWFuO1xuICBleHRlbnNpb25zPzogUmVjb3JkPHN0cmluZywgYm9vbGVhbj47XG59XG5cbmludGVyZmFjZSBSZWdpc3Rlck90cFJlc3BvbnNlIHtcbiAgdXNlcjoge1xuICAgIG90cERldmljZXM6IE90cERldmljZVtdO1xuICB9O1xufVxuXG4vKipcbiAqIFJlY3Vyc2l2ZWx5IGNvbnZlcnRzIGEgUHVibGljS2V5Q3JlZGVudGlhbCAob3IgYW55IHZhbHVlIGl0IGNvbnRhaW5zKSB0byBhXG4gKiBKU09OLXNlcmlhbGlzYWJsZSByZXByZXNlbnRhdGlvbiwgZW5jb2RpbmcgQXJyYXlCdWZmZXJzIGFzIGJhc2U2NHVybCBzdHJpbmdzLlxuICovXG5mdW5jdGlvbiBwdWJsaWNLZXlDcmVkZW50aWFsVG9KU09OKHZhbHVlOiB1bmtub3duKTogdW5rbm93biB7XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZS5tYXAocHVibGljS2V5Q3JlZGVudGlhbFRvSlNPTik7XG4gIH1cbiAgaWYgKHZhbHVlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICByZXR1cm4gYnVmZmVyVG9CYXNlNjRVcmwodmFsdWUpO1xuICB9XG4gIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcodmFsdWUpKSB7XG4gICAgcmV0dXJuIGJ1ZmZlclRvQmFzZTY0VXJsKHZhbHVlLmJ1ZmZlciBhcyBBcnJheUJ1ZmZlcik7XG4gIH1cbiAgaWYgKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSB7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuICAgIC8vIFVzZSBmb3IuLi5pbiB0byBlbnVtZXJhdGUgRE9NIG9iamVjdCBwcm9wZXJ0aWVzIChub24tZW51bWVyYWJsZSBvd24gKyBpbmhlcml0ZWQpXG4gICAgZm9yIChjb25zdCBrZXkgaW4gdmFsdWUpIHtcbiAgICAgIHJlc3VsdFtrZXldID0gcHVibGljS2V5Q3JlZGVudGlhbFRvSlNPTigodmFsdWUgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW2tleV0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuLyoqXG4gKiBEZWNvZGVzIGV4Y2x1ZGVkIGNyZWRlbnRpYWwgSURzIGZyb20gYmFzZTY0IHN0cmluZ3MgdG8gQXJyYXlCdWZmZXJzLlxuICogVGhlIFdlYkF1dGhuIEFQSSByZXF1aXJlcyBCdWZmZXJTb3VyY2UgdmFsdWVzLCBub3QgYmFzZTY0IHN0cmluZ3MuXG4gKi9cbmZ1bmN0aW9uIHByZWZvcm1hdEV4Y2x1ZGVkQ3JlZGVudGlhbHMoXG4gIGV4Y2x1ZGVDcmVkZW50aWFsczogUHVibGljS2V5Q3JlZGVudGlhbERlc2NyaXB0b3JbXSB8IHVuZGVmaW5lZFxuKTogUHVibGljS2V5Q3JlZGVudGlhbERlc2NyaXB0b3JbXSB7XG4gIGlmICghZXhjbHVkZUNyZWRlbnRpYWxzKSByZXR1cm4gW107XG4gIHJldHVybiBleGNsdWRlQ3JlZGVudGlhbHMubWFwKChjcmVkKSA9PiAoe1xuICAgIC4uLmNyZWQsXG4gICAgaWQ6IEJ1ZmZlci5mcm9tKGNyZWQuaWQgYXMgdW5rbm93biBhcyBzdHJpbmcsICdiYXNlNjQnKSBhcyB1bmtub3duIGFzIEFycmF5QnVmZmVyLFxuICB9KSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWdpc3RlclBhc3NrZXkocGFyYW1zOiB7XG4gIGJpdGdvOiBCaXRHb0Jhc2U7XG4gIHByb3ZpZGVyOiBXZWJBdXRoblByb3ZpZGVyO1xuICBsYWJlbDogc3RyaW5nO1xufSk6IFByb21pc2U8V2ViQXV0aG5PdHBEZXZpY2UgJiB7IHByZlN1cHBvcnRlZDogYm9vbGVhbiB9PiB7XG4gIGNvbnN0IHsgYml0Z28sIHByb3ZpZGVyLCBsYWJlbCB9ID0gcGFyYW1zO1xuXG4gIC8vIFN0ZXAgMTogRmV0Y2ggc2VydmVyIGNoYWxsZW5nZSAoY29udGFpbnMgYmFzZVNhbHQpXG4gIGNvbnN0IGNoYWxsZW5nZSA9IChhd2FpdCBiaXRnb1xuICAgIC5nZXQoYml0Z28udXJsKCcvdXNlci9vdHAvd2ViYXV0aG4vcmVnaXN0ZXInLCAyKSlcbiAgICAucmVzdWx0KCkpIGFzIFJlZ2lzdGVyQ2hhbGxlbmdlUmVzcG9uc2U7XG5cbiAgLy8gU3RlcCAyOiBQYXNzIGZvcm1hdHRlZCBjaGFsbGVuZ2UgdG8gcHJvdmlkZXIuY3JlYXRlKCkg4oCUIGJyb3dzZXIgcmV0dXJucyBhdHRlc3RhdGlvblxuICBjb25zdCBhdHRlc3RhdGlvbiA9IGF3YWl0IHByb3ZpZGVyLmNyZWF0ZSh7XG4gICAgY2hhbGxlbmdlOiBCdWZmZXIuZnJvbShjaGFsbGVuZ2UuY2hhbGxlbmdlLCAnYmFzZTY0JyksXG4gICAgcnA6IGNoYWxsZW5nZS5ycCxcbiAgICB1c2VyOiBjaGFsbGVuZ2UudXNlcixcbiAgICBwdWJLZXlDcmVkUGFyYW1zOiBjaGFsbGVuZ2UucHViS2V5Q3JlZFBhcmFtcyxcbiAgICB0aW1lb3V0OiBjaGFsbGVuZ2UudGltZW91dCxcbiAgICBleGNsdWRlQ3JlZGVudGlhbHM6IHByZWZvcm1hdEV4Y2x1ZGVkQ3JlZGVudGlhbHMoY2hhbGxlbmdlLmV4Y2x1ZGVDcmVkZW50aWFscyksXG4gICAgYXV0aGVudGljYXRvclNlbGVjdGlvbjogY2hhbGxlbmdlLmF1dGhlbnRpY2F0b3JTZWxlY3Rpb24sXG4gICAgYXR0ZXN0YXRpb246IGNoYWxsZW5nZS5hdHRlc3RhdGlvbixcbiAgICBleHRlbnNpb25zOiBjaGFsbGVuZ2UuZXh0ZW5zaW9ucyxcbiAgfSk7XG5cbiAgLy8gU3RlcCAzOiBDaGVjayBpZiBQUkYgaXMgc3VwcG9ydGVkIOKAlCBgcHJmLmVuYWJsZWRgIGlzIHNldCBkdXJpbmcgcmVnaXN0cmF0aW9uXG4gIC8vIChub3QgYHByZi5yZXN1bHRzLmZpcnN0YCwgd2hpY2ggaXMgb25seSBwcmVzZW50IGR1cmluZyBhdXRoZW50aWNhdGlvbiBhc3NlcnRpb25zKVxuICBjb25zdCBjbGllbnRFeHRlbnNpb25SZXN1bHRzOiBBdXRoZW50aWNhdGlvbkV4dGVuc2lvbnNDbGllbnRPdXRwdXRzID0gYXR0ZXN0YXRpb24uZ2V0Q2xpZW50RXh0ZW5zaW9uUmVzdWx0cygpO1xuICBjb25zdCBwcmZFbmFibGVkID0gY2xpZW50RXh0ZW5zaW9uUmVzdWx0cy5wcmY7XG4gIGNvbnN0IHByZlN1cHBvcnRlZCA9IHR5cGVvZiBwcmZFbmFibGVkID09PSAnb2JqZWN0JyAmJiBwcmZFbmFibGVkICE9PSBudWxsICYmIHByZkVuYWJsZWQuZW5hYmxlZCA9PT0gdHJ1ZTtcblxuICAvLyBTdGVwIDQ6IFNlcmlhbGl6ZSB0aGUgZnVsbCBjcmVkZW50aWFsIHVzaW5nIHJlY3Vyc2l2ZSBiYXNlNjR1cmwgZW5jb2RpbmdcbiAgY29uc3Qgb3RwID0gSlNPTi5zdHJpbmdpZnkocHVibGljS2V5Q3JlZGVudGlhbFRvSlNPTihhdHRlc3RhdGlvbikpO1xuXG4gIGNvbnN0IHB1dEJvZHk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuICAgIG90cCxcbiAgICB0eXBlOiAnd2ViYXV0aG4nLFxuICAgIGxhYmVsLFxuICB9O1xuXG4gIGlmIChwcmZTdXBwb3J0ZWQpIHtcbiAgICBwdXRCb2R5LmV4dGVuc2lvbnMgPSBbJ3ByZiddO1xuICAgIHB1dEJvZHkuc2NvcGVzID0gWyd3YWxsZXRfaG90J107XG4gIH1cblxuICAvLyBTdGVwIDU6IFBVVCAvYXBpL3YyL3VzZXIvb3RwXG4gIGNvbnN0IHJlc3BvbnNlID0gKGF3YWl0IGJpdGdvLnB1dChiaXRnby51cmwoJy91c2VyL290cCcsIDIpKS5zZW5kKHB1dEJvZHkpLnJlc3VsdCgpKSBhcyBSZWdpc3Rlck90cFJlc3BvbnNlO1xuXG4gIC8vIFN0ZXAgNjogRmluZCB0aGUgbmV3bHkgcmVnaXN0ZXJlZCBkZXZpY2UgYnkgbWF0Y2hpbmcgY3JlZGVudGlhbElkXG4gIGNvbnN0IGRldmljZSA9IHJlc3BvbnNlLnVzZXIub3RwRGV2aWNlcy5maW5kKChkKSA9PiBkLmNyZWRlbnRpYWxJZCA9PT0gYXR0ZXN0YXRpb24uaWQpO1xuICBpZiAoIWRldmljZSkge1xuICAgIGNvbnN0IGF2YWlsYWJsZSA9IHJlc3BvbnNlLnVzZXIub3RwRGV2aWNlcy5tYXAoKGQpID0+IGQuY3JlZGVudGlhbElkKS5qb2luKCcsICcpO1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBSZWdpc3RlcmVkIGRldmljZSBub3QgZm91bmQgaW4gcmVzcG9uc2UgKGNyZWRlbnRpYWxJZDogJHthdHRlc3RhdGlvbi5pZH0pLiBBdmFpbGFibGU6IFske2F2YWlsYWJsZX1dYFxuICAgICk7XG4gIH1cblxuICAvLyBTdGVwIDc6IFJldHVybiBXZWJBdXRobk90cERldmljZSArIHByZlN1cHBvcnRlZFxuICByZXR1cm4ge1xuICAgIGlkOiBkZXZpY2UuaWQsXG4gICAgY3JlZGVudGlhbElkOiBkZXZpY2UuY3JlZGVudGlhbElkLFxuICAgIHByZlNhbHQ6IGRldmljZS5wcmZTYWx0LFxuICAgIGlzUGFzc2tleTogZGV2aWNlLmlzUGFzc2tleSxcbiAgICBleHRlbnNpb25zOiBkZXZpY2UuZXh0ZW5zaW9ucyxcbiAgICBwcmZTdXBwb3J0ZWQsXG4gIH07XG59XG4iXX0=
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BitGoBase } from '@bitgo-beta/sdk-core';
|
|
2
|
+
import type { WebAuthnOtpDevice } from '@bitgo/public-types';
|
|
3
|
+
/**
|
|
4
|
+
* Permanently removes a passkey credential from the user's account.
|
|
5
|
+
* Call removePasskeyFromWallet() for all affected wallets before calling this.
|
|
6
|
+
*/
|
|
7
|
+
export declare function removePasskeyFromAccount(params: {
|
|
8
|
+
bitgo: BitGoBase;
|
|
9
|
+
device: WebAuthnOtpDevice;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=removePasskeyFromAccount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"removePasskeyFromAccount.d.ts","sourceRoot":"","sources":["../../src/removePasskeyFromAccount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAMrH"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removePasskeyFromAccount = removePasskeyFromAccount;
|
|
4
|
+
/**
|
|
5
|
+
* Permanently removes a passkey credential from the user's account.
|
|
6
|
+
* Call removePasskeyFromWallet() for all affected wallets before calling this.
|
|
7
|
+
*/
|
|
8
|
+
async function removePasskeyFromAccount(params) {
|
|
9
|
+
const { bitgo, device } = params;
|
|
10
|
+
if (!device.id) {
|
|
11
|
+
throw new Error('device.id is required to remove a passkey from the account');
|
|
12
|
+
}
|
|
13
|
+
await bitgo.del(bitgo.url(`/user/otp/${device.id}`)).result();
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3ZlUGFzc2tleUZyb21BY2NvdW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlbW92ZVBhc3NrZXlGcm9tQWNjb3VudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQU9BLDREQU1DO0FBVkQ7OztHQUdHO0FBQ0ksS0FBSyxVQUFVLHdCQUF3QixDQUFDLE1BQXVEO0lBQ3BHLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBQ2pDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDZixNQUFNLElBQUksS0FBSyxDQUFDLDREQUE0RCxDQUFDLENBQUM7SUFDaEYsQ0FBQztJQUNELE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLGFBQWEsTUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztBQUNoRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQml0R29CYXNlIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBXZWJBdXRobk90cERldmljZSB9IGZyb20gJ0BiaXRnby9wdWJsaWMtdHlwZXMnO1xuXG4vKipcbiAqIFBlcm1hbmVudGx5IHJlbW92ZXMgYSBwYXNza2V5IGNyZWRlbnRpYWwgZnJvbSB0aGUgdXNlcidzIGFjY291bnQuXG4gKiBDYWxsIHJlbW92ZVBhc3NrZXlGcm9tV2FsbGV0KCkgZm9yIGFsbCBhZmZlY3RlZCB3YWxsZXRzIGJlZm9yZSBjYWxsaW5nIHRoaXMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW1vdmVQYXNza2V5RnJvbUFjY291bnQocGFyYW1zOiB7IGJpdGdvOiBCaXRHb0Jhc2U7IGRldmljZTogV2ViQXV0aG5PdHBEZXZpY2UgfSk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IGJpdGdvLCBkZXZpY2UgfSA9IHBhcmFtcztcbiAgaWYgKCFkZXZpY2UuaWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2RldmljZS5pZCBpcyByZXF1aXJlZCB0byByZW1vdmUgYSBwYXNza2V5IGZyb20gdGhlIGFjY291bnQnKTtcbiAgfVxuICBhd2FpdCBiaXRnby5kZWwoYml0Z28udXJsKGAvdXNlci9vdHAvJHtkZXZpY2UuaWR9YCkpLnJlc3VsdCgpO1xufVxuIl19
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BitGoBase, type WebAuthnOtpDevice } from '@bitgo-beta/sdk-core';
|
|
2
|
+
export declare function removePasskeyFromWallet(params: {
|
|
3
|
+
bitgo: BitGoBase;
|
|
4
|
+
coin: string;
|
|
5
|
+
walletId: string;
|
|
6
|
+
device: WebAuthnOtpDevice;
|
|
7
|
+
walletPassphrase: string;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=removePasskeyFromWallet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"removePasskeyFromWallet.d.ts","sourceRoot":"","sources":["../../src/removePasskeyFromWallet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA6B,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEpG,wBAAsB,uBAAuB,CAAC,MAAM,EAAE;IACpD,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBhB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removePasskeyFromWallet = removePasskeyFromWallet;
|
|
4
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
5
|
+
async function removePasskeyFromWallet(params) {
|
|
6
|
+
const { bitgo, coin: coinName, walletId, device, walletPassphrase } = params;
|
|
7
|
+
if (!device.id) {
|
|
8
|
+
throw new Error('device.id is required to remove a passkey from the wallet');
|
|
9
|
+
}
|
|
10
|
+
const baseCoin = bitgo.coin(coinName);
|
|
11
|
+
const wallet = await baseCoin.wallets().get({ id: walletId });
|
|
12
|
+
const keychainId = wallet.keyIds()[0];
|
|
13
|
+
const keychain = await baseCoin.keychains().get({ id: keychainId });
|
|
14
|
+
// Verify passphrase before any mutation
|
|
15
|
+
const decrypted = await (0, sdk_core_1.decryptKeychainPrivateKey)(bitgo, keychain, walletPassphrase);
|
|
16
|
+
if (!decrypted) {
|
|
17
|
+
throw new Error('Incorrect wallet passphrase. Passkey removal aborted to prevent lockout.');
|
|
18
|
+
}
|
|
19
|
+
// No sdk-core abstraction for this endpoint; raw DELETE is required
|
|
20
|
+
await bitgo.del(bitgo.url(`/key/${keychainId}/webauthndevice/${device.id}`, 2)).result();
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3ZlUGFzc2tleUZyb21XYWxsZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVtb3ZlUGFzc2tleUZyb21XYWxsZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSwwREEwQkM7QUE1QkQsbURBQW9HO0FBRTdGLEtBQUssVUFBVSx1QkFBdUIsQ0FBQyxNQU03QztJQUNDLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixFQUFFLEdBQUcsTUFBTSxDQUFDO0lBRTdFLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDZixNQUFNLElBQUksS0FBSyxDQUFDLDJEQUEyRCxDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUVELE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDOUQsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLE1BQU0sUUFBUSxHQUFHLE1BQU0sUUFBUSxDQUFDLFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBRXBFLHdDQUF3QztJQUN4QyxNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUEsb0NBQXlCLEVBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3JGLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsMEVBQTBFLENBQUMsQ0FBQztJQUM5RixDQUFDO0lBRUQsb0VBQW9FO0lBQ3BFLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsVUFBVSxtQkFBbUIsTUFBTSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUM7QUFDM0YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJpdEdvQmFzZSwgZGVjcnlwdEtleWNoYWluUHJpdmF0ZUtleSwgdHlwZSBXZWJBdXRobk90cERldmljZSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbW92ZVBhc3NrZXlGcm9tV2FsbGV0KHBhcmFtczoge1xuICBiaXRnbzogQml0R29CYXNlO1xuICBjb2luOiBzdHJpbmc7XG4gIHdhbGxldElkOiBzdHJpbmc7XG4gIGRldmljZTogV2ViQXV0aG5PdHBEZXZpY2U7XG4gIHdhbGxldFBhc3NwaHJhc2U6IHN0cmluZztcbn0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgeyBiaXRnbywgY29pbjogY29pbk5hbWUsIHdhbGxldElkLCBkZXZpY2UsIHdhbGxldFBhc3NwaHJhc2UgfSA9IHBhcmFtcztcblxuICBpZiAoIWRldmljZS5pZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignZGV2aWNlLmlkIGlzIHJlcXVpcmVkIHRvIHJlbW92ZSBhIHBhc3NrZXkgZnJvbSB0aGUgd2FsbGV0Jyk7XG4gIH1cblxuICBjb25zdCBiYXNlQ29pbiA9IGJpdGdvLmNvaW4oY29pbk5hbWUpO1xuICBjb25zdCB3YWxsZXQgPSBhd2FpdCBiYXNlQ29pbi53YWxsZXRzKCkuZ2V0KHsgaWQ6IHdhbGxldElkIH0pO1xuICBjb25zdCBrZXljaGFpbklkID0gd2FsbGV0LmtleUlkcygpWzBdO1xuICBjb25zdCBrZXljaGFpbiA9IGF3YWl0IGJhc2VDb2luLmtleWNoYWlucygpLmdldCh7IGlkOiBrZXljaGFpbklkIH0pO1xuXG4gIC8vIFZlcmlmeSBwYXNzcGhyYXNlIGJlZm9yZSBhbnkgbXV0YXRpb25cbiAgY29uc3QgZGVjcnlwdGVkID0gYXdhaXQgZGVjcnlwdEtleWNoYWluUHJpdmF0ZUtleShiaXRnbywga2V5Y2hhaW4sIHdhbGxldFBhc3NwaHJhc2UpO1xuICBpZiAoIWRlY3J5cHRlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5jb3JyZWN0IHdhbGxldCBwYXNzcGhyYXNlLiBQYXNza2V5IHJlbW92YWwgYWJvcnRlZCB0byBwcmV2ZW50IGxvY2tvdXQuJyk7XG4gIH1cblxuICAvLyBObyBzZGstY29yZSBhYnN0cmFjdGlvbiBmb3IgdGhpcyBlbmRwb2ludDsgcmF3IERFTEVURSBpcyByZXF1aXJlZFxuICBhd2FpdCBiaXRnby5kZWwoYml0Z28udXJsKGAva2V5LyR7a2V5Y2hhaW5JZH0vd2ViYXV0aG5kZXZpY2UvJHtkZXZpY2UuaWR9YCwgMikpLnJlc3VsdCgpO1xufVxuIl19
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const ENTERPRISE_ID = "enterprise-abc";
|
|
2
|
+
export declare const WALLET_ID = "wallet-hot-123";
|
|
3
|
+
export declare const KEYCHAIN_ID = "key-user-001";
|
|
4
|
+
export declare const COIN = "tbtc";
|
|
5
|
+
export declare const EXISTING_PASSPHRASE = "my-existing-passphrase";
|
|
6
|
+
export declare const PRF_OUTPUT: ArrayBuffer;
|
|
7
|
+
export declare const CREDENTIAL_ID = "Y3JlZC1pZC00NTY";
|
|
8
|
+
export declare const DEVICE_MONGO_ID = "device-mongo-id-1";
|
|
9
|
+
export declare const BASE_SALT = "ZqJ64M2dL65zn2-Jxd58SMN2ILc9QjbCFxUTGHd_LC8";
|
|
10
|
+
export declare const REGISTER_CHALLENGE: string;
|
|
11
|
+
export declare const ASSERTION_CHALLENGE: string;
|
|
12
|
+
//# sourceMappingURL=fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../../../test/integration/helpers/fixtures.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,mBAAmB,CAAC;AAC9C,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAC1C,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAC1C,eAAO,MAAM,IAAI,SAAS,CAAC;AAC3B,eAAO,MAAM,mBAAmB,2BAA2B,CAAC;AAC5D,eAAO,MAAM,UAAU,aAA0E,CAAC;AAClG,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAC/C,eAAO,MAAM,eAAe,sBAAsB,CAAC;AACnD,eAAO,MAAM,SAAS,gDAAgD,CAAC;AACvE,eAAO,MAAM,kBAAkB,QAAqD,CAAC;AACrF,eAAO,MAAM,mBAAmB,QAAwD,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ASSERTION_CHALLENGE = exports.REGISTER_CHALLENGE = exports.BASE_SALT = exports.DEVICE_MONGO_ID = exports.CREDENTIAL_ID = exports.PRF_OUTPUT = exports.EXISTING_PASSPHRASE = exports.COIN = exports.KEYCHAIN_ID = exports.WALLET_ID = exports.ENTERPRISE_ID = void 0;
|
|
4
|
+
exports.ENTERPRISE_ID = 'enterprise-abc';
|
|
5
|
+
exports.WALLET_ID = 'wallet-hot-123';
|
|
6
|
+
exports.KEYCHAIN_ID = 'key-user-001';
|
|
7
|
+
exports.COIN = 'tbtc';
|
|
8
|
+
exports.EXISTING_PASSPHRASE = 'my-existing-passphrase';
|
|
9
|
+
exports.PRF_OUTPUT = new Uint8Array([0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x01, 0x02]).buffer;
|
|
10
|
+
exports.CREDENTIAL_ID = 'Y3JlZC1pZC00NTY';
|
|
11
|
+
exports.DEVICE_MONGO_ID = 'device-mongo-id-1';
|
|
12
|
+
exports.BASE_SALT = 'ZqJ64M2dL65zn2-Jxd58SMN2ILc9QjbCFxUTGHd_LC8';
|
|
13
|
+
exports.REGISTER_CHALLENGE = Buffer.from('random-challenge').toString('base64');
|
|
14
|
+
exports.ASSERTION_CHALLENGE = Buffer.from('assertion-challenge').toString('base64');
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L2ludGVncmF0aW9uL2hlbHBlcnMvZml4dHVyZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQWEsUUFBQSxhQUFhLEdBQUcsZ0JBQWdCLENBQUM7QUFDakMsUUFBQSxTQUFTLEdBQUcsZ0JBQWdCLENBQUM7QUFDN0IsUUFBQSxXQUFXLEdBQUcsY0FBYyxDQUFDO0FBQzdCLFFBQUEsSUFBSSxHQUFHLE1BQU0sQ0FBQztBQUNkLFFBQUEsbUJBQW1CLEdBQUcsd0JBQXdCLENBQUM7QUFDL0MsUUFBQSxVQUFVLEdBQUcsSUFBSSxVQUFVLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7QUFDckYsUUFBQSxhQUFhLEdBQUcsaUJBQWlCLENBQUM7QUFDbEMsUUFBQSxlQUFlLEdBQUcsbUJBQW1CLENBQUM7QUFDdEMsUUFBQSxTQUFTLEdBQUcsNkNBQTZDLENBQUM7QUFDMUQsUUFBQSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQ3hFLFFBQUEsbUJBQW1CLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBFTlRFUlBSSVNFX0lEID0gJ2VudGVycHJpc2UtYWJjJztcbmV4cG9ydCBjb25zdCBXQUxMRVRfSUQgPSAnd2FsbGV0LWhvdC0xMjMnO1xuZXhwb3J0IGNvbnN0IEtFWUNIQUlOX0lEID0gJ2tleS11c2VyLTAwMSc7XG5leHBvcnQgY29uc3QgQ09JTiA9ICd0YnRjJztcbmV4cG9ydCBjb25zdCBFWElTVElOR19QQVNTUEhSQVNFID0gJ215LWV4aXN0aW5nLXBhc3NwaHJhc2UnO1xuZXhwb3J0IGNvbnN0IFBSRl9PVVRQVVQgPSBuZXcgVWludDhBcnJheShbMHhkZSwgMHhhZCwgMHhiZSwgMHhlZiwgMHhjYSwgMHhmZSwgMHgwMSwgMHgwMl0pLmJ1ZmZlcjtcbmV4cG9ydCBjb25zdCBDUkVERU5USUFMX0lEID0gJ1kzSmxaQzFwWkMwME5UWSc7XG5leHBvcnQgY29uc3QgREVWSUNFX01PTkdPX0lEID0gJ2RldmljZS1tb25nby1pZC0xJztcbmV4cG9ydCBjb25zdCBCQVNFX1NBTFQgPSAnWnFKNjRNMmRMNjV6bjItSnhkNThTTU4ySUxjOVFqYkNGeFVUR0hkX0xDOCc7XG5leHBvcnQgY29uc3QgUkVHSVNURVJfQ0hBTExFTkdFID0gQnVmZmVyLmZyb20oJ3JhbmRvbS1jaGFsbGVuZ2UnKS50b1N0cmluZygnYmFzZTY0Jyk7XG5leHBvcnQgY29uc3QgQVNTRVJUSU9OX0NIQUxMRU5HRSA9IEJ1ZmZlci5mcm9tKCdhc3NlcnRpb24tY2hhbGxlbmdlJykudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuIl19
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface KeychainState {
|
|
2
|
+
id: string;
|
|
3
|
+
encryptedPrv: string;
|
|
4
|
+
webauthnDevices?: Array<{
|
|
5
|
+
authenticatorInfo: {
|
|
6
|
+
credID: string;
|
|
7
|
+
};
|
|
8
|
+
prfSalt: string;
|
|
9
|
+
id?: string;
|
|
10
|
+
encryptedPrv?: string;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
export interface MockBitGo {
|
|
14
|
+
bitgo: any;
|
|
15
|
+
keychainState: KeychainState;
|
|
16
|
+
wallet: any;
|
|
17
|
+
encrypt: (params: {
|
|
18
|
+
password: string;
|
|
19
|
+
input: string;
|
|
20
|
+
}) => string;
|
|
21
|
+
decrypt: (params: {
|
|
22
|
+
password: string;
|
|
23
|
+
input: string;
|
|
24
|
+
}) => string;
|
|
25
|
+
}
|
|
26
|
+
export declare function makeMockBitGo(initialEncryptedPrv: string): MockBitGo;
|
|
27
|
+
//# sourceMappingURL=mockBitGo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mockBitGo.d.ts","sourceRoot":"","sources":["../../../../test/integration/helpers/mockBitGo.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,iBAAiB,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QACtC,OAAO,EAAE,MAAM,CAAC;QAChB,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,GAAG,CAAC;IACX,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,EAAE,GAAG,CAAC;IACZ,OAAO,EAAE,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;IACjE,OAAO,EAAE,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;CAClE;AAED,wBAAgB,aAAa,CAAC,mBAAmB,EAAE,MAAM,GAAG,SAAS,CA8GpE"}
|