@bitgo/passkey-crypto 0.0.1 → 0.3.0
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/LICENSE +191 -0
- package/dist/src/attachPasskeyToWallet.d.ts +11 -0
- package/dist/src/attachPasskeyToWallet.d.ts.map +1 -0
- package/dist/src/attachPasskeyToWallet.js +63 -0
- package/dist/src/base64url.d.ts +16 -0
- package/dist/src/base64url.d.ts.map +1 -0
- package/dist/src/base64url.js +27 -0
- package/dist/src/deriveEnterpriseSalt.d.ts +18 -0
- package/dist/src/deriveEnterpriseSalt.d.ts.map +1 -0
- package/dist/src/deriveEnterpriseSalt.js +26 -0
- package/dist/src/derivePasskeyPrfKey.d.ts +15 -0
- package/dist/src/derivePasskeyPrfKey.d.ts.map +1 -0
- package/dist/src/derivePasskeyPrfKey.js +68 -0
- package/dist/src/derivePassword.d.ts +11 -0
- package/dist/src/derivePassword.d.ts.map +1 -0
- package/dist/src/derivePassword.js +16 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +21 -0
- package/dist/src/prfHelpers.d.ts +15 -0
- package/dist/src/prfHelpers.d.ts.map +1 -0
- package/dist/src/prfHelpers.js +47 -0
- package/dist/src/registerPasskey.d.ts +10 -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 +10 -0
- package/dist/src/removePasskeyFromWallet.d.ts.map +1 -0
- package/dist/src/removePasskeyFromWallet.js +22 -0
- package/dist/src/webAuthnTypes.d.ts +18 -0
- package/dist/src/webAuthnTypes.d.ts.map +1 -0
- package/dist/src/webAuthnTypes.js +3 -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 +153 -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/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.d.ts +2 -0
- package/dist/test/unit/deriveEnterpriseSalt.test.d.ts.map +1 -0
- package/dist/test/unit/deriveEnterpriseSalt.test.js +77 -0
- 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/derivePassword.test.d.ts +2 -0
- package/dist/test/unit/derivePassword.test.d.ts.map +1 -0
- package/dist/test/unit/derivePassword.test.js +66 -0
- package/dist/test/unit/prfHelpers.test.d.ts +2 -0
- package/dist/test/unit/prfHelpers.test.d.ts.map +1 -0
- package/dist/test/unit/prfHelpers.test.js +99 -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 -0
- package/package.json +39 -10
|
@@ -0,0 +1,153 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const assert = __importStar(require("assert"));
|
|
37
|
+
const derivePassword_1 = require("../../src/derivePassword");
|
|
38
|
+
const deriveEnterpriseSalt_1 = require("../../src/deriveEnterpriseSalt");
|
|
39
|
+
const registerPasskey_1 = require("../../src/registerPasskey");
|
|
40
|
+
const attachPasskeyToWallet_1 = require("../../src/attachPasskeyToWallet");
|
|
41
|
+
const derivePasskeyPrfKey_1 = require("../../src/derivePasskeyPrfKey");
|
|
42
|
+
const removePasskeyFromWallet_1 = require("../../src/removePasskeyFromWallet");
|
|
43
|
+
const removePasskeyFromAccount_1 = require("../../src/removePasskeyFromAccount");
|
|
44
|
+
const mockBitGo_1 = require("./helpers/mockBitGo");
|
|
45
|
+
const mockProvider_1 = require("./helpers/mockProvider");
|
|
46
|
+
const fixtures_1 = require("./helpers/fixtures");
|
|
47
|
+
// Use sjcl directly for round-trip encryption tests — same crypto as mockBitGo
|
|
48
|
+
const sjcl = require('sjcl');
|
|
49
|
+
const sjclEncrypt = (password, input) => JSON.stringify(sjcl.encrypt(password, input));
|
|
50
|
+
const sjclDecrypt = (password, input) => sjcl.decrypt(password, JSON.parse(input));
|
|
51
|
+
describe('passkey-crypto integration', function () {
|
|
52
|
+
let initialEncryptedPrv;
|
|
53
|
+
const PRIVATE_KEY = 'xprv-test-private-key-12345';
|
|
54
|
+
before(function () {
|
|
55
|
+
// Encrypt the private key with the existing passphrase (simulates what the server stores)
|
|
56
|
+
initialEncryptedPrv = sjclEncrypt(fixtures_1.EXISTING_PASSPHRASE, PRIVATE_KEY);
|
|
57
|
+
});
|
|
58
|
+
describe('register → attach', function () {
|
|
59
|
+
it('re-encrypts the private key under the PRF-derived password', async function () {
|
|
60
|
+
const { bitgo, keychainState } = (0, mockBitGo_1.makeMockBitGo)(initialEncryptedPrv);
|
|
61
|
+
const provider = (0, mockProvider_1.makeMockProvider)();
|
|
62
|
+
const device = await (0, registerPasskey_1.registerPasskey)({ bitgo, provider, label: 'test-key' });
|
|
63
|
+
assert.strictEqual(device.credentialId, fixtures_1.CREDENTIAL_ID);
|
|
64
|
+
assert.strictEqual(device.prfSupported, true);
|
|
65
|
+
await (0, attachPasskeyToWallet_1.attachPasskeyToWallet)({
|
|
66
|
+
bitgo,
|
|
67
|
+
coin: fixtures_1.COIN,
|
|
68
|
+
walletId: fixtures_1.WALLET_ID,
|
|
69
|
+
device,
|
|
70
|
+
existingPassphrase: fixtures_1.EXISTING_PASSPHRASE,
|
|
71
|
+
provider,
|
|
72
|
+
});
|
|
73
|
+
// Verify encryptedPrv round-trips with the PRF-derived password
|
|
74
|
+
const decrypted = sjclDecrypt((0, derivePassword_1.derivePassword)(fixtures_1.PRF_OUTPUT), keychainState.encryptedPrv);
|
|
75
|
+
assert.strictEqual(decrypted, PRIVATE_KEY);
|
|
76
|
+
// prfSalt stored in webauthnInfo must be valid base64url
|
|
77
|
+
assert.ok(keychainState.webauthnDevices);
|
|
78
|
+
assert.match(keychainState.webauthnDevices[0].prfSalt, /^[A-Za-z0-9\-_]+$/);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe('attach → derivePasskeyPrfKey', function () {
|
|
82
|
+
it('derives the same passphrase used to re-encrypt during attach', async function () {
|
|
83
|
+
const { bitgo, keychainState, wallet } = (0, mockBitGo_1.makeMockBitGo)(initialEncryptedPrv);
|
|
84
|
+
const provider = (0, mockProvider_1.makeMockProvider)();
|
|
85
|
+
const device = { id: fixtures_1.DEVICE_MONGO_ID, credentialId: fixtures_1.CREDENTIAL_ID, prfSalt: fixtures_1.BASE_SALT, isPasskey: true };
|
|
86
|
+
await (0, attachPasskeyToWallet_1.attachPasskeyToWallet)({
|
|
87
|
+
bitgo,
|
|
88
|
+
coin: fixtures_1.COIN,
|
|
89
|
+
walletId: fixtures_1.WALLET_ID,
|
|
90
|
+
device,
|
|
91
|
+
existingPassphrase: fixtures_1.EXISTING_PASSPHRASE,
|
|
92
|
+
provider,
|
|
93
|
+
});
|
|
94
|
+
const derivedPassphrase = await (0, derivePasskeyPrfKey_1.derivePasskeyPrfKey)({ bitgo, wallet, provider });
|
|
95
|
+
// Same passphrase as what attach used — decrypts the stored key
|
|
96
|
+
assert.strictEqual(derivedPassphrase, (0, derivePassword_1.derivePassword)(fixtures_1.PRF_OUTPUT));
|
|
97
|
+
assert.strictEqual(sjclDecrypt(derivedPassphrase, keychainState.encryptedPrv), PRIVATE_KEY);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('full lifecycle (register → attach → derive → remove)', function () {
|
|
101
|
+
it('completes all steps and hits both DEL endpoints', async function () {
|
|
102
|
+
const { bitgo, wallet } = (0, mockBitGo_1.makeMockBitGo)(initialEncryptedPrv);
|
|
103
|
+
const provider = (0, mockProvider_1.makeMockProvider)();
|
|
104
|
+
const device = await (0, registerPasskey_1.registerPasskey)({ bitgo, provider, label: 'lifecycle-key' });
|
|
105
|
+
await (0, attachPasskeyToWallet_1.attachPasskeyToWallet)({
|
|
106
|
+
bitgo,
|
|
107
|
+
coin: fixtures_1.COIN,
|
|
108
|
+
walletId: fixtures_1.WALLET_ID,
|
|
109
|
+
device,
|
|
110
|
+
existingPassphrase: fixtures_1.EXISTING_PASSPHRASE,
|
|
111
|
+
provider,
|
|
112
|
+
});
|
|
113
|
+
const passphrase = await (0, derivePasskeyPrfKey_1.derivePasskeyPrfKey)({ bitgo, wallet, provider });
|
|
114
|
+
await (0, removePasskeyFromWallet_1.removePasskeyFromWallet)({ bitgo, coin: fixtures_1.COIN, walletId: fixtures_1.WALLET_ID, device, walletPassphrase: passphrase });
|
|
115
|
+
await (0, removePasskeyFromAccount_1.removePasskeyFromAccount)({ bitgo, device });
|
|
116
|
+
const delUrls = bitgo.del.args.map((a) => a[0]);
|
|
117
|
+
assert.ok(delUrls.some((url) => url.includes(`/key/${fixtures_1.KEYCHAIN_ID}/webauthndevice/${fixtures_1.DEVICE_MONGO_ID}`)));
|
|
118
|
+
assert.ok(delUrls.some((url) => url.includes(`/user/otp/${fixtures_1.DEVICE_MONGO_ID}`)));
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
describe('PRF salt derivation wiring', function () {
|
|
122
|
+
it('passes deriveEnterpriseSalt output as the eval salt in attachPasskeyToWallet', async function () {
|
|
123
|
+
const { bitgo } = (0, mockBitGo_1.makeMockBitGo)(initialEncryptedPrv);
|
|
124
|
+
const provider = (0, mockProvider_1.makeMockProvider)();
|
|
125
|
+
const device = { id: fixtures_1.DEVICE_MONGO_ID, credentialId: fixtures_1.CREDENTIAL_ID, prfSalt: fixtures_1.BASE_SALT, isPasskey: true };
|
|
126
|
+
await (0, attachPasskeyToWallet_1.attachPasskeyToWallet)({
|
|
127
|
+
bitgo,
|
|
128
|
+
coin: fixtures_1.COIN,
|
|
129
|
+
walletId: fixtures_1.WALLET_ID,
|
|
130
|
+
device,
|
|
131
|
+
existingPassphrase: fixtures_1.EXISTING_PASSPHRASE,
|
|
132
|
+
provider,
|
|
133
|
+
});
|
|
134
|
+
assert.strictEqual(provider.lastEvalByCredential?.[fixtures_1.CREDENTIAL_ID], (0, deriveEnterpriseSalt_1.deriveEnterpriseSalt)(fixtures_1.BASE_SALT, fixtures_1.ENTERPRISE_ID));
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
describe('error propagation', function () {
|
|
138
|
+
it('aborts removePasskeyFromWallet and does not DEL when passphrase is wrong', async function () {
|
|
139
|
+
const { bitgo } = (0, mockBitGo_1.makeMockBitGo)(initialEncryptedPrv);
|
|
140
|
+
const device = { id: fixtures_1.DEVICE_MONGO_ID, credentialId: fixtures_1.CREDENTIAL_ID, prfSalt: fixtures_1.BASE_SALT, isPasskey: true };
|
|
141
|
+
// Uses real sjcl decrypt — wrong passphrase genuinely fails decryptKeychainPrivateKey
|
|
142
|
+
await assert.rejects(() => (0, removePasskeyFromWallet_1.removePasskeyFromWallet)({
|
|
143
|
+
bitgo,
|
|
144
|
+
coin: fixtures_1.COIN,
|
|
145
|
+
walletId: fixtures_1.WALLET_ID,
|
|
146
|
+
device,
|
|
147
|
+
walletPassphrase: 'wrong-passphrase',
|
|
148
|
+
}), /Incorrect wallet passphrase/);
|
|
149
|
+
assert.strictEqual(bitgo.del.callCount, 0);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFzc2tleUxpZmVjeWNsZS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC9pbnRlZ3JhdGlvbi9wYXNza2V5TGlmZWN5Y2xlLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBaUM7QUFDakMsNkRBQTBEO0FBQzFELHlFQUFzRTtBQUN0RSwrREFBNEQ7QUFDNUQsMkVBQXdFO0FBQ3hFLHVFQUFvRTtBQUNwRSwrRUFBNEU7QUFDNUUsaUZBQThFO0FBQzlFLG1EQUFvRDtBQUNwRCx5REFBMEQ7QUFDMUQsaURBVTRCO0FBRTVCLCtFQUErRTtBQUMvRSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDN0IsTUFBTSxXQUFXLEdBQUcsQ0FBQyxRQUFnQixFQUFFLEtBQWEsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ3ZHLE1BQU0sV0FBVyxHQUFHLENBQUMsUUFBZ0IsRUFBRSxLQUFhLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUVuRyxRQUFRLENBQUMsNEJBQTRCLEVBQUU7SUFDckMsSUFBSSxtQkFBMkIsQ0FBQztJQUNoQyxNQUFNLFdBQVcsR0FBRyw2QkFBNkIsQ0FBQztJQUVsRCxNQUFNLENBQUM7UUFDTCwwRkFBMEY7UUFDMUYsbUJBQW1CLEdBQUcsV0FBVyxDQUFDLDhCQUFtQixFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3RFLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLG1CQUFtQixFQUFFO1FBQzVCLEVBQUUsQ0FBQyw0REFBNEQsRUFBRSxLQUFLO1lBQ3BFLE1BQU0sRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLEdBQUcsSUFBQSx5QkFBYSxFQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDcEUsTUFBTSxRQUFRLEdBQUcsSUFBQSwrQkFBZ0IsR0FBRSxDQUFDO1lBRXBDLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBQSxpQ0FBZSxFQUFDLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztZQUM3RSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsd0JBQWEsQ0FBQyxDQUFDO1lBQ3ZELE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsQ0FBQztZQUU5QyxNQUFNLElBQUEsNkNBQXFCLEVBQUM7Z0JBQzFCLEtBQUs7Z0JBQ0wsSUFBSSxFQUFFLGVBQUk7Z0JBQ1YsUUFBUSxFQUFFLG9CQUFTO2dCQUNuQixNQUFNO2dCQUNOLGtCQUFrQixFQUFFLDhCQUFtQjtnQkFDdkMsUUFBUTthQUNULENBQUMsQ0FBQztZQUVILGdFQUFnRTtZQUNoRSxNQUFNLFNBQVMsR0FBRyxXQUFXLENBQUMsSUFBQSwrQkFBYyxFQUFDLHFCQUFVLENBQUMsRUFBRSxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdEYsTUFBTSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFFM0MseURBQXlEO1lBQ3pELE1BQU0sQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ3pDLE1BQU0sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztRQUM5RSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLDhCQUE4QixFQUFFO1FBQ3ZDLEVBQUUsQ0FBQyw4REFBOEQsRUFBRSxLQUFLO1lBQ3RFLE1BQU0sRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxHQUFHLElBQUEseUJBQWEsRUFBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQzVFLE1BQU0sUUFBUSxHQUFHLElBQUEsK0JBQWdCLEdBQUUsQ0FBQztZQUVwQyxNQUFNLE1BQU0sR0FBRyxFQUFFLEVBQUUsRUFBRSwwQkFBZSxFQUFFLFlBQVksRUFBRSx3QkFBYSxFQUFFLE9BQU8sRUFBRSxvQkFBUyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUN6RyxNQUFNLElBQUEsNkNBQXFCLEVBQUM7Z0JBQzFCLEtBQUs7Z0JBQ0wsSUFBSSxFQUFFLGVBQUk7Z0JBQ1YsUUFBUSxFQUFFLG9CQUFTO2dCQUNuQixNQUFNO2dCQUNOLGtCQUFrQixFQUFFLDhCQUFtQjtnQkFDdkMsUUFBUTthQUNULENBQUMsQ0FBQztZQUVILE1BQU0saUJBQWlCLEdBQUcsTUFBTSxJQUFBLHlDQUFtQixFQUFDLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBRWpGLGdFQUFnRTtZQUNoRSxNQUFNLENBQUMsV0FBVyxDQUFDLGlCQUFpQixFQUFFLElBQUEsK0JBQWMsRUFBQyxxQkFBVSxDQUFDLENBQUMsQ0FBQztZQUNsRSxNQUFNLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsRUFBRSxhQUFhLENBQUMsWUFBWSxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDOUYsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxzREFBc0QsRUFBRTtRQUMvRCxFQUFFLENBQUMsaURBQWlELEVBQUUsS0FBSztZQUN6RCxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLElBQUEseUJBQWEsRUFBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQzdELE1BQU0sUUFBUSxHQUFHLElBQUEsK0JBQWdCLEdBQUUsQ0FBQztZQUVwQyxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEsaUNBQWUsRUFBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUM7WUFDbEYsTUFBTSxJQUFBLDZDQUFxQixFQUFDO2dCQUMxQixLQUFLO2dCQUNMLElBQUksRUFBRSxlQUFJO2dCQUNWLFFBQVEsRUFBRSxvQkFBUztnQkFDbkIsTUFBTTtnQkFDTixrQkFBa0IsRUFBRSw4QkFBbUI7Z0JBQ3ZDLFFBQVE7YUFDVCxDQUFDLENBQUM7WUFFSCxNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUEseUNBQW1CLEVBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDMUUsTUFBTSxJQUFBLGlEQUF1QixFQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxlQUFJLEVBQUUsUUFBUSxFQUFFLG9CQUFTLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7WUFDaEgsTUFBTSxJQUFBLG1EQUF3QixFQUFDLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFFbEQsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMxRCxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsUUFBUSxzQkFBVyxtQkFBbUIsMEJBQWUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hILE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxhQUFhLDBCQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN6RixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLDRCQUE0QixFQUFFO1FBQ3JDLEVBQUUsQ0FBQyw4RUFBOEUsRUFBRSxLQUFLO1lBQ3RGLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFBLHlCQUFhLEVBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUNyRCxNQUFNLFFBQVEsR0FBRyxJQUFBLCtCQUFnQixHQUFFLENBQUM7WUFFcEMsTUFBTSxNQUFNLEdBQUcsRUFBRSxFQUFFLEVBQUUsMEJBQWUsRUFBRSxZQUFZLEVBQUUsd0JBQWEsRUFBRSxPQUFPLEVBQUUsb0JBQVMsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUM7WUFDekcsTUFBTSxJQUFBLDZDQUFxQixFQUFDO2dCQUMxQixLQUFLO2dCQUNMLElBQUksRUFBRSxlQUFJO2dCQUNWLFFBQVEsRUFBRSxvQkFBUztnQkFDbkIsTUFBTTtnQkFDTixrQkFBa0IsRUFBRSw4QkFBbUI7Z0JBQ3ZDLFFBQVE7YUFDVCxDQUFDLENBQUM7WUFFSCxNQUFNLENBQUMsV0FBVyxDQUNoQixRQUFRLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyx3QkFBYSxDQUFDLEVBQzlDLElBQUEsMkNBQW9CLEVBQUMsb0JBQVMsRUFBRSx3QkFBYSxDQUFDLENBQy9DLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLG1CQUFtQixFQUFFO1FBQzVCLEVBQUUsQ0FBQywwRUFBMEUsRUFBRSxLQUFLO1lBQ2xGLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFBLHlCQUFhLEVBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUNyRCxNQUFNLE1BQU0sR0FBRyxFQUFFLEVBQUUsRUFBRSwwQkFBZSxFQUFFLFlBQVksRUFBRSx3QkFBYSxFQUFFLE9BQU8sRUFBRSxvQkFBUyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUV6RyxzRkFBc0Y7WUFDdEYsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUNsQixHQUFHLEVBQUUsQ0FDSCxJQUFBLGlEQUF1QixFQUFDO2dCQUN0QixLQUFLO2dCQUNMLElBQUksRUFBRSxlQUFJO2dCQUNWLFFBQVEsRUFBRSxvQkFBUztnQkFDbkIsTUFBTTtnQkFDTixnQkFBZ0IsRUFBRSxrQkFBa0I7YUFDckMsQ0FBQyxFQUNKLDZCQUE2QixDQUM5QixDQUFDO1lBRUYsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM3QyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGRlcml2ZVBhc3N3b3JkIH0gZnJvbSAnLi4vLi4vc3JjL2Rlcml2ZVBhc3N3b3JkJztcbmltcG9ydCB7IGRlcml2ZUVudGVycHJpc2VTYWx0IH0gZnJvbSAnLi4vLi4vc3JjL2Rlcml2ZUVudGVycHJpc2VTYWx0JztcbmltcG9ydCB7IHJlZ2lzdGVyUGFzc2tleSB9IGZyb20gJy4uLy4uL3NyYy9yZWdpc3RlclBhc3NrZXknO1xuaW1wb3J0IHsgYXR0YWNoUGFzc2tleVRvV2FsbGV0IH0gZnJvbSAnLi4vLi4vc3JjL2F0dGFjaFBhc3NrZXlUb1dhbGxldCc7XG5pbXBvcnQgeyBkZXJpdmVQYXNza2V5UHJmS2V5IH0gZnJvbSAnLi4vLi4vc3JjL2Rlcml2ZVBhc3NrZXlQcmZLZXknO1xuaW1wb3J0IHsgcmVtb3ZlUGFzc2tleUZyb21XYWxsZXQgfSBmcm9tICcuLi8uLi9zcmMvcmVtb3ZlUGFzc2tleUZyb21XYWxsZXQnO1xuaW1wb3J0IHsgcmVtb3ZlUGFzc2tleUZyb21BY2NvdW50IH0gZnJvbSAnLi4vLi4vc3JjL3JlbW92ZVBhc3NrZXlGcm9tQWNjb3VudCc7XG5pbXBvcnQgeyBtYWtlTW9ja0JpdEdvIH0gZnJvbSAnLi9oZWxwZXJzL21vY2tCaXRHbyc7XG5pbXBvcnQgeyBtYWtlTW9ja1Byb3ZpZGVyIH0gZnJvbSAnLi9oZWxwZXJzL21vY2tQcm92aWRlcic7XG5pbXBvcnQge1xuICBFTlRFUlBSSVNFX0lELFxuICBXQUxMRVRfSUQsXG4gIENPSU4sXG4gIEVYSVNUSU5HX1BBU1NQSFJBU0UsXG4gIFBSRl9PVVRQVVQsXG4gIENSRURFTlRJQUxfSUQsXG4gIERFVklDRV9NT05HT19JRCxcbiAgQkFTRV9TQUxULFxuICBLRVlDSEFJTl9JRCxcbn0gZnJvbSAnLi9oZWxwZXJzL2ZpeHR1cmVzJztcblxuLy8gVXNlIHNqY2wgZGlyZWN0bHkgZm9yIHJvdW5kLXRyaXAgZW5jcnlwdGlvbiB0ZXN0cyDigJQgc2FtZSBjcnlwdG8gYXMgbW9ja0JpdEdvXG5jb25zdCBzamNsID0gcmVxdWlyZSgnc2pjbCcpO1xuY29uc3Qgc2pjbEVuY3J5cHQgPSAocGFzc3dvcmQ6IHN0cmluZywgaW5wdXQ6IHN0cmluZykgPT4gSlNPTi5zdHJpbmdpZnkoc2pjbC5lbmNyeXB0KHBhc3N3b3JkLCBpbnB1dCkpO1xuY29uc3Qgc2pjbERlY3J5cHQgPSAocGFzc3dvcmQ6IHN0cmluZywgaW5wdXQ6IHN0cmluZykgPT4gc2pjbC5kZWNyeXB0KHBhc3N3b3JkLCBKU09OLnBhcnNlKGlucHV0KSk7XG5cbmRlc2NyaWJlKCdwYXNza2V5LWNyeXB0byBpbnRlZ3JhdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgbGV0IGluaXRpYWxFbmNyeXB0ZWRQcnY6IHN0cmluZztcbiAgY29uc3QgUFJJVkFURV9LRVkgPSAneHBydi10ZXN0LXByaXZhdGUta2V5LTEyMzQ1JztcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIC8vIEVuY3J5cHQgdGhlIHByaXZhdGUga2V5IHdpdGggdGhlIGV4aXN0aW5nIHBhc3NwaHJhc2UgKHNpbXVsYXRlcyB3aGF0IHRoZSBzZXJ2ZXIgc3RvcmVzKVxuICAgIGluaXRpYWxFbmNyeXB0ZWRQcnYgPSBzamNsRW5jcnlwdChFWElTVElOR19QQVNTUEhSQVNFLCBQUklWQVRFX0tFWSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdyZWdpc3RlciDihpIgYXR0YWNoJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdyZS1lbmNyeXB0cyB0aGUgcHJpdmF0ZSBrZXkgdW5kZXIgdGhlIFBSRi1kZXJpdmVkIHBhc3N3b3JkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgeyBiaXRnbywga2V5Y2hhaW5TdGF0ZSB9ID0gbWFrZU1vY2tCaXRHbyhpbml0aWFsRW5jcnlwdGVkUHJ2KTtcbiAgICAgIGNvbnN0IHByb3ZpZGVyID0gbWFrZU1vY2tQcm92aWRlcigpO1xuXG4gICAgICBjb25zdCBkZXZpY2UgPSBhd2FpdCByZWdpc3RlclBhc3NrZXkoeyBiaXRnbywgcHJvdmlkZXIsIGxhYmVsOiAndGVzdC1rZXknIH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGRldmljZS5jcmVkZW50aWFsSWQsIENSRURFTlRJQUxfSUQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGRldmljZS5wcmZTdXBwb3J0ZWQsIHRydWUpO1xuXG4gICAgICBhd2FpdCBhdHRhY2hQYXNza2V5VG9XYWxsZXQoe1xuICAgICAgICBiaXRnbyxcbiAgICAgICAgY29pbjogQ09JTixcbiAgICAgICAgd2FsbGV0SWQ6IFdBTExFVF9JRCxcbiAgICAgICAgZGV2aWNlLFxuICAgICAgICBleGlzdGluZ1Bhc3NwaHJhc2U6IEVYSVNUSU5HX1BBU1NQSFJBU0UsXG4gICAgICAgIHByb3ZpZGVyLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFZlcmlmeSBlbmNyeXB0ZWRQcnYgcm91bmQtdHJpcHMgd2l0aCB0aGUgUFJGLWRlcml2ZWQgcGFzc3dvcmRcbiAgICAgIGNvbnN0IGRlY3J5cHRlZCA9IHNqY2xEZWNyeXB0KGRlcml2ZVBhc3N3b3JkKFBSRl9PVVRQVVQpLCBrZXljaGFpblN0YXRlLmVuY3J5cHRlZFBydik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZGVjcnlwdGVkLCBQUklWQVRFX0tFWSk7XG5cbiAgICAgIC8vIHByZlNhbHQgc3RvcmVkIGluIHdlYmF1dGhuSW5mbyBtdXN0IGJlIHZhbGlkIGJhc2U2NHVybFxuICAgICAgYXNzZXJ0Lm9rKGtleWNoYWluU3RhdGUud2ViYXV0aG5EZXZpY2VzKTtcbiAgICAgIGFzc2VydC5tYXRjaChrZXljaGFpblN0YXRlLndlYmF1dGhuRGV2aWNlc1swXS5wcmZTYWx0LCAvXltBLVphLXowLTlcXC1fXSskLyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdhdHRhY2gg4oaSIGRlcml2ZVBhc3NrZXlQcmZLZXknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ2Rlcml2ZXMgdGhlIHNhbWUgcGFzc3BocmFzZSB1c2VkIHRvIHJlLWVuY3J5cHQgZHVyaW5nIGF0dGFjaCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHsgYml0Z28sIGtleWNoYWluU3RhdGUsIHdhbGxldCB9ID0gbWFrZU1vY2tCaXRHbyhpbml0aWFsRW5jcnlwdGVkUHJ2KTtcbiAgICAgIGNvbnN0IHByb3ZpZGVyID0gbWFrZU1vY2tQcm92aWRlcigpO1xuXG4gICAgICBjb25zdCBkZXZpY2UgPSB7IGlkOiBERVZJQ0VfTU9OR09fSUQsIGNyZWRlbnRpYWxJZDogQ1JFREVOVElBTF9JRCwgcHJmU2FsdDogQkFTRV9TQUxULCBpc1Bhc3NrZXk6IHRydWUgfTtcbiAgICAgIGF3YWl0IGF0dGFjaFBhc3NrZXlUb1dhbGxldCh7XG4gICAgICAgIGJpdGdvLFxuICAgICAgICBjb2luOiBDT0lOLFxuICAgICAgICB3YWxsZXRJZDogV0FMTEVUX0lELFxuICAgICAgICBkZXZpY2UsXG4gICAgICAgIGV4aXN0aW5nUGFzc3BocmFzZTogRVhJU1RJTkdfUEFTU1BIUkFTRSxcbiAgICAgICAgcHJvdmlkZXIsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZGVyaXZlZFBhc3NwaHJhc2UgPSBhd2FpdCBkZXJpdmVQYXNza2V5UHJmS2V5KHsgYml0Z28sIHdhbGxldCwgcHJvdmlkZXIgfSk7XG5cbiAgICAgIC8vIFNhbWUgcGFzc3BocmFzZSBhcyB3aGF0IGF0dGFjaCB1c2VkIOKAlCBkZWNyeXB0cyB0aGUgc3RvcmVkIGtleVxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGRlcml2ZWRQYXNzcGhyYXNlLCBkZXJpdmVQYXNzd29yZChQUkZfT1VUUFVUKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2pjbERlY3J5cHQoZGVyaXZlZFBhc3NwaHJhc2UsIGtleWNoYWluU3RhdGUuZW5jcnlwdGVkUHJ2KSwgUFJJVkFURV9LRVkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZnVsbCBsaWZlY3ljbGUgKHJlZ2lzdGVyIOKGkiBhdHRhY2gg4oaSIGRlcml2ZSDihpIgcmVtb3ZlKScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnY29tcGxldGVzIGFsbCBzdGVwcyBhbmQgaGl0cyBib3RoIERFTCBlbmRwb2ludHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB7IGJpdGdvLCB3YWxsZXQgfSA9IG1ha2VNb2NrQml0R28oaW5pdGlhbEVuY3J5cHRlZFBydik7XG4gICAgICBjb25zdCBwcm92aWRlciA9IG1ha2VNb2NrUHJvdmlkZXIoKTtcblxuICAgICAgY29uc3QgZGV2aWNlID0gYXdhaXQgcmVnaXN0ZXJQYXNza2V5KHsgYml0Z28sIHByb3ZpZGVyLCBsYWJlbDogJ2xpZmVjeWNsZS1rZXknIH0pO1xuICAgICAgYXdhaXQgYXR0YWNoUGFzc2tleVRvV2FsbGV0KHtcbiAgICAgICAgYml0Z28sXG4gICAgICAgIGNvaW46IENPSU4sXG4gICAgICAgIHdhbGxldElkOiBXQUxMRVRfSUQsXG4gICAgICAgIGRldmljZSxcbiAgICAgICAgZXhpc3RpbmdQYXNzcGhyYXNlOiBFWElTVElOR19QQVNTUEhSQVNFLFxuICAgICAgICBwcm92aWRlcixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBwYXNzcGhyYXNlID0gYXdhaXQgZGVyaXZlUGFzc2tleVByZktleSh7IGJpdGdvLCB3YWxsZXQsIHByb3ZpZGVyIH0pO1xuICAgICAgYXdhaXQgcmVtb3ZlUGFzc2tleUZyb21XYWxsZXQoeyBiaXRnbywgY29pbjogQ09JTiwgd2FsbGV0SWQ6IFdBTExFVF9JRCwgZGV2aWNlLCB3YWxsZXRQYXNzcGhyYXNlOiBwYXNzcGhyYXNlIH0pO1xuICAgICAgYXdhaXQgcmVtb3ZlUGFzc2tleUZyb21BY2NvdW50KHsgYml0Z28sIGRldmljZSB9KTtcblxuICAgICAgY29uc3QgZGVsVXJscyA9IGJpdGdvLmRlbC5hcmdzLm1hcCgoYTogc3RyaW5nW10pID0+IGFbMF0pO1xuICAgICAgYXNzZXJ0Lm9rKGRlbFVybHMuc29tZSgodXJsOiBzdHJpbmcpID0+IHVybC5pbmNsdWRlcyhgL2tleS8ke0tFWUNIQUlOX0lEfS93ZWJhdXRobmRldmljZS8ke0RFVklDRV9NT05HT19JRH1gKSkpO1xuICAgICAgYXNzZXJ0Lm9rKGRlbFVybHMuc29tZSgodXJsOiBzdHJpbmcpID0+IHVybC5pbmNsdWRlcyhgL3VzZXIvb3RwLyR7REVWSUNFX01PTkdPX0lEfWApKSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdQUkYgc2FsdCBkZXJpdmF0aW9uIHdpcmluZycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgncGFzc2VzIGRlcml2ZUVudGVycHJpc2VTYWx0IG91dHB1dCBhcyB0aGUgZXZhbCBzYWx0IGluIGF0dGFjaFBhc3NrZXlUb1dhbGxldCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHsgYml0Z28gfSA9IG1ha2VNb2NrQml0R28oaW5pdGlhbEVuY3J5cHRlZFBydik7XG4gICAgICBjb25zdCBwcm92aWRlciA9IG1ha2VNb2NrUHJvdmlkZXIoKTtcblxuICAgICAgY29uc3QgZGV2aWNlID0geyBpZDogREVWSUNFX01PTkdPX0lELCBjcmVkZW50aWFsSWQ6IENSRURFTlRJQUxfSUQsIHByZlNhbHQ6IEJBU0VfU0FMVCwgaXNQYXNza2V5OiB0cnVlIH07XG4gICAgICBhd2FpdCBhdHRhY2hQYXNza2V5VG9XYWxsZXQoe1xuICAgICAgICBiaXRnbyxcbiAgICAgICAgY29pbjogQ09JTixcbiAgICAgICAgd2FsbGV0SWQ6IFdBTExFVF9JRCxcbiAgICAgICAgZGV2aWNlLFxuICAgICAgICBleGlzdGluZ1Bhc3NwaHJhc2U6IEVYSVNUSU5HX1BBU1NQSFJBU0UsXG4gICAgICAgIHByb3ZpZGVyLFxuICAgICAgfSk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgcHJvdmlkZXIubGFzdEV2YWxCeUNyZWRlbnRpYWw/LltDUkVERU5USUFMX0lEXSxcbiAgICAgICAgZGVyaXZlRW50ZXJwcmlzZVNhbHQoQkFTRV9TQUxULCBFTlRFUlBSSVNFX0lEKVxuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2Vycm9yIHByb3BhZ2F0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdhYm9ydHMgcmVtb3ZlUGFzc2tleUZyb21XYWxsZXQgYW5kIGRvZXMgbm90IERFTCB3aGVuIHBhc3NwaHJhc2UgaXMgd3JvbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB7IGJpdGdvIH0gPSBtYWtlTW9ja0JpdEdvKGluaXRpYWxFbmNyeXB0ZWRQcnYpO1xuICAgICAgY29uc3QgZGV2aWNlID0geyBpZDogREVWSUNFX01PTkdPX0lELCBjcmVkZW50aWFsSWQ6IENSRURFTlRJQUxfSUQsIHByZlNhbHQ6IEJBU0VfU0FMVCwgaXNQYXNza2V5OiB0cnVlIH07XG5cbiAgICAgIC8vIFVzZXMgcmVhbCBzamNsIGRlY3J5cHQg4oCUIHdyb25nIHBhc3NwaHJhc2UgZ2VudWluZWx5IGZhaWxzIGRlY3J5cHRLZXljaGFpblByaXZhdGVLZXlcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgIHJlbW92ZVBhc3NrZXlGcm9tV2FsbGV0KHtcbiAgICAgICAgICAgIGJpdGdvLFxuICAgICAgICAgICAgY29pbjogQ09JTixcbiAgICAgICAgICAgIHdhbGxldElkOiBXQUxMRVRfSUQsXG4gICAgICAgICAgICBkZXZpY2UsXG4gICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnd3JvbmctcGFzc3BocmFzZScsXG4gICAgICAgICAgfSksXG4gICAgICAgIC9JbmNvcnJlY3Qgd2FsbGV0IHBhc3NwaHJhc2UvXG4gICAgICApO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYml0Z28uZGVsLmNhbGxDb3VudCwgMCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachPasskeyToWallet.test.d.ts","sourceRoot":"","sources":["../../../test/unit/attachPasskeyToWallet.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,205 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const assert = __importStar(require("assert"));
|
|
37
|
+
const sinon = __importStar(require("sinon"));
|
|
38
|
+
const attachPasskeyToWallet_1 = require("../../src/attachPasskeyToWallet");
|
|
39
|
+
describe('attachPasskeyToWallet', function () {
|
|
40
|
+
const coin = 'tbtc';
|
|
41
|
+
const walletId = 'wallet-abc123';
|
|
42
|
+
const keychainId = 'key-user-id';
|
|
43
|
+
const enterpriseId = 'enterprise-xyz';
|
|
44
|
+
const encryptedPrv = 'encrypted-prv-string';
|
|
45
|
+
const decryptedPrv = 'xprv-decrypted';
|
|
46
|
+
const existingPassphrase = 'correct-passphrase';
|
|
47
|
+
const reEncryptedPrv = 're-encrypted-prv';
|
|
48
|
+
const prfResultBuffer = new Uint8Array([0x1e, 0x5c, 0xb4, 0x78]).buffer;
|
|
49
|
+
const device = {
|
|
50
|
+
id: 'mongo-object-id-123',
|
|
51
|
+
credentialId: 'cred-id-456',
|
|
52
|
+
prfSalt: 'ZqJ64M2dL65zn2-Jxd58SMN2ILc9QjbCFxUTGHd_LC8',
|
|
53
|
+
isPasskey: true,
|
|
54
|
+
};
|
|
55
|
+
const mockAuthResult = {
|
|
56
|
+
prfResult: prfResultBuffer,
|
|
57
|
+
credentialId: 'cred-id-456',
|
|
58
|
+
otpCode: '123456',
|
|
59
|
+
};
|
|
60
|
+
const updatedKeychain = {
|
|
61
|
+
id: keychainId,
|
|
62
|
+
pub: 'xpub-123',
|
|
63
|
+
type: 'independent',
|
|
64
|
+
encryptedPrv,
|
|
65
|
+
};
|
|
66
|
+
let mockWallet;
|
|
67
|
+
let mockWallets;
|
|
68
|
+
let mockBaseCoin;
|
|
69
|
+
let mockBitGo;
|
|
70
|
+
let mockProvider;
|
|
71
|
+
beforeEach(function () {
|
|
72
|
+
mockWallet = {
|
|
73
|
+
type: sinon.stub().returns('hot'),
|
|
74
|
+
toJSON: sinon.stub().returns({ enterprise: enterpriseId }),
|
|
75
|
+
getEncryptedUserKeychain: sinon.stub().resolves({ id: keychainId, encryptedPrv }),
|
|
76
|
+
};
|
|
77
|
+
mockWallets = {
|
|
78
|
+
get: sinon.stub().resolves(mockWallet),
|
|
79
|
+
};
|
|
80
|
+
mockBaseCoin = {
|
|
81
|
+
wallets: sinon.stub().returns(mockWallets),
|
|
82
|
+
};
|
|
83
|
+
mockBitGo = {
|
|
84
|
+
url: sinon
|
|
85
|
+
.stub()
|
|
86
|
+
.callsFake((path, version) => `/api/v${version ?? 1}${path}`),
|
|
87
|
+
coin: sinon.stub().returns(mockBaseCoin),
|
|
88
|
+
put: sinon.stub(),
|
|
89
|
+
decrypt: sinon.stub(),
|
|
90
|
+
encrypt: sinon.stub(),
|
|
91
|
+
};
|
|
92
|
+
mockProvider = {
|
|
93
|
+
create: sinon.stub(),
|
|
94
|
+
get: sinon.stub(),
|
|
95
|
+
};
|
|
96
|
+
mockBitGo.decrypt.returns(decryptedPrv);
|
|
97
|
+
mockBitGo.encrypt.returns(reEncryptedPrv);
|
|
98
|
+
const putSendStub = sinon.stub().returns({ result: sinon.stub().resolves(updatedKeychain) });
|
|
99
|
+
mockBitGo.put.returns({ send: putSendStub });
|
|
100
|
+
mockProvider.get.resolves(mockAuthResult);
|
|
101
|
+
});
|
|
102
|
+
afterEach(function () {
|
|
103
|
+
sinon.restore();
|
|
104
|
+
});
|
|
105
|
+
async function callAttach(overrides) {
|
|
106
|
+
return (0, attachPasskeyToWallet_1.attachPasskeyToWallet)({
|
|
107
|
+
bitgo: mockBitGo,
|
|
108
|
+
coin,
|
|
109
|
+
walletId,
|
|
110
|
+
device,
|
|
111
|
+
existingPassphrase,
|
|
112
|
+
provider: mockProvider,
|
|
113
|
+
...overrides,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
it('should attach a passkey and return the updated keychain', async function () {
|
|
117
|
+
const result = await callAttach();
|
|
118
|
+
sinon.assert.calledWith(mockBitGo.coin, coin);
|
|
119
|
+
sinon.assert.calledWith(mockWallets.get, { id: walletId });
|
|
120
|
+
sinon.assert.calledOnce(mockWallet.type);
|
|
121
|
+
sinon.assert.calledOnce(mockWallet.getEncryptedUserKeychain);
|
|
122
|
+
sinon.assert.calledOnce(mockBitGo.decrypt);
|
|
123
|
+
sinon.assert.calledWithExactly(mockBitGo.decrypt, { password: existingPassphrase, input: encryptedPrv });
|
|
124
|
+
// provider.get called with evalByCredential keyed on device.credentialId
|
|
125
|
+
sinon.assert.calledOnce(mockProvider.get);
|
|
126
|
+
const getArgs = mockProvider.get.firstCall.args[0];
|
|
127
|
+
assert.ok(getArgs.evalByCredential);
|
|
128
|
+
assert.strictEqual(typeof getArgs.evalByCredential[device.credentialId], 'string');
|
|
129
|
+
// allowCredentials must be populated with the credential ID as an ArrayBuffer
|
|
130
|
+
assert.ok(Array.isArray(getArgs.publicKey.allowCredentials));
|
|
131
|
+
assert.strictEqual(getArgs.publicKey.allowCredentials.length, 1);
|
|
132
|
+
assert.strictEqual(getArgs.publicKey.allowCredentials[0].type, 'public-key');
|
|
133
|
+
assert.ok(getArgs.publicKey.allowCredentials[0].id instanceof ArrayBuffer);
|
|
134
|
+
// PUT called with correct shape
|
|
135
|
+
sinon.assert.calledOnce(mockBitGo.put);
|
|
136
|
+
sinon.assert.calledWith(mockBitGo.put, `/api/v2/${coin}/key/${keychainId}`);
|
|
137
|
+
const sendStub = mockBitGo.put.firstCall.returnValue.send;
|
|
138
|
+
sinon.assert.calledOnce(sendStub);
|
|
139
|
+
const putBody = sendStub.firstCall.args[0];
|
|
140
|
+
assert.ok(putBody.webauthnInfo);
|
|
141
|
+
assert.strictEqual(putBody.webauthnInfo.otpDeviceId, device.id);
|
|
142
|
+
// prfSalt must be base64url (URL-safe, no padding) as required by server validation
|
|
143
|
+
assert.match(putBody.webauthnInfo.prfSalt, /^[A-Za-z0-9\-_]+$/);
|
|
144
|
+
assert.strictEqual(typeof putBody.webauthnInfo.encryptedPrv, 'string');
|
|
145
|
+
assert.strictEqual(result.id, keychainId);
|
|
146
|
+
});
|
|
147
|
+
it('should decode credentialId containing base64url-specific characters (- and _)', async function () {
|
|
148
|
+
const deviceWithUrlChars = {
|
|
149
|
+
...device,
|
|
150
|
+
credentialId: 'abc-def_ghi+jkl',
|
|
151
|
+
};
|
|
152
|
+
const result = await callAttach({ device: deviceWithUrlChars });
|
|
153
|
+
assert.ok(result);
|
|
154
|
+
const getArgs = mockProvider.get.firstCall.args[0];
|
|
155
|
+
assert.ok(getArgs.publicKey.allowCredentials[0].id instanceof ArrayBuffer);
|
|
156
|
+
});
|
|
157
|
+
it('should throw if device.prfSalt is undefined', async function () {
|
|
158
|
+
const deviceNoPrf = { ...device, prfSalt: undefined };
|
|
159
|
+
await assert.rejects(() => callAttach({ device: deviceNoPrf }), (err) => {
|
|
160
|
+
assert.strictEqual(err.message, 'PRF extension not supported by this device. Please use a different passkey.');
|
|
161
|
+
return true;
|
|
162
|
+
});
|
|
163
|
+
sinon.assert.notCalled(mockBitGo.coin);
|
|
164
|
+
sinon.assert.notCalled(mockBitGo.put);
|
|
165
|
+
});
|
|
166
|
+
it('should throw if wallet is not a hot wallet', async function () {
|
|
167
|
+
mockWallet.type.returns('cold');
|
|
168
|
+
await assert.rejects(() => callAttach(), (err) => {
|
|
169
|
+
assert.ok(err.message.includes('not a hot wallet'));
|
|
170
|
+
return true;
|
|
171
|
+
});
|
|
172
|
+
sinon.assert.notCalled(mockBitGo.put);
|
|
173
|
+
});
|
|
174
|
+
it('should throw if wallet has no enterprise', async function () {
|
|
175
|
+
mockWallet.toJSON.returns({ enterprise: undefined });
|
|
176
|
+
await assert.rejects(() => callAttach(), (err) => {
|
|
177
|
+
assert.ok(err.message.includes('has no enterprise'));
|
|
178
|
+
return true;
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
it('should throw if PRF assertion returns no result', async function () {
|
|
182
|
+
mockProvider.get.resolves({ ...mockAuthResult, prfResult: undefined });
|
|
183
|
+
await assert.rejects(() => callAttach(), (err) => {
|
|
184
|
+
assert.ok(err.message.includes('PRF assertion did not return a result'));
|
|
185
|
+
return true;
|
|
186
|
+
});
|
|
187
|
+
sinon.assert.notCalled(mockBitGo.put);
|
|
188
|
+
});
|
|
189
|
+
it('should propagate decrypt errors', async function () {
|
|
190
|
+
mockBitGo.decrypt.throws(new Error('decryption failed'));
|
|
191
|
+
await assert.rejects(() => callAttach(), (err) => {
|
|
192
|
+
assert.ok(err.message.includes('decryption failed'));
|
|
193
|
+
return true;
|
|
194
|
+
});
|
|
195
|
+
sinon.assert.notCalled(mockBitGo.put);
|
|
196
|
+
});
|
|
197
|
+
it('should use device.credentialId as the key in evalByCredential', async function () {
|
|
198
|
+
await callAttach();
|
|
199
|
+
const getArgs = mockProvider.get.firstCall.args[0];
|
|
200
|
+
const evalKeys = Object.keys(getArgs.evalByCredential);
|
|
201
|
+
assert.strictEqual(evalKeys.length, 1);
|
|
202
|
+
assert.strictEqual(evalKeys[0], device.credentialId);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0YWNoUGFzc2tleVRvV2FsbGV0LnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQvYXR0YWNoUGFzc2tleVRvV2FsbGV0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBaUM7QUFDakMsNkNBQStCO0FBQy9CLDJFQUF3RTtBQUd4RSxRQUFRLENBQUMsdUJBQXVCLEVBQUU7SUFDaEMsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDO0lBQ3BCLE1BQU0sUUFBUSxHQUFHLGVBQWUsQ0FBQztJQUNqQyxNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUM7SUFDakMsTUFBTSxZQUFZLEdBQUcsZ0JBQWdCLENBQUM7SUFDdEMsTUFBTSxZQUFZLEdBQUcsc0JBQXNCLENBQUM7SUFDNUMsTUFBTSxZQUFZLEdBQUcsZ0JBQWdCLENBQUM7SUFDdEMsTUFBTSxrQkFBa0IsR0FBRyxvQkFBb0IsQ0FBQztJQUNoRCxNQUFNLGNBQWMsR0FBRyxrQkFBa0IsQ0FBQztJQUUxQyxNQUFNLGVBQWUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBRXhFLE1BQU0sTUFBTSxHQUFzQjtRQUNoQyxFQUFFLEVBQUUscUJBQXFCO1FBQ3pCLFlBQVksRUFBRSxhQUFhO1FBQzNCLE9BQU8sRUFBRSw2Q0FBNkM7UUFDdEQsU0FBUyxFQUFFLElBQUk7S0FDaEIsQ0FBQztJQUVGLE1BQU0sY0FBYyxHQUFzQjtRQUN4QyxTQUFTLEVBQUUsZUFBZTtRQUMxQixZQUFZLEVBQUUsYUFBYTtRQUMzQixPQUFPLEVBQUUsUUFBUTtLQUNsQixDQUFDO0lBRUYsTUFBTSxlQUFlLEdBQUc7UUFDdEIsRUFBRSxFQUFFLFVBQVU7UUFDZCxHQUFHLEVBQUUsVUFBVTtRQUNmLElB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b3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCB7IGF0dGFjaFBhc3NrZXlUb1dhbGxldCB9IGZyb20gJy4uLy4uL3NyYy9hdHRhY2hQYXNza2V5VG9XYWxsZXQnO1xuaW1wb3J0IHsgV2ViQXV0aG5PdHBEZXZpY2UsIFBhc3NrZXlBdXRoUmVzdWx0LCBXZWJBdXRoblByb3ZpZGVyIH0gZnJvbSAnLi4vLi4vc3JjL3dlYkF1dGhuVHlwZXMnO1xuXG5kZXNjcmliZSgnYXR0YWNoUGFzc2tleVRvV2FsbGV0JywgZnVuY3Rpb24gKCkge1xuICBjb25zdCBjb2luID0gJ3RidGMnO1xuICBjb25zdCB3YWxsZXRJZCA9ICd3YWxsZXQtYWJjMTIzJztcbiAgY29uc3Qga2V5Y2hhaW5JZCA9ICdrZXktdXNlci1pZCc7XG4gIGNvbnN0IGVudGVycHJpc2VJZCA9ICdlbnRlcnByaXNlLXh5eic7XG4gIGNvbnN0IGVuY3J5cHRlZFBydiA9ICdlbmNyeXB0ZWQtcHJ2LXN0cmluZyc7XG4gIGNvbnN0IGRlY3J5cHRlZFBydiA9ICd4cHJ2LWRlY3J5cHRlZCc7XG4gIGNvbnN0IGV4aXN0aW5nUGFzc3BocmFzZSA9ICdjb3JyZWN0LXBhc3NwaHJhc2UnO1xuICBjb25zdCByZUVuY3J5cHRlZFBydiA9ICdyZS1lbmNyeXB0ZWQtcHJ2JztcblxuICBjb25zdCBwcmZSZXN1bHRCdWZmZXIgPSBuZXcgVWludDhBcnJheShbMHgxZSwgMHg1YywgMHhiNCwgMHg3OF0pLmJ1ZmZlcjtcblxuICBjb25zdCBkZXZpY2U6IFdlYkF1dGhuT3RwRGV2aWNlID0ge1xuICAgIGlkOiAnbW9uZ28tb2JqZWN0LWlkLTEyMycsXG4gICAgY3JlZGVudGlhbElkOiAnY3JlZC1pZC00NTYnLFxuICAgIHByZlNhbHQ6ICdacUo2NE0yZEw2NXpuMi1KeGQ1OFNNTjJJTGM5UWpiQ0Z4VVRHSGRfTEM4JyxcbiAgICBpc1Bhc3NrZXk6IHRydWUsXG4gIH07XG5cbiAgY29uc3QgbW9ja0F1dGhSZXN1bHQ6IFBhc3NrZXlBdXRoUmVzdWx0ID0ge1xuICAgIHByZlJlc3VsdDogcHJmUmVzdWx0QnVmZmVyLFxuICAgIGNyZWRlbnRpYWxJZDogJ2NyZWQtaWQtNDU2JyxcbiAgICBvdHBDb2RlOiAnMTIzNDU2JyxcbiAgfTtcblxuICBjb25zdCB1cGRhdGVkS2V5Y2hhaW4gPSB7XG4gICAgaWQ6IGtleWNoYWluSWQsXG4gICAgcHViOiAneHB1Yi0xMjMnLFxuICAgIHR5cGU6ICdpbmRlcGVuZGVudCcgYXMgY29uc3QsXG4gICAgZW5jcnlwdGVkUHJ2LFxuICB9O1xuXG4gIGxldCBtb2NrV2FsbGV0OiB7XG4gICAgdHlwZTogc2lub24uU2lub25TdHViO1xuICAgIHRvSlNPTjogc2lub24uU2lub25TdHViO1xuICAgIGdldEVuY3J5cHRlZFVzZXJLZXljaGFpbjogc2lub24uU2lub25TdHViO1xuICB9O1xuXG4gIGxldCBtb2NrV2FsbGV0czoge1xuICAgIGdldDogc2lub24uU2lub25TdHViO1xuICB9O1xuXG4gIGxldCBtb2NrQmFzZUNvaW46IHtcbiAgICB3YWxsZXRzOiBzaW5vbi5TaW5vblN0dWI7XG4gIH07XG5cbiAgbGV0IG1vY2tCaXRHbzoge1xuICAgIHVybDogc2lub24uU2lub25TdHViO1xuICAgIGNvaW46IHNpbm9uLlNpbm9uU3R1YjtcbiAgICBwdXQ6IHNpbm9uLlNpbm9uU3R1YjtcbiAgICBkZWNyeXB0OiBzaW5vbi5TaW5vblN0dWI7XG4gICAgZW5jcnlwdDogc2lub24uU2lub25TdHViO1xuICB9O1xuXG4gIGxldCBtb2NrUHJvdmlkZXI6IHtcbiAgICBjcmVhdGU6IHNpbm9uLlNpbm9uU3R1YjtcbiAgICBnZXQ6IHNpbm9uLlNpbm9uU3R1YjtcbiAgfTtcblxuICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBtb2NrV2FsbGV0ID0ge1xuICAgICAgdHlwZTogc2lub24uc3R1YigpLnJldHVybnMoJ2hvdCcpLFxuICAgICAgdG9KU09OOiBzaW5vbi5zdHViKCkucmV0dXJucyh7IGVudGVycHJpc2U6IGVudGVycHJpc2VJZCB9KSxcbiAgICAgIGdldEVuY3J5cHRlZFVzZXJLZXljaGFpbjogc2lub24uc3R1YigpLnJlc29sdmVzKHsgaWQ6IGtleWNoYWluSWQsIGVuY3J5cHRlZFBydiB9KSxcbiAgICB9O1xuXG4gICAgbW9ja1dhbGxldHMgPSB7XG4gICAgICBnZXQ6IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyhtb2NrV2FsbGV0KSxcbiAgICB9O1xuXG4gICAgbW9ja0Jhc2VDb2luID0ge1xuICAgICAgd2FsbGV0czogc2lub24uc3R1YigpLnJldHVybnMobW9ja1dhbGxldHMpLFxuICAgIH07XG5cbiAgICBtb2NrQml0R28gPSB7XG4gICAgICB1cmw6IHNpbm9uXG4gICAgICAgIC5zdHViPFtwYXRoOiBzdHJpbmcsIHZlcnNpb24/OiBudW1iZXJdLCBzdHJpbmc+KClcbiAgICAgICAgLmNhbGxzRmFrZSgocGF0aCwgdmVyc2lvbikgPT4gYC9hcGkvdiR7dmVyc2lvbiA/PyAxfSR7cGF0aH1gKSxcbiAgICAgIGNvaW46IHNpbm9uLnN0dWIoKS5yZXR1cm5zKG1vY2tCYXNlQ29pbiksXG4gICAgICBwdXQ6IHNpbm9uLnN0dWIoKSxcbiAgICAgIGRlY3J5cHQ6IHNpbm9uLnN0dWIoKSxcbiAgICAgIGVuY3J5cHQ6IHNpbm9uLnN0dWIoKSxcbiAgICB9O1xuXG4gICAgbW9ja1Byb3ZpZGVyID0ge1xuICAgICAgY3JlYXRlOiBzaW5vbi5zdHViKCksXG4gICAgICBnZXQ6IHNpbm9uLnN0dWIoKSxcbiAgICB9O1xuXG4gICAgbW9ja0JpdEdvLmRlY3J5cHQucmV0dXJucyhkZWNyeXB0ZWRQcnYpO1xuICAgIG1vY2tCaXRHby5lbmNyeXB0LnJldHVybnMocmVFbmNyeXB0ZWRQcnYpO1xuXG4gICAgY29uc3QgcHV0U2VuZFN0dWIgPSBzaW5vbi5zdHViKCkucmV0dXJucyh7IHJlc3VsdDogc2lub24uc3R1YigpLnJlc29sdmVzKHVwZGF0ZWRLZXljaGFpbikgfSk7XG4gICAgbW9ja0JpdEdvLnB1dC5yZXR1cm5zKHsgc2VuZDogcHV0U2VuZFN0dWIgfSk7XG5cbiAgICBtb2NrUHJvdmlkZXIuZ2V0LnJlc29sdmVzKG1vY2tBdXRoUmVzdWx0KTtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIGNhbGxBdHRhY2gob3ZlcnJpZGVzPzogUGFydGlhbDxQYXJhbWV0ZXJzPHR5cGVvZiBhdHRhY2hQYXNza2V5VG9XYWxsZXQ+WzBdPikge1xuICAgIHJldHVybiBhdHRhY2hQYXNza2V5VG9XYWxsZXQoe1xuICAgICAgYml0Z286IG1vY2tCaXRHbyBhcyB1bmtub3duIGFzIFBhcmFtZXRlcnM8dHlwZW9mIGF0dGFjaFBhc3NrZXlUb1dhbGxldD5bMF1bJ2JpdGdvJ10sXG4gICAgICBjb2luLFxuICAgICAgd2FsbGV0SWQsXG4gICAgICBkZXZpY2UsXG4gICAgICBleGlzdGluZ1Bhc3NwaHJhc2UsXG4gICAgICBwcm92aWRlcjogbW9ja1Byb3ZpZGVyIGFzIHVua25vd24gYXMgV2ViQXV0aG5Qcm92aWRlcixcbiAgICAgIC4uLm92ZXJyaWRlcyxcbiAgICB9KTtcbiAgfVxuXG4gIGl0KCdzaG91bGQgYXR0YWNoIGEgcGFzc2tleSBhbmQgcmV0dXJuIHRoZSB1cGRhdGVkIGtleWNoYWluJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNhbGxBdHRhY2goKTtcblxuICAgIHNpbm9uLmFzc2VydC5jYWxsZWRXaXRoKG1vY2tCaXRHby5jb2luLCBjb2luKTtcbiAgICBzaW5vbi5hc3NlcnQuY2FsbGVkV2l0aChtb2NrV2FsbGV0cy5nZXQsIHsgaWQ6IHdhbGxldElkIH0pO1xuICAgIHNpbm9uLmFzc2VydC5jYWxsZWRPbmNlKG1vY2tXYWxsZXQudHlwZSk7XG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2UobW9ja1dhbGxldC5nZXRFbmNyeXB0ZWRVc2VyS2V5Y2hhaW4pO1xuICAgIHNpbm9uLmFzc2VydC5jYWxsZWRPbmNlKG1vY2tCaXRHby5kZWNyeXB0KTtcbiAgICBzaW5vbi5hc3NlcnQuY2FsbGVkV2l0aEV4YWN0bHkobW9ja0JpdEdvLmRlY3J5cHQsIHsgcGFzc3dvcmQ6IGV4aXN0aW5nUGFzc3BocmFzZSwgaW5wdXQ6IGVuY3J5cHRlZFBydiB9KTtcblxuICAgIC8vIHByb3ZpZGVyLmdldCBjYWxsZWQgd2l0aCBldmFsQnlDcmVkZW50aWFsIGtleWVkIG9uIGRldmljZS5jcmVkZW50aWFsSWRcbiAgICBzaW5vbi5hc3NlcnQuY2FsbGVkT25jZShtb2NrUHJvdmlkZXIuZ2V0KTtcbiAgICBjb25zdCBnZXRBcmdzID0gbW9ja1Byb3ZpZGVyLmdldC5maXJzdENhbGwuYXJnc1swXTtcbiAgICBhc3NlcnQub2soZ2V0QXJncy5ldmFsQnlDcmVkZW50aWFsKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHlwZW9mIGdldEFyZ3MuZXZhbEJ5Q3JlZGVudGlhbFtkZXZpY2UuY3JlZGVudGlhbElkXSwgJ3N0cmluZycpO1xuXG4gICAgLy8gYWxsb3dDcmVkZW50aWFscyBtdXN0IGJlIHBvcHVsYXRlZCB3aXRoIHRoZSBjcmVkZW50aWFsIElEIGFzIGFuIEFycmF5QnVmZmVyXG4gICAgYXNzZXJ0Lm9rKEFycmF5LmlzQXJyYXkoZ2V0QXJncy5wdWJsaWNLZXkuYWxsb3dDcmVkZW50aWFscykpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChnZXRBcmdzLnB1YmxpY0tleS5hbGxvd0NyZWRlbnRpYWxzLmxlbmd0aCwgMSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGdldEFyZ3MucHVibGljS2V5LmFsbG93Q3JlZGVudGlhbHNbMF0udHlwZSwgJ3B1YmxpYy1rZXknKTtcbiAgICBhc3NlcnQub2soZ2V0QXJncy5wdWJsaWNLZXkuYWxsb3dDcmVkZW50aWFsc1swXS5pZCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKTtcblxuICAgIC8vIFBVVCBjYWxsZWQgd2l0aCBjb3JyZWN0IHNoYXBlXG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2UobW9ja0JpdEdvLnB1dCk7XG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZFdpdGgobW9ja0JpdEdvLnB1dCwgYC9hcGkvdjIvJHtjb2lufS9rZXkvJHtrZXljaGFpbklkfWApO1xuICAgIGNvbnN0IHNlbmRTdHViID0gbW9ja0JpdEdvLnB1dC5maXJzdENhbGwucmV0dXJuVmFsdWUuc2VuZDtcbiAgICBzaW5vbi5hc3NlcnQuY2FsbGVkT25jZShzZW5kU3R1Yik7XG4gICAgY29uc3QgcHV0Qm9keSA9IHNlbmRTdHViLmZpcnN0Q2FsbC5hcmdzWzBdO1xuICAgIGFzc2VydC5vayhwdXRCb2R5LndlYmF1dGhuSW5mbyk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHB1dEJvZHkud2ViYXV0aG5JbmZvLm90cERldmljZUlkLCBkZXZpY2UuaWQpO1xuICAgIC8vIHByZlNhbHQgbXVzdCBiZSBiYXNlNjR1cmwgKFVSTC1zYWZlLCBubyBwYWRkaW5nKSBhcyByZXF1aXJlZCBieSBzZXJ2ZXIgdmFsaWRhdGlvblxuICAgIGFzc2VydC5tYXRjaChwdXRCb2R5LndlYmF1dGhuSW5mby5wcmZTYWx0LCAvXltBLVphLXowLTlcXC1fXSskLyk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR5cGVvZiBwdXRCb2R5LndlYmF1dGhuSW5mby5lbmNyeXB0ZWRQcnYsICdzdHJpbmcnKTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQuaWQsIGtleWNoYWluSWQpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGRlY29kZSBjcmVkZW50aWFsSWQgY29udGFpbmluZyBiYXNlNjR1cmwtc3BlY2lmaWMgY2hhcmFjdGVycyAoLSBhbmQgXyknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgZGV2aWNlV2l0aFVybENoYXJzOiBXZWJBdXRobk90cERldmljZSA9IHtcbiAgICAgIC4uLmRldmljZSxcbiAgICAgIGNyZWRlbnRpYWxJZDogJ2FiYy1kZWZfZ2hpK2prbCcsXG4gICAgfTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNhbGxBdHRhY2goeyBkZXZpY2U6IGRldmljZVdpdGhVcmxDaGFycyB9KTtcbiAgICBhc3NlcnQub2socmVzdWx0KTtcblxuICAgIGNvbnN0IGdldEFyZ3MgPSBtb2NrUHJvdmlkZXIuZ2V0LmZpcnN0Q2FsbC5hcmdzWzBdO1xuICAgIGFzc2VydC5vayhnZXRBcmdzLnB1YmxpY0tleS5hbGxvd0NyZWRlbnRpYWxzWzBdLmlkIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IGlmIGRldmljZS5wcmZTYWx0IGlzIHVuZGVmaW5lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBkZXZpY2VOb1ByZjogV2ViQXV0aG5PdHBEZXZpY2UgPSB7IC4uLmRldmljZSwgcHJmU2FsdDogdW5kZWZpbmVkIH07XG5cbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+IGNhbGxBdHRhY2goeyBkZXZpY2U6IGRldmljZU5vUHJmIH0pLFxuICAgICAgKGVycjogRXJyb3IpID0+IHtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVyci5tZXNzYWdlLCAnUFJGIGV4dGVuc2lvbiBub3Qgc3VwcG9ydGVkIGJ5IHRoaXMgZGV2aWNlLiBQbGVhc2UgdXNlIGEgZGlmZmVyZW50IHBhc3NrZXkuJyk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICk7XG5cbiAgICBzaW5vbi5hc3NlcnQubm90Q2FsbGVkKG1vY2tCaXRHby5jb2luKTtcbiAgICBzaW5vbi5hc3NlcnQubm90Q2FsbGVkKG1vY2tCaXRHby5wdXQpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IGlmIHdhbGxldCBpcyBub3QgYSBob3Qgd2FsbGV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIG1vY2tXYWxsZXQudHlwZS5yZXR1cm5zKCdjb2xkJyk7XG5cbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+IGNhbGxBdHRhY2goKSxcbiAgICAgIChlcnI6IEVycm9yKSA9PiB7XG4gICAgICAgIGFzc2VydC5vayhlcnIubWVzc2FnZS5pbmNsdWRlcygnbm90IGEgaG90IHdhbGxldCcpKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgKTtcblxuICAgIHNpbm9uLmFzc2VydC5ub3RDYWxsZWQobW9ja0JpdEdvLnB1dCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgaWYgd2FsbGV0IGhhcyBubyBlbnRlcnByaXNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIG1vY2tXYWxsZXQudG9KU09OLnJldHVybnMoeyBlbnRlcnByaXNlOiB1bmRlZmluZWQgfSk7XG5cbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+IGNhbGxBdHRhY2goKSxcbiAgICAgIChlcnI6IEVycm9yKSA9PiB7XG4gICAgICAgIGFzc2VydC5vayhlcnIubWVzc2FnZS5pbmNsdWRlcygnaGFzIG5vIGVudGVycHJpc2UnKSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgaWYgUFJGIGFzc2VydGlvbiByZXR1cm5zIG5vIHJlc3VsdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBtb2NrUHJvdmlkZXIuZ2V0LnJlc29sdmVzKHsgLi4ubW9ja0F1dGhSZXN1bHQsIHByZlJlc3VsdDogdW5kZWZpbmVkIH0pO1xuXG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PiBjYWxsQXR0YWNoKCksXG4gICAgICAoZXJyOiBFcnJvcikgPT4ge1xuICAgICAgICBhc3NlcnQub2soZXJyLm1lc3NhZ2UuaW5jbHVkZXMoJ1BSRiBhc3NlcnRpb24gZGlkIG5vdCByZXR1cm4gYSByZXN1bHQnKSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICk7XG5cbiAgICBzaW5vbi5hc3NlcnQubm90Q2FsbGVkKG1vY2tCaXRHby5wdXQpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHByb3BhZ2F0ZSBkZWNyeXB0IGVycm9ycycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBtb2NrQml0R28uZGVjcnlwdC50aHJvd3MobmV3IEVycm9yKCdkZWNyeXB0aW9uIGZhaWxlZCcpKTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT4gY2FsbEF0dGFjaCgpLFxuICAgICAgKGVycjogRXJyb3IpID0+IHtcbiAgICAgICAgYXNzZXJ0Lm9rKGVyci5tZXNzYWdlLmluY2x1ZGVzKCdkZWNyeXB0aW9uIGZhaWxlZCcpKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgKTtcblxuICAgIHNpbm9uLmFzc2VydC5ub3RDYWxsZWQobW9ja0JpdEdvLnB1dCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdXNlIGRldmljZS5jcmVkZW50aWFsSWQgYXMgdGhlIGtleSBpbiBldmFsQnlDcmVkZW50aWFsJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGF3YWl0IGNhbGxBdHRhY2goKTtcblxuICAgIGNvbnN0IGdldEFyZ3MgPSBtb2NrUHJvdmlkZXIuZ2V0LmZpcnN0Q2FsbC5hcmdzWzBdO1xuICAgIGNvbnN0IGV2YWxLZXlzID0gT2JqZWN0LmtleXMoZ2V0QXJncy5ldmFsQnlDcmVkZW50aWFsKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZXZhbEtleXMubGVuZ3RoLCAxKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZXZhbEtleXNbMF0sIGRldmljZS5jcmVkZW50aWFsSWQpO1xuICB9KTtcbn0pO1xuIl19
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base64url.test.d.ts","sourceRoot":"","sources":["../../../test/unit/base64url.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const assert = __importStar(require("assert"));
|
|
37
|
+
const base64url_1 = require("../../src/base64url");
|
|
38
|
+
describe('base64url helpers', function () {
|
|
39
|
+
describe('toBase64Url', function () {
|
|
40
|
+
it('replaces +, / and strips padding', function () {
|
|
41
|
+
assert.strictEqual((0, base64url_1.toBase64Url)('a+b/c=='), 'a-b_c');
|
|
42
|
+
});
|
|
43
|
+
it('is a no-op on already-base64url input', function () {
|
|
44
|
+
assert.strictEqual((0, base64url_1.toBase64Url)('a-b_c'), 'a-b_c');
|
|
45
|
+
});
|
|
46
|
+
it('handles empty string', function () {
|
|
47
|
+
assert.strictEqual((0, base64url_1.toBase64Url)(''), '');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('bufferToBase64Url', function () {
|
|
51
|
+
it('encodes a Buffer to unpadded base64url', function () {
|
|
52
|
+
// bytes that produce + and / in standard base64
|
|
53
|
+
const buf = Buffer.from([0xfb, 0xff, 0xbf]);
|
|
54
|
+
assert.strictEqual(buf.toString('base64'), '+/+/');
|
|
55
|
+
assert.strictEqual((0, base64url_1.bufferToBase64Url)(buf), '-_-_');
|
|
56
|
+
});
|
|
57
|
+
it('encodes an ArrayBuffer to unpadded base64url', function () {
|
|
58
|
+
const ab = new Uint8Array([0xff, 0xfe, 0xfd]).buffer;
|
|
59
|
+
assert.strictEqual((0, base64url_1.bufferToBase64Url)(ab), '__79');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('base64UrlToBuffer', function () {
|
|
63
|
+
it('round-trips through bufferToBase64Url', function () {
|
|
64
|
+
const original = Buffer.from([0x00, 0xff, 0x10, 0x20, 0xab, 0xcd]);
|
|
65
|
+
const encoded = (0, base64url_1.bufferToBase64Url)(original);
|
|
66
|
+
const decoded = (0, base64url_1.base64UrlToBuffer)(encoded);
|
|
67
|
+
assert.deepStrictEqual(decoded, original);
|
|
68
|
+
});
|
|
69
|
+
it('decodes base64url with - and _ chars', function () {
|
|
70
|
+
const decoded = (0, base64url_1.base64UrlToBuffer)('-_-_');
|
|
71
|
+
assert.deepStrictEqual(decoded, Buffer.from([0xfb, 0xff, 0xbf]));
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZTY0dXJsLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQvYmFzZTY0dXJsLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBaUM7QUFDakMsbURBQXdGO0FBRXhGLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRTtJQUM1QixRQUFRLENBQUMsYUFBYSxFQUFFO1FBQ3RCLEVBQUUsQ0FBQyxrQ0FBa0MsRUFBRTtZQUNyQyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUEsdUJBQVcsRUFBQyxTQUFTLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN0RCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx1Q0FBdUMsRUFBRTtZQUMxQyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUEsdUJBQVcsRUFBQyxPQUFPLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNwRCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxzQkFBc0IsRUFBRTtZQUN6QixNQUFNLENBQUMsV0FBVyxDQUFDLElBQUEsdUJBQVcsRUFBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMxQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLG1CQUFtQixFQUFFO1FBQzVCLEVBQUUsQ0FBQyx3Q0FBd0MsRUFBRTtZQUMzQyxnREFBZ0Q7WUFDaEQsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUM1QyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDbkQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFBLDZCQUFpQixFQUFDLEdBQUcsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3JELENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDhDQUE4QyxFQUFFO1lBQ2pELE1BQU0sRUFBRSxHQUFHLElBQUksVUFBVSxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztZQUNyRCxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUEsNkJBQWlCLEVBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxtQkFBbUIsRUFBRTtRQUM1QixFQUFFLENBQUMsdUNBQXVDLEVBQUU7WUFDMUMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNuRSxNQUFNLE9BQU8sR0FBRyxJQUFBLDZCQUFpQixFQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzVDLE1BQU0sT0FBTyxHQUFHLElBQUEsNkJBQWlCLEVBQUMsT0FBTyxDQUFDLENBQUM7WUFDM0MsTUFBTSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDNUMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsc0NBQXNDLEVBQUU7WUFDekMsTUFBTSxPQUFPLEdBQUcsSUFBQSw2QkFBaUIsRUFBQyxNQUFNLENBQUMsQ0FBQztZQUMxQyxNQUFNLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyBiYXNlNjRVcmxUb0J1ZmZlciwgYnVmZmVyVG9CYXNlNjRVcmwsIHRvQmFzZTY0VXJsIH0gZnJvbSAnLi4vLi4vc3JjL2Jhc2U2NHVybCc7XG5cbmRlc2NyaWJlKCdiYXNlNjR1cmwgaGVscGVycycsIGZ1bmN0aW9uICgpIHtcbiAgZGVzY3JpYmUoJ3RvQmFzZTY0VXJsJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdyZXBsYWNlcyArLCAvIGFuZCBzdHJpcHMgcGFkZGluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0b0Jhc2U2NFVybCgnYStiL2M9PScpLCAnYS1iX2MnKTtcbiAgICB9KTtcblxuICAgIGl0KCdpcyBhIG5vLW9wIG9uIGFscmVhZHktYmFzZTY0dXJsIGlucHV0JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRvQmFzZTY0VXJsKCdhLWJfYycpLCAnYS1iX2MnKTtcbiAgICB9KTtcblxuICAgIGl0KCdoYW5kbGVzIGVtcHR5IHN0cmluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0b0Jhc2U2NFVybCgnJyksICcnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2J1ZmZlclRvQmFzZTY0VXJsJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdlbmNvZGVzIGEgQnVmZmVyIHRvIHVucGFkZGVkIGJhc2U2NHVybCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIGJ5dGVzIHRoYXQgcHJvZHVjZSArIGFuZCAvIGluIHN0YW5kYXJkIGJhc2U2NFxuICAgICAgY29uc3QgYnVmID0gQnVmZmVyLmZyb20oWzB4ZmIsIDB4ZmYsIDB4YmZdKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChidWYudG9TdHJpbmcoJ2Jhc2U2NCcpLCAnKy8rLycpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJ1ZmZlclRvQmFzZTY0VXJsKGJ1ZiksICctXy1fJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnZW5jb2RlcyBhbiBBcnJheUJ1ZmZlciB0byB1bnBhZGRlZCBiYXNlNjR1cmwnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhYiA9IG5ldyBVaW50OEFycmF5KFsweGZmLCAweGZlLCAweGZkXSkuYnVmZmVyO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJ1ZmZlclRvQmFzZTY0VXJsKGFiKSwgJ19fNzknKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2Jhc2U2NFVybFRvQnVmZmVyJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdyb3VuZC10cmlwcyB0aHJvdWdoIGJ1ZmZlclRvQmFzZTY0VXJsJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgb3JpZ2luYWwgPSBCdWZmZXIuZnJvbShbMHgwMCwgMHhmZiwgMHgxMCwgMHgyMCwgMHhhYiwgMHhjZF0pO1xuICAgICAgY29uc3QgZW5jb2RlZCA9IGJ1ZmZlclRvQmFzZTY0VXJsKG9yaWdpbmFsKTtcbiAgICAgIGNvbnN0IGRlY29kZWQgPSBiYXNlNjRVcmxUb0J1ZmZlcihlbmNvZGVkKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoZGVjb2RlZCwgb3JpZ2luYWwpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RlY29kZXMgYmFzZTY0dXJsIHdpdGggLSBhbmQgXyBjaGFycycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGRlY29kZWQgPSBiYXNlNjRVcmxUb0J1ZmZlcignLV8tXycpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChkZWNvZGVkLCBCdWZmZXIuZnJvbShbMHhmYiwgMHhmZiwgMHhiZl0pKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deriveEnterpriseSalt.test.d.ts","sourceRoot":"","sources":["../../../test/unit/deriveEnterpriseSalt.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const assert = __importStar(require("assert"));
|
|
37
|
+
const src_1 = require("../../src");
|
|
38
|
+
// Real fixture values captured from a live environment (DB + browser devtools)
|
|
39
|
+
const REAL_FIXTURE = {
|
|
40
|
+
basePrfSalt: 'ZqJ64M2dL65zn2-Jxd58SMN2ILc9QjbCFxUTGHd_LC8',
|
|
41
|
+
enterpriseId: '69c2aea1a3d7bc07f7f775c0ca86b0ec',
|
|
42
|
+
// base64url encoding of the HMAC-SHA256(baseSalt_decoded, enterpriseId) digest.
|
|
43
|
+
// Same encoding the server stores and the WebAuthn PRF extension consumes — keeping
|
|
44
|
+
// one encoding everywhere avoids the hex/base64url mismatch that broke browser PRF.
|
|
45
|
+
expectedDerivedSalt: 'oiasOqzkuyuEz_8043-3IXYghSu3LV4N_a1MLIRzmU8',
|
|
46
|
+
};
|
|
47
|
+
describe('deriveEnterpriseSalt', function () {
|
|
48
|
+
it('produces the correct derived salt for real fixture values', function () {
|
|
49
|
+
// Verifies SDK output matches what the retail UI produces for the same inputs,
|
|
50
|
+
// ensuring clients can move between SDK and retail app seamlessly.
|
|
51
|
+
assert.strictEqual((0, src_1.deriveEnterpriseSalt)(REAL_FIXTURE.basePrfSalt, REAL_FIXTURE.enterpriseId), REAL_FIXTURE.expectedDerivedSalt);
|
|
52
|
+
});
|
|
53
|
+
it('is deterministic — same inputs always produce the same salt', function () {
|
|
54
|
+
const first = (0, src_1.deriveEnterpriseSalt)(REAL_FIXTURE.basePrfSalt, REAL_FIXTURE.enterpriseId);
|
|
55
|
+
const second = (0, src_1.deriveEnterpriseSalt)(REAL_FIXTURE.basePrfSalt, REAL_FIXTURE.enterpriseId);
|
|
56
|
+
assert.ok(first);
|
|
57
|
+
assert.strictEqual(first, second);
|
|
58
|
+
});
|
|
59
|
+
it('produces different salts for different enterpriseIds with the same prfSalt', function () {
|
|
60
|
+
const saltA = (0, src_1.deriveEnterpriseSalt)(REAL_FIXTURE.basePrfSalt, REAL_FIXTURE.enterpriseId);
|
|
61
|
+
const saltB = (0, src_1.deriveEnterpriseSalt)(REAL_FIXTURE.basePrfSalt, 'different-enterprise-id');
|
|
62
|
+
assert.notStrictEqual(saltA, saltB);
|
|
63
|
+
});
|
|
64
|
+
it('produces different salts for different prfSalts with the same enterpriseId', function () {
|
|
65
|
+
const saltA = (0, src_1.deriveEnterpriseSalt)(REAL_FIXTURE.basePrfSalt, REAL_FIXTURE.enterpriseId);
|
|
66
|
+
const saltB = (0, src_1.deriveEnterpriseSalt)('deadbeefcafebabe0102030405060708', REAL_FIXTURE.enterpriseId);
|
|
67
|
+
assert.notStrictEqual(saltA, saltB);
|
|
68
|
+
});
|
|
69
|
+
it('returns a non-empty unpadded base64url string', function () {
|
|
70
|
+
const result = (0, src_1.deriveEnterpriseSalt)(REAL_FIXTURE.basePrfSalt, REAL_FIXTURE.enterpriseId);
|
|
71
|
+
assert.strictEqual(typeof result, 'string');
|
|
72
|
+
assert.ok(result.length > 0);
|
|
73
|
+
// Base64url alphabet, no padding. SHA-256 = 32 bytes → 43 base64url chars.
|
|
74
|
+
assert.match(result, /^[A-Za-z0-9_-]{43}$/);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVyaXZlRW50ZXJwcmlzZVNhbHQudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9kZXJpdmVFbnRlcnByaXNlU2FsdC50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsK0NBQWlDO0FBQ2pDLG1DQUFpRDtBQUVqRCwrRUFBK0U7QUFDL0UsTUFBTSxZQUFZLEdBQUc7SUFDbkIsV0FBVyxFQUFFLDZDQUE2QztJQUMxRCxZQUFZLEVBQUUsa0NBQWtDO0lBQ2hELGdGQUFnRjtJQUNoRixvRkFBb0Y7SUFDcEYsb0ZBQW9GO0lBQ3BGLG1CQUFtQixFQUFFLDZDQUE2QztDQUNuRSxDQUFDO0FBRUYsUUFBUSxDQUFDLHNCQUFzQixFQUFFO0lBQy9CLEVBQUUsQ0FBQywyREFBMkQsRUFBRTtRQUM5RCwrRUFBK0U7UUFDL0UsbUVBQW1FO1FBQ25FLE1BQU0sQ0FBQyxXQUFXLENBQ2hCLElBQUEsMEJBQW9CLEVBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxZQUFZLENBQUMsWUFBWSxDQUFDLEVBQ3pFLFlBQVksQ0FBQyxtQkFBbUIsQ0FDakMsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDZEQUE2RCxFQUFFO1FBQ2hFLE1BQU0sS0FBSyxHQUFHLElBQUEsMEJBQW9CLEVBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDeEYsTUFBTSxNQUFNLEdBQUcsSUFBQSwwQkFBb0IsRUFBQyxZQUFZLENBQUMsV0FBVyxFQUFFLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN6RixNQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pCLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3BDLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDRFQUE0RSxFQUFFO1FBQy9FLE1BQU0sS0FBSyxHQUFHLElBQUEsMEJBQW9CLEVBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDeEYsTUFBTSxLQUFLLEdBQUcsSUFBQSwwQkFBb0IsRUFBQyxZQUFZLENBQUMsV0FBVyxFQUFFLHlCQUF5QixDQUFDLENBQUM7UUFDeEYsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDdEMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsNEVBQTRFLEVBQUU7UUFDL0UsTUFBTSxLQUFLLEdBQUcsSUFBQSwwQkFBb0IsRUFBQyxZQUFZLENBQUMsV0FBVyxFQUFFLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN4RixNQUFNLEtBQUssR0FBRyxJQUFBLDBCQUFvQixFQUFDLGtDQUFrQyxFQUFFLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNsRyxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN0QyxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQywrQ0FBK0MsRUFBRTtRQUNsRCxNQUFNLE1BQU0sR0FBRyxJQUFBLDBCQUFvQixFQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsWUFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3pGLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDNUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzdCLDJFQUEyRTtRQUMzRSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO0lBQzlDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGRlcml2ZUVudGVycHJpc2VTYWx0IH0gZnJvbSAnLi4vLi4vc3JjJztcblxuLy8gUmVhbCBmaXh0dXJlIHZhbHVlcyBjYXB0dXJlZCBmcm9tIGEgbGl2ZSBlbnZpcm9ubWVudCAoREIgKyBicm93c2VyIGRldnRvb2xzKVxuY29uc3QgUkVBTF9GSVhUVVJFID0ge1xuICBiYXNlUHJmU2FsdDogJ1pxSjY0TTJkTDY1em4yLUp4ZDU4U01OMklMYzlRamJDRnhVVEdIZF9MQzgnLFxuICBlbnRlcnByaXNlSWQ6ICc2OWMyYWVhMWEzZDdiYzA3ZjdmNzc1YzBjYTg2YjBlYycsXG4gIC8vIGJhc2U2NHVybCBlbmNvZGluZyBvZiB0aGUgSE1BQy1TSEEyNTYoYmFzZVNhbHRfZGVjb2RlZCwgZW50ZXJwcmlzZUlkKSBkaWdlc3QuXG4gIC8vIFNhbWUgZW5jb2RpbmcgdGhlIHNlcnZlciBzdG9yZXMgYW5kIHRoZSBXZWJBdXRobiBQUkYgZXh0ZW5zaW9uIGNvbnN1bWVzIOKAlCBrZWVwaW5nXG4gIC8vIG9uZSBlbmNvZGluZyBldmVyeXdoZXJlIGF2b2lkcyB0aGUgaGV4L2Jhc2U2NHVybCBtaXNtYXRjaCB0aGF0IGJyb2tlIGJyb3dzZXIgUFJGLlxuICBleHBlY3RlZERlcml2ZWRTYWx0OiAnb2lhc09xemt1eXVFel84MDQzLTNJWFlnaFN1M0xWNE5fYTFNTElSem1VOCcsXG59O1xuXG5kZXNjcmliZSgnZGVyaXZlRW50ZXJwcmlzZVNhbHQnLCBmdW5jdGlvbiAoKSB7XG4gIGl0KCdwcm9kdWNlcyB0aGUgY29ycmVjdCBkZXJpdmVkIHNhbHQgZm9yIHJlYWwgZml4dHVyZSB2YWx1ZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgLy8gVmVyaWZpZXMgU0RLIG91dHB1dCBtYXRjaGVzIHdoYXQgdGhlIHJldGFpbCBVSSBwcm9kdWNlcyBmb3IgdGhlIHNhbWUgaW5wdXRzLFxuICAgIC8vIGVuc3VyaW5nIGNsaWVudHMgY2FuIG1vdmUgYmV0d2VlbiBTREsgYW5kIHJldGFpbCBhcHAgc2VhbWxlc3NseS5cbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoXG4gICAgICBkZXJpdmVFbnRlcnByaXNlU2FsdChSRUFMX0ZJWFRVUkUuYmFzZVByZlNhbHQsIFJFQUxfRklYVFVSRS5lbnRlcnByaXNlSWQpLFxuICAgICAgUkVBTF9GSVhUVVJFLmV4cGVjdGVkRGVyaXZlZFNhbHRcbiAgICApO1xuICB9KTtcblxuICBpdCgnaXMgZGV0ZXJtaW5pc3RpYyDigJQgc2FtZSBpbnB1dHMgYWx3YXlzIHByb2R1Y2UgdGhlIHNhbWUgc2FsdCcsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBmaXJzdCA9IGRlcml2ZUVudGVycHJpc2VTYWx0KFJFQUxfRklYVFVSRS5iYXNlUHJmU2FsdCwgUkVBTF9GSVhUVVJFLmVudGVycHJpc2VJZCk7XG4gICAgY29uc3Qgc2Vjb25kID0gZGVyaXZlRW50ZXJwcmlzZVNhbHQoUkVBTF9GSVhUVVJFLmJhc2VQcmZTYWx0LCBSRUFMX0ZJWFRVUkUuZW50ZXJwcmlzZUlkKTtcbiAgICBhc3NlcnQub2soZmlyc3QpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChmaXJzdCwgc2Vjb25kKTtcbiAgfSk7XG5cbiAgaXQoJ3Byb2R1Y2VzIGRpZmZlcmVudCBzYWx0cyBmb3IgZGlmZmVyZW50IGVudGVycHJpc2VJZHMgd2l0aCB0aGUgc2FtZSBwcmZTYWx0JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHNhbHRBID0gZGVyaXZlRW50ZXJwcmlzZVNhbHQoUkVBTF9GSVhUVVJFLmJhc2VQcmZTYWx0LCBSRUFMX0ZJWFRVUkUuZW50ZXJwcmlzZUlkKTtcbiAgICBjb25zdCBzYWx0QiA9IGRlcml2ZUVudGVycHJpc2VTYWx0KFJFQUxfRklYVFVSRS5iYXNlUHJmU2FsdCwgJ2RpZmZlcmVudC1lbnRlcnByaXNlLWlkJyk7XG4gICAgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsKHNhbHRBLCBzYWx0Qik7XG4gIH0pO1xuXG4gIGl0KCdwcm9kdWNlcyBkaWZmZXJlbnQgc2FsdHMgZm9yIGRpZmZlcmVudCBwcmZTYWx0cyB3aXRoIHRoZSBzYW1lIGVudGVycHJpc2VJZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBzYWx0QSA9IGRlcml2ZUVudGVycHJpc2VTYWx0KFJFQUxfRklYVFVSRS5iYXNlUHJmU2FsdCwgUkVBTF9GSVhUVVJFLmVudGVycHJpc2VJZCk7XG4gICAgY29uc3Qgc2FsdEIgPSBkZXJpdmVFbnRlcnByaXNlU2FsdCgnZGVhZGJlZWZjYWZlYmFiZTAxMDIwMzA0MDUwNjA3MDgnLCBSRUFMX0ZJWFRVUkUuZW50ZXJwcmlzZUlkKTtcbiAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwoc2FsdEEsIHNhbHRCKTtcbiAgfSk7XG5cbiAgaXQoJ3JldHVybnMgYSBub24tZW1wdHkgdW5wYWRkZWQgYmFzZTY0dXJsIHN0cmluZycsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCByZXN1bHQgPSBkZXJpdmVFbnRlcnByaXNlU2FsdChSRUFMX0ZJWFRVUkUuYmFzZVByZlNhbHQsIFJFQUxfRklYVFVSRS5lbnRlcnByaXNlSWQpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2YgcmVzdWx0LCAnc3RyaW5nJyk7XG4gICAgYXNzZXJ0Lm9rKHJlc3VsdC5sZW5ndGggPiAwKTtcbiAgICAvLyBCYXNlNjR1cmwgYWxwaGFiZXQsIG5vIHBhZGRpbmcuIFNIQS0yNTYgPSAzMiBieXRlcyDihpIgNDMgYmFzZTY0dXJsIGNoYXJzLlxuICAgIGFzc2VydC5tYXRjaChyZXN1bHQsIC9eW0EtWmEtejAtOV8tXXs0M30kLyk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derivePasskeyPrfKey.test.d.ts","sourceRoot":"","sources":["../../../test/unit/derivePasskeyPrfKey.test.ts"],"names":[],"mappings":""}
|