@bitgo-beta/passkey-crypto 0.0.1-beta.7 → 0.0.1-beta.9
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 +67 -0
- package/dist/src/deriveEnterpriseSalt.d.ts +1 -1
- package/dist/src/deriveEnterpriseSalt.d.ts.map +1 -1
- package/dist/src/deriveEnterpriseSalt.js +5 -42
- package/dist/src/derivePasskeyPrfKey.d.ts +15 -0
- package/dist/src/derivePasskeyPrfKey.d.ts.map +1 -0
- package/dist/src/derivePasskeyPrfKey.js +45 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -2
- package/dist/src/registerPasskey.d.ts +10 -0
- package/dist/src/registerPasskey.d.ts.map +1 -0
- package/dist/src/registerPasskey.js +96 -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 +10 -0
- package/dist/src/removePasskeyFromWallet.d.ts.map +1 -0
- package/dist/src/removePasskeyFromWallet.js +22 -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 +205 -0
- package/dist/test/unit/deriveEnterpriseSalt.test.js +4 -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 +3 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BitGoBase, Keychain } from '@bitgo-beta/sdk-core';
|
|
2
|
+
import { WebAuthnOtpDevice, WebAuthnProvider } from './webAuthnTypes';
|
|
3
|
+
export declare function attachPasskeyToWallet(params: {
|
|
4
|
+
bitgo: BitGoBase;
|
|
5
|
+
coin: string;
|
|
6
|
+
walletId: string;
|
|
7
|
+
device: WebAuthnOtpDevice;
|
|
8
|
+
existingPassphrase: string;
|
|
9
|
+
provider: WebAuthnProvider;
|
|
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,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,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;CAC5B,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2EpB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.attachPasskeyToWallet = attachPasskeyToWallet;
|
|
4
|
+
const deriveEnterpriseSalt_1 = require("./deriveEnterpriseSalt");
|
|
5
|
+
const derivePassword_1 = require("./derivePassword");
|
|
6
|
+
async function attachPasskeyToWallet(params) {
|
|
7
|
+
const { bitgo, coin, walletId, device, existingPassphrase, provider } = params;
|
|
8
|
+
// Throw early if PRF extension is not supported
|
|
9
|
+
if (!device.prfSalt) {
|
|
10
|
+
throw new Error('PRF extension not supported by this device. Please use a different passkey.');
|
|
11
|
+
}
|
|
12
|
+
const baseCoin = bitgo.coin(coin);
|
|
13
|
+
// Fetch wallet and validate it is a hot wallet
|
|
14
|
+
const wallet = await baseCoin.wallets().get({ id: walletId });
|
|
15
|
+
if (wallet.type() !== 'hot') {
|
|
16
|
+
throw new Error(`Wallet ${walletId} is not a hot wallet. Only hot wallets support passkey attachment.`);
|
|
17
|
+
}
|
|
18
|
+
const walletData = wallet.toJSON();
|
|
19
|
+
const enterpriseId = walletData.enterprise;
|
|
20
|
+
if (!enterpriseId) {
|
|
21
|
+
throw new Error(`Wallet ${walletId} has no enterprise.`);
|
|
22
|
+
}
|
|
23
|
+
// Fetch the user keychain — iterates keys until it finds one with encryptedPrv
|
|
24
|
+
const keychain = await wallet.getEncryptedUserKeychain();
|
|
25
|
+
const keychainId = keychain.id;
|
|
26
|
+
// Derive enterprise-scoped salt
|
|
27
|
+
const enterpriseSalt = (0, deriveEnterpriseSalt_1.deriveEnterpriseSalt)(device.prfSalt, enterpriseId);
|
|
28
|
+
// Decrypt private key with existing passphrase
|
|
29
|
+
const privateKey = bitgo.decrypt({ password: existingPassphrase, input: keychain.encryptedPrv });
|
|
30
|
+
// Decode credentialId from base64url to ArrayBuffer for allowCredentials.
|
|
31
|
+
// The WebAuthn spec requires allowCredentials to be non-empty when using evalByCredential,
|
|
32
|
+
// and each entry must correspond to a key in the evalByCredential map.
|
|
33
|
+
const credentialIdBuffer = Buffer.from(device.credentialId.replace(/-/g, '+').replace(/_/g, '/'), 'base64').buffer;
|
|
34
|
+
// PRF assertion — evalByCredential maps this device's credentialId to its enterprise salt
|
|
35
|
+
const authResult = await provider.get({
|
|
36
|
+
publicKey: {
|
|
37
|
+
allowCredentials: [{ type: 'public-key', id: credentialIdBuffer }],
|
|
38
|
+
},
|
|
39
|
+
evalByCredential: { [device.credentialId]: enterpriseSalt },
|
|
40
|
+
});
|
|
41
|
+
if (!authResult.prfResult) {
|
|
42
|
+
throw new Error('PRF assertion did not return a result.');
|
|
43
|
+
}
|
|
44
|
+
// Derive password from PRF output and re-encrypt
|
|
45
|
+
const prfPassword = (0, derivePassword_1.derivePassword)(authResult.prfResult);
|
|
46
|
+
const encryptedPrv = bitgo.encrypt({ password: prfPassword, input: privateKey });
|
|
47
|
+
// Convert enterpriseSalt from hex to base64url (URL-safe, no padding)
|
|
48
|
+
// as required by the server's prfSalt validation.
|
|
49
|
+
const prfSaltBase64url = Buffer.from(enterpriseSalt, 'hex')
|
|
50
|
+
.toString('base64')
|
|
51
|
+
.replace(/\+/g, '-')
|
|
52
|
+
.replace(/\//g, '_')
|
|
53
|
+
.replace(/=+$/, '');
|
|
54
|
+
// PUT webauthnInfo to keychain endpoint
|
|
55
|
+
const updatedKeychain = await bitgo
|
|
56
|
+
.put(bitgo.url(`/${coin}/key/${keychainId}`, 2))
|
|
57
|
+
.send({
|
|
58
|
+
webauthnInfo: {
|
|
59
|
+
prfSalt: prfSaltBase64url,
|
|
60
|
+
otpDeviceId: device.id,
|
|
61
|
+
encryptedPrv,
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
.result();
|
|
65
|
+
return updatedKeychain;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0YWNoUGFzc2tleVRvV2FsbGV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2F0dGFjaFBhc3NrZXlUb1dhbGxldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUtBLHNEQWtGQztBQXRGRCxpRUFBOEQ7QUFDOUQscURBQWtEO0FBRzNDLEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxNQU8zQztJQUNDLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBRS9FLGdEQUFnRDtJQUNoRCxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3BCLE1BQU0sSUFBSSxLQUFLLENBQUMsNkVBQTZFLENBQUMsQ0FBQztJQUNqRyxDQUFDO0lBRUQsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVsQywrQ0FBK0M7SUFDL0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFFOUQsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLFFBQVEsb0VBQW9FLENBQUMsQ0FBQztJQUMxRyxDQUFDO0lBRUQsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ25DLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUM7SUFDM0MsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ2xCLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxRQUFRLHFCQUFxQixDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVELCtFQUErRTtJQUMvRSxNQUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO0lBQ3pELE1BQU0sVUFBVSxHQUFHLFFBQVEsQ0FBQyxFQUFFLENBQUM7SUFFL0IsZ0NBQWdDO0lBQ2hDLE1BQU0sY0FBYyxHQUFHLElBQUEsMkNBQW9CLEVBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQztJQUUxRSwrQ0FBK0M7SUFDL0MsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLFFBQVEsRUFBRSxrQkFBa0IsRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUM7SUFFakcsMEVBQTBFO0lBQzFFLDJGQUEyRjtJQUMzRix1RUFBdUU7SUFDdkUsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUVuSCwwRkFBMEY7SUFDMUYsTUFBTSxVQUFVLEdBQUcsTUFBTSxRQUFRLENBQUMsR0FBRyxDQUFDO1FBQ3BDLFNBQVMsRUFBRTtZQUNULGdCQUFnQixFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxDQUFDO1NBQzlCO1FBQ3RDLGdCQUFnQixFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLEVBQUUsY0FBYyxFQUFFO0tBQzVELENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRCxpREFBaUQ7SUFDakQsTUFBTSxXQUFXLEdBQUcsSUFBQSwrQkFBYyxFQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN6RCxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUVqRixzRUFBc0U7SUFDdEUsa0RBQWtEO0lBQ2xELE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDO1NBQ3hELFFBQVEsQ0FBQyxRQUFRLENBQUM7U0FDbEIsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUM7U0FDbkIsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUM7U0FDbkIsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztJQUV0Qix3Q0FBd0M7SUFDeEMsTUFBTSxlQUFlLEdBQUcsTUFBTSxLQUFLO1NBQ2hDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxRQUFRLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQy9DLElBQUksQ0FBQztRQUNKLFlBQVksRUFBRTtZQUNaLE9BQU8sRUFBRSxnQkFBZ0I7WUFDekIsV0FBVyxFQUFFLE1BQU0sQ0FBQyxFQUFFO1lBQ3RCLFlBQVk7U0FDYjtLQUNGLENBQUM7U0FDRCxNQUFNLEVBQUUsQ0FBQztJQUVaLE9BQU8sZUFBMkIsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQml0R29CYXNlLCBLZXljaGFpbiB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IGRlcml2ZUVudGVycHJpc2VTYWx0IH0gZnJvbSAnLi9kZXJpdmVFbnRlcnByaXNlU2FsdCc7XG5pbXBvcnQgeyBkZXJpdmVQYXNzd29yZCB9IGZyb20gJy4vZGVyaXZlUGFzc3dvcmQnO1xuaW1wb3J0IHsgV2ViQXV0aG5PdHBEZXZpY2UsIFdlYkF1dGhuUHJvdmlkZXIgfSBmcm9tICcuL3dlYkF1dGhuVHlwZXMnO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXR0YWNoUGFzc2tleVRvV2FsbGV0KHBhcmFtczoge1xuICBiaXRnbzogQml0R29CYXNlO1xuICBjb2luOiBzdHJpbmc7XG4gIHdhbGxldElkOiBzdHJpbmc7XG4gIGRldmljZTogV2ViQXV0aG5PdHBEZXZpY2U7XG4gIGV4aXN0aW5nUGFzc3BocmFzZTogc3RyaW5nO1xuICBwcm92aWRlcjogV2ViQXV0aG5Qcm92aWRlcjtcbn0pOiBQcm9taXNlPEtleWNoYWluPiB7XG4gIGNvbnN0IHsgYml0Z28sIGNvaW4sIHdhbGxldElkLCBkZXZpY2UsIGV4aXN0aW5nUGFzc3BocmFzZSwgcHJvdmlkZXIgfSA9IHBhcmFtcztcblxuICAvLyBUaHJvdyBlYXJseSBpZiBQUkYgZXh0ZW5zaW9uIGlzIG5vdCBzdXBwb3J0ZWRcbiAgaWYgKCFkZXZpY2UucHJmU2FsdCkge1xuICAgIHRocm93IG5ldyBFcnJvcignUFJGIGV4dGVuc2lvbiBub3Qgc3VwcG9ydGVkIGJ5IHRoaXMgZGV2aWNlLiBQbGVhc2UgdXNlIGEgZGlmZmVyZW50IHBhc3NrZXkuJyk7XG4gIH1cblxuICBjb25zdCBiYXNlQ29pbiA9IGJpdGdvLmNvaW4oY29pbik7XG5cbiAgLy8gRmV0Y2ggd2FsbGV0IGFuZCB2YWxpZGF0ZSBpdCBpcyBhIGhvdCB3YWxsZXRcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgYmFzZUNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiB3YWxsZXRJZCB9KTtcblxuICBpZiAod2FsbGV0LnR5cGUoKSAhPT0gJ2hvdCcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFdhbGxldCAke3dhbGxldElkfSBpcyBub3QgYSBob3Qgd2FsbGV0LiBPbmx5IGhvdCB3YWxsZXRzIHN1cHBvcnQgcGFzc2tleSBhdHRhY2htZW50LmApO1xuICB9XG5cbiAgY29uc3Qgd2FsbGV0RGF0YSA9IHdhbGxldC50b0pTT04oKTtcbiAgY29uc3QgZW50ZXJwcmlzZUlkID0gd2FsbGV0RGF0YS5lbnRlcnByaXNlO1xuICBpZiAoIWVudGVycHJpc2VJZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgV2FsbGV0ICR7d2FsbGV0SWR9IGhhcyBubyBlbnRlcnByaXNlLmApO1xuICB9XG5cbiAgLy8gRmV0Y2ggdGhlIHVzZXIga2V5Y2hhaW4g4oCUIGl0ZXJhdGVzIGtleXMgdW50aWwgaXQgZmluZHMgb25lIHdpdGggZW5jcnlwdGVkUHJ2XG4gIGNvbnN0IGtleWNoYWluID0gYXdhaXQgd2FsbGV0LmdldEVuY3J5cHRlZFVzZXJLZXljaGFpbigpO1xuICBjb25zdCBrZXljaGFpbklkID0ga2V5Y2hhaW4uaWQ7XG5cbiAgLy8gRGVyaXZlIGVudGVycHJpc2Utc2NvcGVkIHNhbHRcbiAgY29uc3QgZW50ZXJwcmlzZVNhbHQgPSBkZXJpdmVFbnRlcnByaXNlU2FsdChkZXZpY2UucHJmU2FsdCwgZW50ZXJwcmlzZUlkKTtcblxuICAvLyBEZWNyeXB0IHByaXZhdGUga2V5IHdpdGggZXhpc3RpbmcgcGFzc3BocmFzZVxuICBjb25zdCBwcml2YXRlS2V5ID0gYml0Z28uZGVjcnlwdCh7IHBhc3N3b3JkOiBleGlzdGluZ1Bhc3NwaHJhc2UsIGlucHV0OiBrZXljaGFpbi5lbmNyeXB0ZWRQcnYgfSk7XG5cbiAgLy8gRGVjb2RlIGNyZWRlbnRpYWxJZCBmcm9tIGJhc2U2NHVybCB0byBBcnJheUJ1ZmZlciBmb3IgYWxsb3dDcmVkZW50aWFscy5cbiAgLy8gVGhlIFdlYkF1dGhuIHNwZWMgcmVxdWlyZXMgYWxsb3dDcmVkZW50aWFscyB0byBiZSBub24tZW1wdHkgd2hlbiB1c2luZyBldmFsQnlDcmVkZW50aWFsLFxuICAvLyBhbmQgZWFjaCBlbnRyeSBtdXN0IGNvcnJlc3BvbmQgdG8gYSBrZXkgaW4gdGhlIGV2YWxCeUNyZWRlbnRpYWwgbWFwLlxuICBjb25zdCBjcmVkZW50aWFsSWRCdWZmZXIgPSBCdWZmZXIuZnJvbShkZXZpY2UuY3JlZGVudGlhbElkLnJlcGxhY2UoLy0vZywgJysnKS5yZXBsYWNlKC9fL2csICcvJyksICdiYXNlNjQnKS5idWZmZXI7XG5cbiAgLy8gUFJGIGFzc2VydGlvbiDigJQgZXZhbEJ5Q3JlZGVudGlhbCBtYXBzIHRoaXMgZGV2aWNlJ3MgY3JlZGVudGlhbElkIHRvIGl0cyBlbnRlcnByaXNlIHNhbHRcbiAgY29uc3QgYXV0aFJlc3VsdCA9IGF3YWl0IHByb3ZpZGVyLmdldCh7XG4gICAgcHVibGljS2V5OiB7XG4gICAgICBhbGxvd0NyZWRlbnRpYWxzOiBbeyB0eXBlOiAncHVibGljLWtleScsIGlkOiBjcmVkZW50aWFsSWRCdWZmZXIgfV0sXG4gICAgfSBhcyBQdWJsaWNLZXlDcmVkZW50aWFsUmVxdWVzdE9wdGlvbnMsXG4gICAgZXZhbEJ5Q3JlZGVudGlhbDogeyBbZGV2aWNlLmNyZWRlbnRpYWxJZF06IGVudGVycHJpc2VTYWx0IH0sXG4gIH0pO1xuXG4gIGlmICghYXV0aFJlc3VsdC5wcmZSZXN1bHQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1BSRiBhc3NlcnRpb24gZGlkIG5vdCByZXR1cm4gYSByZXN1bHQuJyk7XG4gIH1cblxuICAvLyBEZXJpdmUgcGFzc3dvcmQgZnJvbSBQUkYgb3V0cHV0IGFuZCByZS1lbmNyeXB0XG4gIGNvbnN0IHByZlBhc3N3b3JkID0gZGVyaXZlUGFzc3dvcmQoYXV0aFJlc3VsdC5wcmZSZXN1bHQpO1xuICBjb25zdCBlbmNyeXB0ZWRQcnYgPSBiaXRnby5lbmNyeXB0KHsgcGFzc3dvcmQ6IHByZlBhc3N3b3JkLCBpbnB1dDogcHJpdmF0ZUtleSB9KTtcblxuICAvLyBDb252ZXJ0IGVudGVycHJpc2VTYWx0IGZyb20gaGV4IHRvIGJhc2U2NHVybCAoVVJMLXNhZmUsIG5vIHBhZGRpbmcpXG4gIC8vIGFzIHJlcXVpcmVkIGJ5IHRoZSBzZXJ2ZXIncyBwcmZTYWx0IHZhbGlkYXRpb24uXG4gIGNvbnN0IHByZlNhbHRCYXNlNjR1cmwgPSBCdWZmZXIuZnJvbShlbnRlcnByaXNlU2FsdCwgJ2hleCcpXG4gICAgLnRvU3RyaW5nKCdiYXNlNjQnKVxuICAgIC5yZXBsYWNlKC9cXCsvZywgJy0nKVxuICAgIC5yZXBsYWNlKC9cXC8vZywgJ18nKVxuICAgIC5yZXBsYWNlKC89KyQvLCAnJyk7XG5cbiAgLy8gUFVUIHdlYmF1dGhuSW5mbyB0byBrZXljaGFpbiBlbmRwb2ludFxuICBjb25zdCB1cGRhdGVkS2V5Y2hhaW4gPSBhd2FpdCBiaXRnb1xuICAgIC5wdXQoYml0Z28udXJsKGAvJHtjb2lufS9rZXkvJHtrZXljaGFpbklkfWAsIDIpKVxuICAgIC5zZW5kKHtcbiAgICAgIHdlYmF1dGhuSW5mbzoge1xuICAgICAgICBwcmZTYWx0OiBwcmZTYWx0QmFzZTY0dXJsLFxuICAgICAgICBvdHBEZXZpY2VJZDogZGV2aWNlLmlkLFxuICAgICAgICBlbmNyeXB0ZWRQcnYsXG4gICAgICB9LFxuICAgIH0pXG4gICAgLnJlc3VsdCgpO1xuXG4gIHJldHVybiB1cGRhdGVkS2V5Y2hhaW4gYXMgS2V5Y2hhaW47XG59XG4iXX0=
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @param baseSalt - Server-provided base64url-encoded PRF salt
|
|
8
8
|
* @param enterpriseId - Enterprise identifier
|
|
9
|
-
* @returns
|
|
9
|
+
* @returns Hex-encoded HMAC-SHA256 digest
|
|
10
10
|
*/
|
|
11
11
|
export declare function deriveEnterpriseSalt(baseSalt: string, enterpriseId: string): string;
|
|
12
12
|
//# sourceMappingURL=deriveEnterpriseSalt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deriveEnterpriseSalt.d.ts","sourceRoot":"","sources":["../../src/deriveEnterpriseSalt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deriveEnterpriseSalt.d.ts","sourceRoot":"","sources":["../../src/deriveEnterpriseSalt.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAGnF"}
|
|
@@ -1,40 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.deriveEnterpriseSalt = deriveEnterpriseSalt;
|
|
37
|
-
const
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
38
5
|
/**
|
|
39
6
|
* Derives an enterprise-scoped PRF salt to prevent cross-enterprise key reuse.
|
|
40
7
|
*
|
|
@@ -43,14 +10,10 @@ const sjcl = __importStar(require("@bitgo-beta/sjcl"));
|
|
|
43
10
|
*
|
|
44
11
|
* @param baseSalt - Server-provided base64url-encoded PRF salt
|
|
45
12
|
* @param enterpriseId - Enterprise identifier
|
|
46
|
-
* @returns
|
|
13
|
+
* @returns Hex-encoded HMAC-SHA256 digest
|
|
47
14
|
*/
|
|
48
15
|
function deriveEnterpriseSalt(baseSalt, enterpriseId) {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const dataBits = codec.utf8String.toBits(enterpriseId);
|
|
52
|
-
const hmacInstance = new misc.hmac(keyBits, hash.sha256);
|
|
53
|
-
const resultBits = hmacInstance.mac(dataBits);
|
|
54
|
-
return codec.base64.fromBits(resultBits);
|
|
16
|
+
const keyBytes = Buffer.from(baseSalt.replace(/-/g, '+').replace(/_/g, '/'), 'base64');
|
|
17
|
+
return (0, crypto_1.createHmac)('sha256', keyBytes).update(enterpriseId).digest('hex');
|
|
55
18
|
}
|
|
56
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVyaXZlRW50ZXJwcmlzZVNhbHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGVyaXZlRW50ZXJwcmlzZVNhbHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFZQSxvREFHQztBQWZELG1DQUFvQztBQUVwQzs7Ozs7Ozs7O0dBU0c7QUFDSCxTQUFnQixvQkFBb0IsQ0FBQyxRQUFnQixFQUFFLFlBQW9CO0lBQ3pFLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN2RixPQUFPLElBQUEsbUJBQVUsRUFBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMzRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlSG1hYyB9IGZyb20gJ2NyeXB0byc7XG5cbi8qKlxuICogRGVyaXZlcyBhbiBlbnRlcnByaXNlLXNjb3BlZCBQUkYgc2FsdCB0byBwcmV2ZW50IGNyb3NzLWVudGVycHJpc2Uga2V5IHJldXNlLlxuICpcbiAqIENvbXB1dGVzIEhNQUMtU0hBMjU2KGtleT1wcmZTYWx0X2Jhc2U2NHVybF9kZWNvZGVkLCBkYXRhPWVudGVycHJpc2VJZF91dGY4KS5cbiAqIFRoZSBiYXNlU2FsdCBtdXN0IGFsd2F5cyBjb21lIGZyb20gdGhlIHNlcnZlciDigJQgbmV2ZXIgZ2VuZXJhdGUgaXQgY2xpZW50LXNpZGUuXG4gKlxuICogQHBhcmFtIGJhc2VTYWx0IC0gU2VydmVyLXByb3ZpZGVkIGJhc2U2NHVybC1lbmNvZGVkIFBSRiBzYWx0XG4gKiBAcGFyYW0gZW50ZXJwcmlzZUlkIC0gRW50ZXJwcmlzZSBpZGVudGlmaWVyXG4gKiBAcmV0dXJucyBIZXgtZW5jb2RlZCBITUFDLVNIQTI1NiBkaWdlc3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlcml2ZUVudGVycHJpc2VTYWx0KGJhc2VTYWx0OiBzdHJpbmcsIGVudGVycHJpc2VJZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qga2V5Qnl0ZXMgPSBCdWZmZXIuZnJvbShiYXNlU2FsdC5yZXBsYWNlKC8tL2csICcrJykucmVwbGFjZSgvXy9nLCAnLycpLCAnYmFzZTY0Jyk7XG4gIHJldHVybiBjcmVhdGVIbWFjKCdzaGEyNTYnLCBrZXlCeXRlcykudXBkYXRlKGVudGVycHJpc2VJZCkuZGlnZXN0KCdoZXgnKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BitGoBase, IWallet } from '@bitgo-beta/sdk-core';
|
|
2
|
+
import type { WebAuthnProvider } from './webAuthnTypes';
|
|
3
|
+
/**
|
|
4
|
+
* Derives a wallet passphrase from a passkey PRF output.
|
|
5
|
+
*
|
|
6
|
+
* Fetches the wallet's user keychain, triggers a WebAuthn assertion with PRF
|
|
7
|
+
* evaluation, and returns a hex-encoded passphrase suitable for use as
|
|
8
|
+
* walletPassphrase in signing calls.
|
|
9
|
+
*/
|
|
10
|
+
export declare function derivePasskeyPrfKey(params: {
|
|
11
|
+
bitgo: BitGoBase;
|
|
12
|
+
wallet: IWallet;
|
|
13
|
+
provider: WebAuthnProvider;
|
|
14
|
+
}): Promise<string>;
|
|
15
|
+
//# sourceMappingURL=derivePasskeyPrfKey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derivePasskeyPrfKey.d.ts","sourceRoot":"","sources":["../../src/derivePasskeyPrfKey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAG/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAMxD;;;;;;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,CAwClB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.derivePasskeyPrfKey = derivePasskeyPrfKey;
|
|
4
|
+
const prfHelpers_1 = require("./prfHelpers");
|
|
5
|
+
const derivePassword_1 = require("./derivePassword");
|
|
6
|
+
/**
|
|
7
|
+
* Derives a wallet passphrase from a passkey PRF output.
|
|
8
|
+
*
|
|
9
|
+
* Fetches the wallet's user keychain, triggers a WebAuthn assertion with PRF
|
|
10
|
+
* evaluation, and returns a hex-encoded passphrase suitable for use as
|
|
11
|
+
* walletPassphrase in signing calls.
|
|
12
|
+
*/
|
|
13
|
+
async function derivePasskeyPrfKey(params) {
|
|
14
|
+
const { bitgo, wallet, provider } = params;
|
|
15
|
+
// Fetch the wallet's user keychain to get webauthnDevices
|
|
16
|
+
const keychain = await wallet.getEncryptedUserKeychain();
|
|
17
|
+
const devices = keychain.webauthnDevices;
|
|
18
|
+
if (!devices || devices.length === 0) {
|
|
19
|
+
throw new Error('No passkey devices available');
|
|
20
|
+
}
|
|
21
|
+
// Build PRF eval map from devices
|
|
22
|
+
const { evalByCredential } = (0, prfHelpers_1.buildEvalByCredential)(devices);
|
|
23
|
+
if (Object.keys(evalByCredential).length === 0) {
|
|
24
|
+
throw new Error('No passkey devices available with a valid PRF salt');
|
|
25
|
+
}
|
|
26
|
+
// Fetch a server-issued assertion challenge
|
|
27
|
+
const { challenge } = (await bitgo
|
|
28
|
+
.get(bitgo.url('/user/otp/webauthn/assertion', 2))
|
|
29
|
+
.result());
|
|
30
|
+
// Trigger WebAuthn assertion with PRF evaluation via the provider (navigator layer)
|
|
31
|
+
const result = await provider.get({
|
|
32
|
+
publicKey: {
|
|
33
|
+
challenge: Buffer.from(challenge, 'base64'),
|
|
34
|
+
},
|
|
35
|
+
evalByCredential,
|
|
36
|
+
});
|
|
37
|
+
// Verify the credential matches a known device
|
|
38
|
+
(0, prfHelpers_1.matchDeviceByCredentialId)(devices, result.credentialId);
|
|
39
|
+
// Derive and return hex-encoded wallet passphrase
|
|
40
|
+
if (!result.prfResult) {
|
|
41
|
+
throw new Error('PRF output was not returned by the authenticator');
|
|
42
|
+
}
|
|
43
|
+
return (0, derivePassword_1.derivePassword)(result.prfResult);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVyaXZlUGFzc2tleVByZktleS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kZXJpdmVQYXNza2V5UHJmS2V5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBZ0JBLGtEQTRDQztBQTNERCw2Q0FBZ0Y7QUFDaEYscURBQWtEO0FBT2xEOzs7Ozs7R0FNRztBQUNJLEtBQUssVUFBVSxtQkFBbUIsQ0FBQyxNQUl6QztJQUNDLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUUzQywwREFBMEQ7SUFDMUQsTUFBTSxRQUFRLEdBQUcsTUFBTSxNQUFNLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztJQUN6RCxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsZUFBZSxDQUFDO0lBRXpDLElBQUksQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVELGtDQUFrQztJQUNsQyxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsR0FBRyxJQUFBLGtDQUFxQixFQUFDLE9BQXNELENBQUMsQ0FBQztJQUUzRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDL0MsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFFRCw0Q0FBNEM7SUFDNUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTSxLQUFLO1NBQy9CLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLDhCQUE4QixFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ2pELE1BQU0sRUFBRSxDQUErQixDQUFDO0lBRTNDLG9GQUFvRjtJQUNwRixNQUFNLE1BQU0sR0FBRyxNQUFNLFFBQVEsQ0FBQyxHQUFHLENBQUM7UUFDaEMsU0FBUyxFQUFFO1lBQ1QsU0FBUyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQztTQUNQO1FBQ3RDLGdCQUFnQjtLQUNqQixDQUFDLENBQUM7SUFFSCwrQ0FBK0M7SUFDL0MsSUFBQSxzQ0FBeUIsRUFBQyxPQUEwRCxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUUzRyxrREFBa0Q7SUFDbEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUVELE9BQU8sSUFBQSwrQkFBYyxFQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUMxQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBCaXRHb0Jhc2UsIElXYWxsZXQgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBidWlsZEV2YWxCeUNyZWRlbnRpYWwsIG1hdGNoRGV2aWNlQnlDcmVkZW50aWFsSWQgfSBmcm9tICcuL3ByZkhlbHBlcnMnO1xuaW1wb3J0IHsgZGVyaXZlUGFzc3dvcmQgfSBmcm9tICcuL2Rlcml2ZVBhc3N3b3JkJztcbmltcG9ydCB0eXBlIHsgV2ViQXV0aG5Qcm92aWRlciB9IGZyb20gJy4vd2ViQXV0aG5UeXBlcyc7XG5cbmludGVyZmFjZSBBc3NlcnRpb25DaGFsbGVuZ2VSZXNwb25zZSB7XG4gIGNoYWxsZW5nZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIERlcml2ZXMgYSB3YWxsZXQgcGFzc3BocmFzZSBmcm9tIGEgcGFzc2tleSBQUkYgb3V0cHV0LlxuICpcbiAqIEZldGNoZXMgdGhlIHdhbGxldCdzIHVzZXIga2V5Y2hhaW4sIHRyaWdnZXJzIGEgV2ViQXV0aG4gYXNzZXJ0aW9uIHdpdGggUFJGXG4gKiBldmFsdWF0aW9uLCBhbmQgcmV0dXJucyBhIGhleC1lbmNvZGVkIHBhc3NwaHJhc2Ugc3VpdGFibGUgZm9yIHVzZSBhc1xuICogd2FsbGV0UGFzc3BocmFzZSBpbiBzaWduaW5nIGNhbGxzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVyaXZlUGFzc2tleVByZktleShwYXJhbXM6IHtcbiAgYml0Z286IEJpdEdvQmFzZTtcbiAgd2FsbGV0OiBJV2FsbGV0O1xuICBwcm92aWRlcjogV2ViQXV0aG5Qcm92aWRlcjtcbn0pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCB7IGJpdGdvLCB3YWxsZXQsIHByb3ZpZGVyIH0gPSBwYXJhbXM7XG5cbiAgLy8gRmV0Y2ggdGhlIHdhbGxldCdzIHVzZXIga2V5Y2hhaW4gdG8gZ2V0IHdlYmF1dGhuRGV2aWNlc1xuICBjb25zdCBrZXljaGFpbiA9IGF3YWl0IHdhbGxldC5nZXRFbmNyeXB0ZWRVc2VyS2V5Y2hhaW4oKTtcbiAgY29uc3QgZGV2aWNlcyA9IGtleWNoYWluLndlYmF1dGhuRGV2aWNlcztcblxuICBpZiAoIWRldmljZXMgfHwgZGV2aWNlcy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHBhc3NrZXkgZGV2aWNlcyBhdmFpbGFibGUnKTtcbiAgfVxuXG4gIC8vIEJ1aWxkIFBSRiBldmFsIG1hcCBmcm9tIGRldmljZXNcbiAgY29uc3QgeyBldmFsQnlDcmVkZW50aWFsIH0gPSBidWlsZEV2YWxCeUNyZWRlbnRpYWwoZGV2aWNlcyBhcyBQYXJhbWV0ZXJzPHR5cGVvZiBidWlsZEV2YWxCeUNyZWRlbnRpYWw+WzBdKTtcblxuICBpZiAoT2JqZWN0LmtleXMoZXZhbEJ5Q3JlZGVudGlhbCkubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdObyBwYXNza2V5IGRldmljZXMgYXZhaWxhYmxlIHdpdGggYSB2YWxpZCBQUkYgc2FsdCcpO1xuICB9XG5cbiAgLy8gRmV0Y2ggYSBzZXJ2ZXItaXNzdWVkIGFzc2VydGlvbiBjaGFsbGVuZ2VcbiAgY29uc3QgeyBjaGFsbGVuZ2UgfSA9IChhd2FpdCBiaXRnb1xuICAgIC5nZXQoYml0Z28udXJsKCcvdXNlci9vdHAvd2ViYXV0aG4vYXNzZXJ0aW9uJywgMikpXG4gICAgLnJlc3VsdCgpKSBhcyBBc3NlcnRpb25DaGFsbGVuZ2VSZXNwb25zZTtcblxuICAvLyBUcmlnZ2VyIFdlYkF1dGhuIGFzc2VydGlvbiB3aXRoIFBSRiBldmFsdWF0aW9uIHZpYSB0aGUgcHJvdmlkZXIgKG5hdmlnYXRvciBsYXllcilcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcHJvdmlkZXIuZ2V0KHtcbiAgICBwdWJsaWNLZXk6IHtcbiAgICAgIGNoYWxsZW5nZTogQnVmZmVyLmZyb20oY2hhbGxlbmdlLCAnYmFzZTY0JyksXG4gICAgfSBhcyBQdWJsaWNLZXlDcmVkZW50aWFsUmVxdWVzdE9wdGlvbnMsXG4gICAgZXZhbEJ5Q3JlZGVudGlhbCxcbiAgfSk7XG5cbiAgLy8gVmVyaWZ5IHRoZSBjcmVkZW50aWFsIG1hdGNoZXMgYSBrbm93biBkZXZpY2VcbiAgbWF0Y2hEZXZpY2VCeUNyZWRlbnRpYWxJZChkZXZpY2VzIGFzIFBhcmFtZXRlcnM8dHlwZW9mIG1hdGNoRGV2aWNlQnlDcmVkZW50aWFsSWQ+WzBdLCByZXN1bHQuY3JlZGVudGlhbElkKTtcblxuICAvLyBEZXJpdmUgYW5kIHJldHVybiBoZXgtZW5jb2RlZCB3YWxsZXQgcGFzc3BocmFzZVxuICBpZiAoIXJlc3VsdC5wcmZSZXN1bHQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1BSRiBvdXRwdXQgd2FzIG5vdCByZXR1cm5lZCBieSB0aGUgYXV0aGVudGljYXRvcicpO1xuICB9XG5cbiAgcmV0dXJuIGRlcml2ZVBhc3N3b3JkKHJlc3VsdC5wcmZSZXN1bHQpO1xufVxuIl19
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { derivePassword } from './derivePassword';
|
|
2
|
+
export { registerPasskey } from './registerPasskey';
|
|
2
3
|
export { deriveEnterpriseSalt } from './deriveEnterpriseSalt';
|
|
3
4
|
export { buildEvalByCredential, matchDeviceByCredentialId } from './prfHelpers';
|
|
5
|
+
export { removePasskeyFromAccount } from './removePasskeyFromAccount';
|
|
4
6
|
export type { WebAuthnOtpDevice, PasskeyAuthResult, PasskeyGetOptions, WebAuthnProvider } from './webAuthnTypes';
|
|
7
|
+
export { removePasskeyFromWallet } from './removePasskeyFromWallet';
|
|
5
8
|
//# 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,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAChF,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,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,iBAAiB,CAAC;AACjH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/src/index.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.matchDeviceByCredentialId = exports.buildEvalByCredential = exports.deriveEnterpriseSalt = exports.derivePassword = void 0;
|
|
3
|
+
exports.removePasskeyFromWallet = exports.removePasskeyFromAccount = exports.matchDeviceByCredentialId = exports.buildEvalByCredential = exports.deriveEnterpriseSalt = exports.registerPasskey = exports.derivePassword = void 0;
|
|
4
4
|
var derivePassword_1 = require("./derivePassword");
|
|
5
5
|
Object.defineProperty(exports, "derivePassword", { enumerable: true, get: function () { return derivePassword_1.derivePassword; } });
|
|
6
|
+
var registerPasskey_1 = require("./registerPasskey");
|
|
7
|
+
Object.defineProperty(exports, "registerPasskey", { enumerable: true, get: function () { return registerPasskey_1.registerPasskey; } });
|
|
6
8
|
var deriveEnterpriseSalt_1 = require("./deriveEnterpriseSalt");
|
|
7
9
|
Object.defineProperty(exports, "deriveEnterpriseSalt", { enumerable: true, get: function () { return deriveEnterpriseSalt_1.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
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbURBQWtEO0FBQXpDLGdIQUFBLGNBQWMsT0FBQTtBQUN2QixxREFBb0Q7QUFBM0Msa0hBQUEsZUFBZSxPQUFBO0FBQ3hCLCtEQUE4RDtBQUFyRCw0SEFBQSxvQkFBb0IsT0FBQTtBQUM3QiwyQ0FBZ0Y7QUFBdkUsbUhBQUEscUJBQXFCLE9BQUE7QUFBRSx1SEFBQSx5QkFBeUIsT0FBQTtBQUN6RCx1RUFBc0U7QUFBN0Qsb0lBQUEsd0JBQXdCLE9BQUE7QUFFakMscUVBQW9FO0FBQTNELGtJQUFBLHVCQUF1QixPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgZGVyaXZlUGFzc3dvcmQgfSBmcm9tICcuL2Rlcml2ZVBhc3N3b3JkJztcbmV4cG9ydCB7IHJlZ2lzdGVyUGFzc2tleSB9IGZyb20gJy4vcmVnaXN0ZXJQYXNza2V5JztcbmV4cG9ydCB7IGRlcml2ZUVudGVycHJpc2VTYWx0IH0gZnJvbSAnLi9kZXJpdmVFbnRlcnByaXNlU2FsdCc7XG5leHBvcnQgeyBidWlsZEV2YWxCeUNyZWRlbnRpYWwsIG1hdGNoRGV2aWNlQnlDcmVkZW50aWFsSWQgfSBmcm9tICcuL3ByZkhlbHBlcnMnO1xuZXhwb3J0IHsgcmVtb3ZlUGFzc2tleUZyb21BY2NvdW50IH0gZnJvbSAnLi9yZW1vdmVQYXNza2V5RnJvbUFjY291bnQnO1xuZXhwb3J0IHR5cGUgeyBXZWJBdXRobk90cERldmljZSwgUGFzc2tleUF1dGhSZXN1bHQsIFBhc3NrZXlHZXRPcHRpb25zLCBXZWJBdXRoblByb3ZpZGVyIH0gZnJvbSAnLi93ZWJBdXRoblR5cGVzJztcbmV4cG9ydCB7IHJlbW92ZVBhc3NrZXlGcm9tV2FsbGV0IH0gZnJvbSAnLi9yZW1vdmVQYXNza2V5RnJvbVdhbGxldCc7XG4iXX0=
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BitGoBase } from '@bitgo-beta/sdk-core';
|
|
2
|
+
import { WebAuthnOtpDevice, WebAuthnProvider } from './webAuthnTypes';
|
|
3
|
+
export declare function registerPasskey(params: {
|
|
4
|
+
bitgo: BitGoBase;
|
|
5
|
+
provider: WebAuthnProvider;
|
|
6
|
+
label: string;
|
|
7
|
+
}): Promise<WebAuthnOtpDevice & {
|
|
8
|
+
prfSupported: boolean;
|
|
9
|
+
}>;
|
|
10
|
+
//# 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,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAyEtE,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,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerPasskey = registerPasskey;
|
|
4
|
+
/** Encodes an ArrayBuffer as a base64url string (no padding). */
|
|
5
|
+
function encodeBase64Url(buffer) {
|
|
6
|
+
return Buffer.from(buffer).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Recursively converts a PublicKeyCredential (or any value it contains) to a
|
|
10
|
+
* JSON-serialisable representation, encoding ArrayBuffers as base64url strings.
|
|
11
|
+
*/
|
|
12
|
+
function publicKeyCredentialToJSON(value) {
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
return value.map(publicKeyCredentialToJSON);
|
|
15
|
+
}
|
|
16
|
+
if (value instanceof ArrayBuffer) {
|
|
17
|
+
return encodeBase64Url(value);
|
|
18
|
+
}
|
|
19
|
+
if (ArrayBuffer.isView(value)) {
|
|
20
|
+
return encodeBase64Url(value.buffer);
|
|
21
|
+
}
|
|
22
|
+
if (value instanceof Object) {
|
|
23
|
+
const result = {};
|
|
24
|
+
// Use for...in to enumerate DOM object properties (non-enumerable own + inherited)
|
|
25
|
+
for (const key in value) {
|
|
26
|
+
result[key] = publicKeyCredentialToJSON(value[key]);
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Decodes excluded credential IDs from base64 strings to ArrayBuffers.
|
|
34
|
+
* The WebAuthn API requires BufferSource values, not base64 strings.
|
|
35
|
+
*/
|
|
36
|
+
function preformatExcludedCredentials(excludeCredentials) {
|
|
37
|
+
if (!excludeCredentials)
|
|
38
|
+
return [];
|
|
39
|
+
return excludeCredentials.map((cred) => ({
|
|
40
|
+
...cred,
|
|
41
|
+
id: Buffer.from(cred.id, 'base64'),
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
async function registerPasskey(params) {
|
|
45
|
+
const { bitgo, provider, label } = params;
|
|
46
|
+
// Step 1: Fetch server challenge (contains baseSalt)
|
|
47
|
+
const challenge = (await bitgo
|
|
48
|
+
.get(bitgo.url('/user/otp/webauthn/register', 2))
|
|
49
|
+
.result());
|
|
50
|
+
// Step 2: Pass formatted challenge to provider.create() — browser returns attestation
|
|
51
|
+
const attestation = await provider.create({
|
|
52
|
+
challenge: Buffer.from(challenge.challenge, 'base64'),
|
|
53
|
+
rp: challenge.rp,
|
|
54
|
+
user: challenge.user,
|
|
55
|
+
pubKeyCredParams: challenge.pubKeyCredParams,
|
|
56
|
+
timeout: challenge.timeout,
|
|
57
|
+
excludeCredentials: preformatExcludedCredentials(challenge.excludeCredentials),
|
|
58
|
+
authenticatorSelection: challenge.authenticatorSelection,
|
|
59
|
+
attestation: challenge.attestation,
|
|
60
|
+
extensions: challenge.extensions,
|
|
61
|
+
});
|
|
62
|
+
// Step 3: Check if PRF is supported — `prf.enabled` is set during registration
|
|
63
|
+
// (not `prf.results.first`, which is only present during authentication assertions)
|
|
64
|
+
const clientExtensionResults = attestation.getClientExtensionResults();
|
|
65
|
+
const prfEnabled = clientExtensionResults.prf;
|
|
66
|
+
const prfSupported = typeof prfEnabled === 'object' && prfEnabled !== null && prfEnabled.enabled === true;
|
|
67
|
+
// Step 4: Serialize the full credential using recursive base64url encoding
|
|
68
|
+
const otp = JSON.stringify(publicKeyCredentialToJSON(attestation));
|
|
69
|
+
const putBody = {
|
|
70
|
+
otp,
|
|
71
|
+
type: 'webauthn',
|
|
72
|
+
label,
|
|
73
|
+
};
|
|
74
|
+
if (prfSupported) {
|
|
75
|
+
putBody.extensions = ['prf'];
|
|
76
|
+
putBody.scopes = ['wallet_hot'];
|
|
77
|
+
}
|
|
78
|
+
// Step 5: PUT /api/v2/user/otp
|
|
79
|
+
const response = (await bitgo.put(bitgo.url('/user/otp', 2)).send(putBody).result());
|
|
80
|
+
// Step 6: Find the newly registered device by matching credentialId
|
|
81
|
+
const device = response.user.otpDevices.find((d) => d.credentialId === attestation.id);
|
|
82
|
+
if (!device) {
|
|
83
|
+
const available = response.user.otpDevices.map((d) => d.credentialId).join(', ');
|
|
84
|
+
throw new Error(`Registered device not found in response (credentialId: ${attestation.id}). Available: [${available}]`);
|
|
85
|
+
}
|
|
86
|
+
// Step 7: Return WebAuthnOtpDevice + prfSupported
|
|
87
|
+
return {
|
|
88
|
+
id: device.id,
|
|
89
|
+
credentialId: device.credentialId,
|
|
90
|
+
prfSalt: device.prfSalt,
|
|
91
|
+
isPasskey: device.isPasskey,
|
|
92
|
+
extensions: device.extensions,
|
|
93
|
+
prfSupported,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0ZXJQYXNza2V5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlZ2lzdGVyUGFzc2tleS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQTBFQSwwQ0FrRUM7QUE5R0QsaUVBQWlFO0FBQ2pFLFNBQVMsZUFBZSxDQUFDLE1BQW1CO0lBQzFDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDMUcsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMseUJBQXlCLENBQUMsS0FBYztJQUMvQyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN6QixPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMseUJBQXlCLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBQ0QsSUFBSSxLQUFLLFlBQVksV0FBVyxFQUFFLENBQUM7UUFDakMsT0FBTyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUNELElBQUksV0FBVyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzlCLE9BQU8sZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFxQixDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUNELElBQUksS0FBSyxZQUFZLE1BQU0sRUFBRSxDQUFDO1FBQzVCLE1BQU0sTUFBTSxHQUE0QixFQUFFLENBQUM7UUFDM0MsbUZBQW1GO1FBQ25GLEtBQUssTUFBTSxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7WUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLHlCQUF5QixDQUFFLEtBQWlDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztR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QUMsTUFBTSxFQUFFLENBQUM7UUFDWixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakYsTUFBTSxJQUFJLEtBQUssQ0FDYiwwREFBMEQsV0FBVyxDQUFDLEVBQUUsa0JBQWtCLFNBQVMsR0FBRyxDQUN2RyxDQUFDO0lBQ0osQ0FBQztJQUVELGtEQUFrRDtJQUNsRCxPQUFPO1FBQ0wsRUFBRSxFQUFFLE1BQU0sQ0FBQyxFQUFFO1FBQ2IsWUFBWSxFQUFFLE1BQU0sQ0FBQyxZQUFZO1FBQ2pDLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztRQUN2QixTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7UUFDM0IsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO1FBQzdCLFlBQVk7S0FDYixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJpdEdvQmFzZSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IFdlYkF1dGhuT3RwRGV2aWNlLCBXZWJBdXRoblByb3ZpZGVyIH0gZnJvbSAnLi93ZWJBdXRoblR5cGVzJztcblxuaW50ZXJmYWNlIFJlZ2lzdGVyQ2hhbGxlbmdlUmVzcG9uc2Uge1xuICBjaGFsbGVuZ2U6IHN0cmluZztcbiAgYmFzZVNhbHQ6IHN0cmluZztcbiAgcnA6IFB1YmxpY0tleUNyZWRlbnRpYWxScEVudGl0eTtcbiAgdXNlcjogUHVibGljS2V5Q3JlZGVudGlhbFVzZXJFbnRpdHk7XG4gIHB1YktleUNyZWRQYXJhbXM6IFB1YmxpY0tleUNyZWRlbnRpYWxQYXJhbWV0ZXJzW107XG4gIHRpbWVvdXQ/OiBudW1iZXI7XG4gIGV4Y2x1ZGVDcmVkZW50aWFscz86IFB1YmxpY0tleUNyZWRlbnRpYWxEZXNjcmlwdG9yW107XG4gIGF1dGhlbnRpY2F0b3JTZWxlY3Rpb24/OiBBdXRoZW50aWNhdG9yU2VsZWN0aW9uQ3JpdGVyaWE7XG4gIGF0dGVzdGF0aW9uPzogQXR0ZXN0YXRpb25Db252ZXlhbmNlUHJlZmVyZW5jZTtcbiAgZXh0ZW5zaW9ucz86IEF1dGhlbnRpY2F0aW9uRXh0ZW5zaW9uc0NsaWVudElucHV0cztcbn1cblxuaW50ZXJmYWNlIE90cERldmljZSB7XG4gIGlkOiBzdHJpbmc7XG4gIGNyZWRlbnRpYWxJZDogc3RyaW5nO1xuICBwcmZTYWx0Pzogc3RyaW5nO1xuICBpc1Bhc3NrZXk/OiBib29sZWFuO1xuICBleHRlbnNpb25zPzogUmVjb3JkPHN0cmluZywgYm9vbGVhbj47XG59XG5cbmludGVyZmFjZSBSZWdpc3Rlck90cFJlc3BvbnNlIHtcbiAgdXNlcjoge1xuICAgIG90cERldmljZXM6IE90cERldmljZVtdO1xuICB9O1xufVxuXG4vKiogRW5jb2RlcyBhbiBBcnJheUJ1ZmZlciBhcyBhIGJhc2U2NHVybCBzdHJpbmcgKG5vIHBhZGRpbmcpLiAqL1xuZnVuY3Rpb24gZW5jb2RlQmFzZTY0VXJsKGJ1ZmZlcjogQXJyYXlCdWZmZXIpOiBzdHJpbmcge1xuICByZXR1cm4gQnVmZmVyLmZyb20oYnVmZmVyKS50b1N0cmluZygnYmFzZTY0JykucmVwbGFjZSgvPS9nLCAnJykucmVwbGFjZSgvXFwrL2csICctJykucmVwbGFjZSgvXFwvL2csICdfJyk7XG59XG5cbi8qKlxuICogUmVjdXJzaXZlbHkgY29udmVydHMgYSBQdWJsaWNLZXlDcmVkZW50aWFsIChvciBhbnkgdmFsdWUgaXQgY29udGFpbnMpIHRvIGFcbiAqIEpTT04tc2VyaWFsaXNhYmxlIHJlcHJlc2VudGF0aW9uLCBlbmNvZGluZyBBcnJheUJ1ZmZlcnMgYXMgYmFzZTY0dXJsIHN0cmluZ3MuXG4gKi9cbmZ1bmN0aW9uIHB1YmxpY0tleUNyZWRlbnRpYWxUb0pTT04odmFsdWU6IHVua25vd24pOiB1bmtub3duIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbHVlLm1hcChwdWJsaWNLZXlDcmVkZW50aWFsVG9KU09OKTtcbiAgfVxuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgIHJldHVybiBlbmNvZGVCYXNlNjRVcmwodmFsdWUpO1xuICB9XG4gIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcodmFsdWUpKSB7XG4gICAgcmV0dXJuIGVuY29kZUJhc2U2NFVybCh2YWx1ZS5idWZmZXIgYXMgQXJyYXlCdWZmZXIpO1xuICB9XG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkge1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgICAvLyBVc2UgZm9yLi4uaW4gdG8gZW51bWVyYXRlIERPTSBvYmplY3QgcHJvcGVydGllcyAobm9uLWVudW1lcmFibGUgb3duICsgaW5oZXJpdGVkKVxuICAgIGZvciAoY29uc3Qga2V5IGluIHZhbHVlKSB7XG4gICAgICByZXN1bHRba2V5XSA9IHB1YmxpY0tleUNyZWRlbnRpYWxUb0pTT04oKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtrZXldKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbi8qKlxuICogRGVjb2RlcyBleGNsdWRlZCBjcmVkZW50aWFsIElEcyBmcm9tIGJhc2U2NCBzdHJpbmdzIHRvIEFycmF5QnVmZmVycy5cbiAqIFRoZSBXZWJBdXRobiBBUEkgcmVxdWlyZXMgQnVmZmVyU291cmNlIHZhbHVlcywgbm90IGJhc2U2NCBzdHJpbmdzLlxuICovXG5mdW5jdGlvbiBwcmVmb3JtYXRFeGNsdWRlZENyZWRlbnRpYWxzKFxuICBleGNsdWRlQ3JlZGVudGlhbHM6IFB1YmxpY0tleUNyZWRlbnRpYWxEZXNjcmlwdG9yW10gfCB1bmRlZmluZWRcbik6IFB1YmxpY0tleUNyZWRlbnRpYWxEZXNjcmlwdG9yW10ge1xuICBpZiAoIWV4Y2x1ZGVDcmVkZW50aWFscykgcmV0dXJuIFtdO1xuICByZXR1cm4gZXhjbHVkZUNyZWRlbnRpYWxzLm1hcCgoY3JlZCkgPT4gKHtcbiAgICAuLi5jcmVkLFxuICAgIGlkOiBCdWZmZXIuZnJvbShjcmVkLmlkIGFzIHVua25vd24gYXMgc3RyaW5nLCAnYmFzZTY0JykgYXMgdW5rbm93biBhcyBBcnJheUJ1ZmZlcixcbiAgfSkpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVnaXN0ZXJQYXNza2V5KHBhcmFtczoge1xuICBiaXRnbzogQml0R29CYXNlO1xuICBwcm92aWRlcjogV2ViQXV0aG5Qcm92aWRlcjtcbiAgbGFiZWw6IHN0cmluZztcbn0pOiBQcm9taXNlPFdlYkF1dGhuT3RwRGV2aWNlICYgeyBwcmZTdXBwb3J0ZWQ6IGJvb2xlYW4gfT4ge1xuICBjb25zdCB7IGJpdGdvLCBwcm92aWRlciwgbGFiZWwgfSA9IHBhcmFtcztcblxuICAvLyBTdGVwIDE6IEZldGNoIHNlcnZlciBjaGFsbGVuZ2UgKGNvbnRhaW5zIGJhc2VTYWx0KVxuICBjb25zdCBjaGFsbGVuZ2UgPSAoYXdhaXQgYml0Z29cbiAgICAuZ2V0KGJpdGdvLnVybCgnL3VzZXIvb3RwL3dlYmF1dGhuL3JlZ2lzdGVyJywgMikpXG4gICAgLnJlc3VsdCgpKSBhcyBSZWdpc3RlckNoYWxsZW5nZVJlc3BvbnNlO1xuXG4gIC8vIFN0ZXAgMjogUGFzcyBmb3JtYXR0ZWQgY2hhbGxlbmdlIHRvIHByb3ZpZGVyLmNyZWF0ZSgpIOKAlCBicm93c2VyIHJldHVybnMgYXR0ZXN0YXRpb25cbiAgY29uc3QgYXR0ZXN0YXRpb24gPSBhd2FpdCBwcm92aWRlci5jcmVhdGUoe1xuICAgIGNoYWxsZW5nZTogQnVmZmVyLmZyb20oY2hhbGxlbmdlLmNoYWxsZW5nZSwgJ2Jhc2U2NCcpLFxuICAgIHJwOiBjaGFsbGVuZ2UucnAsXG4gICAgdXNlcjogY2hhbGxlbmdlLnVzZXIsXG4gICAgcHViS2V5Q3JlZFBhcmFtczogY2hhbGxlbmdlLnB1YktleUNyZWRQYXJhbXMsXG4gICAgdGltZW91dDogY2hhbGxlbmdlLnRpbWVvdXQsXG4gICAgZXhjbHVkZUNyZWRlbnRpYWxzOiBwcmVmb3JtYXRFeGNsdWRlZENyZWRlbnRpYWxzKGNoYWxsZW5nZS5leGNsdWRlQ3JlZGVudGlhbHMpLFxuICAgIGF1dGhlbnRpY2F0b3JTZWxlY3Rpb246IGNoYWxsZW5nZS5hdXRoZW50aWNhdG9yU2VsZWN0aW9uLFxuICAgIGF0dGVzdGF0aW9uOiBjaGFsbGVuZ2UuYXR0ZXN0YXRpb24sXG4gICAgZXh0ZW5zaW9uczogY2hhbGxlbmdlLmV4dGVuc2lvbnMsXG4gIH0pO1xuXG4gIC8vIFN0ZXAgMzogQ2hlY2sgaWYgUFJGIGlzIHN1cHBvcnRlZCDigJQgYHByZi5lbmFibGVkYCBpcyBzZXQgZHVyaW5nIHJlZ2lzdHJhdGlvblxuICAvLyAobm90IGBwcmYucmVzdWx0cy5maXJzdGAsIHdoaWNoIGlzIG9ubHkgcHJlc2VudCBkdXJpbmcgYXV0aGVudGljYXRpb24gYXNzZXJ0aW9ucylcbiAgY29uc3QgY2xpZW50RXh0ZW5zaW9uUmVzdWx0czogQXV0aGVudGljYXRpb25FeHRlbnNpb25zQ2xpZW50T3V0cHV0cyA9IGF0dGVzdGF0aW9uLmdldENsaWVudEV4dGVuc2lvblJlc3VsdHMoKTtcbiAgY29uc3QgcHJmRW5hYmxlZCA9IGNsaWVudEV4dGVuc2lvblJlc3VsdHMucHJmO1xuICBjb25zdCBwcmZTdXBwb3J0ZWQgPSB0eXBlb2YgcHJmRW5hYmxlZCA9PT0gJ29iamVjdCcgJiYgcHJmRW5hYmxlZCAhPT0gbnVsbCAmJiBwcmZFbmFibGVkLmVuYWJsZWQgPT09IHRydWU7XG5cbiAgLy8gU3RlcCA0OiBTZXJpYWxpemUgdGhlIGZ1bGwgY3JlZGVudGlhbCB1c2luZyByZWN1cnNpdmUgYmFzZTY0dXJsIGVuY29kaW5nXG4gIGNvbnN0IG90cCA9IEpTT04uc3RyaW5naWZ5KHB1YmxpY0tleUNyZWRlbnRpYWxUb0pTT04oYXR0ZXN0YXRpb24pKTtcblxuICBjb25zdCBwdXRCb2R5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICBvdHAsXG4gICAgdHlwZTogJ3dlYmF1dGhuJyxcbiAgICBsYWJlbCxcbiAgfTtcblxuICBpZiAocHJmU3VwcG9ydGVkKSB7XG4gICAgcHV0Qm9keS5leHRlbnNpb25zID0gWydwcmYnXTtcbiAgICBwdXRCb2R5LnNjb3BlcyA9IFsnd2FsbGV0X2hvdCddO1xuICB9XG5cbiAgLy8gU3RlcCA1OiBQVVQgL2FwaS92Mi91c2VyL290cFxuICBjb25zdCByZXNwb25zZSA9IChhd2FpdCBiaXRnby5wdXQoYml0Z28udXJsKCcvdXNlci9vdHAnLCAyKSkuc2VuZChwdXRCb2R5KS5yZXN1bHQoKSkgYXMgUmVnaXN0ZXJPdHBSZXNwb25zZTtcblxuICAvLyBTdGVwIDY6IEZpbmQgdGhlIG5ld2x5IHJlZ2lzdGVyZWQgZGV2aWNlIGJ5IG1hdGNoaW5nIGNyZWRlbnRpYWxJZFxuICBjb25zdCBkZXZpY2UgPSByZXNwb25zZS51c2VyLm90cERldmljZXMuZmluZCgoZCkgPT4gZC5jcmVkZW50aWFsSWQgPT09IGF0dGVzdGF0aW9uLmlkKTtcbiAgaWYgKCFkZXZpY2UpIHtcbiAgICBjb25zdCBhdmFpbGFibGUgPSByZXNwb25zZS51c2VyLm90cERldmljZXMubWFwKChkKSA9PiBkLmNyZWRlbnRpYWxJZCkuam9pbignLCAnKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgUmVnaXN0ZXJlZCBkZXZpY2Ugbm90IGZvdW5kIGluIHJlc3BvbnNlIChjcmVkZW50aWFsSWQ6ICR7YXR0ZXN0YXRpb24uaWR9KS4gQXZhaWxhYmxlOiBbJHthdmFpbGFibGV9XWBcbiAgICApO1xuICB9XG5cbiAgLy8gU3RlcCA3OiBSZXR1cm4gV2ViQXV0aG5PdHBEZXZpY2UgKyBwcmZTdXBwb3J0ZWRcbiAgcmV0dXJuIHtcbiAgICBpZDogZGV2aWNlLmlkLFxuICAgIGNyZWRlbnRpYWxJZDogZGV2aWNlLmNyZWRlbnRpYWxJZCxcbiAgICBwcmZTYWx0OiBkZXZpY2UucHJmU2FsdCxcbiAgICBpc1Bhc3NrZXk6IGRldmljZS5pc1Bhc3NrZXksXG4gICAgZXh0ZW5zaW9uczogZGV2aWNlLmV4dGVuc2lvbnMsXG4gICAgcHJmU3VwcG9ydGVkLFxuICB9O1xufVxuIl19
|
|
@@ -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,10 @@
|
|
|
1
|
+
import { BitGoBase } from '@bitgo-beta/sdk-core';
|
|
2
|
+
import { WebAuthnOtpDevice } from './webAuthnTypes';
|
|
3
|
+
export declare function removePasskeyFromWallet(params: {
|
|
4
|
+
bitgo: BitGoBase;
|
|
5
|
+
coin: string;
|
|
6
|
+
walletId: string;
|
|
7
|
+
device: WebAuthnOtpDevice;
|
|
8
|
+
walletPassphrase: string;
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
//# 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,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,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 = (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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3ZlUGFzc2tleUZyb21XYWxsZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVtb3ZlUGFzc2tleUZyb21XYWxsZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFHQSwwREEwQkM7QUE3QkQsbURBQTRFO0FBR3JFLEtBQUssVUFBVSx1QkFBdUIsQ0FBQyxNQU03QztJQUNDLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixFQUFFLEdBQUcsTUFBTSxDQUFDO0lBRTdFLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDZixNQUFNLElBQUksS0FBSyxDQUFDLDJEQUEyRCxDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUVELE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDOUQsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLE1BQU0sUUFBUSxHQUFHLE1BQU0sUUFBUSxDQUFDLFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBRXBFLHdDQUF3QztJQUN4QyxNQUFNLFNBQVMsR0FBRyxJQUFBLG9DQUF5QixFQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUMvRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDZixNQUFNLElBQUksS0FBSyxDQUFDLDBFQUEwRSxDQUFDLENBQUM7SUFDOUYsQ0FBQztJQUVELG9FQUFvRTtJQUNwRSxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLFVBQVUsbUJBQW1CLE1BQU0sQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO0FBQzNGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCaXRHb0Jhc2UsIGRlY3J5cHRLZXljaGFpblByaXZhdGVLZXkgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBXZWJBdXRobk90cERldmljZSB9IGZyb20gJy4vd2ViQXV0aG5UeXBlcyc7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW1vdmVQYXNza2V5RnJvbVdhbGxldChwYXJhbXM6IHtcbiAgYml0Z286IEJpdEdvQmFzZTtcbiAgY29pbjogc3RyaW5nO1xuICB3YWxsZXRJZDogc3RyaW5nO1xuICBkZXZpY2U6IFdlYkF1dGhuT3RwRGV2aWNlO1xuICB3YWxsZXRQYXNzcGhyYXNlOiBzdHJpbmc7XG59KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHsgYml0Z28sIGNvaW46IGNvaW5OYW1lLCB3YWxsZXRJZCwgZGV2aWNlLCB3YWxsZXRQYXNzcGhyYXNlIH0gPSBwYXJhbXM7XG5cbiAgaWYgKCFkZXZpY2UuaWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2RldmljZS5pZCBpcyByZXF1aXJlZCB0byByZW1vdmUgYSBwYXNza2V5IGZyb20gdGhlIHdhbGxldCcpO1xuICB9XG5cbiAgY29uc3QgYmFzZUNvaW4gPSBiaXRnby5jb2luKGNvaW5OYW1lKTtcbiAgY29uc3Qgd2FsbGV0ID0gYXdhaXQgYmFzZUNvaW4ud2FsbGV0cygpLmdldCh7IGlkOiB3YWxsZXRJZCB9KTtcbiAgY29uc3Qga2V5Y2hhaW5JZCA9IHdhbGxldC5rZXlJZHMoKVswXTtcbiAgY29uc3Qga2V5Y2hhaW4gPSBhd2FpdCBiYXNlQ29pbi5rZXljaGFpbnMoKS5nZXQoeyBpZDoga2V5Y2hhaW5JZCB9KTtcblxuICAvLyBWZXJpZnkgcGFzc3BocmFzZSBiZWZvcmUgYW55IG11dGF0aW9uXG4gIGNvbnN0IGRlY3J5cHRlZCA9IGRlY3J5cHRLZXljaGFpblByaXZhdGVLZXkoYml0Z28sIGtleWNoYWluLCB3YWxsZXRQYXNzcGhyYXNlKTtcbiAgaWYgKCFkZWNyeXB0ZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0luY29ycmVjdCB3YWxsZXQgcGFzc3BocmFzZS4gUGFzc2tleSByZW1vdmFsIGFib3J0ZWQgdG8gcHJldmVudCBsb2Nrb3V0LicpO1xuICB9XG5cbiAgLy8gTm8gc2RrLWNvcmUgYWJzdHJhY3Rpb24gZm9yIHRoaXMgZW5kcG9pbnQ7IHJhdyBERUxFVEUgaXMgcmVxdWlyZWRcbiAgYXdhaXQgYml0Z28uZGVsKGJpdGdvLnVybChgL2tleS8ke2tleWNoYWluSWR9L3dlYmF1dGhuZGV2aWNlLyR7ZGV2aWNlLmlkfWAsIDIpKS5yZXN1bHQoKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachPasskeyToWallet.test.d.ts","sourceRoot":"","sources":["../../../test/unit/attachPasskeyToWallet.test.ts"],"names":[],"mappings":""}
|