decane-connect-kit 2.12.1 → 2.13.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/dist/index.cjs +37 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +37 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2968,9 +2968,6 @@ async function deriveKeyFromPin(pin, salt) {
|
|
|
2968
2968
|
["encrypt", "decrypt"]
|
|
2969
2969
|
);
|
|
2970
2970
|
}
|
|
2971
|
-
function validatePin(pin) {
|
|
2972
|
-
if (!/^\d{4,8}$/.test(pin)) throw new Error("PIN must be 4\u20138 digits");
|
|
2973
|
-
}
|
|
2974
2971
|
|
|
2975
2972
|
// src/social/crypto/passkey.ts
|
|
2976
2973
|
var import_browser2 = require("@simplewebauthn/browser");
|
|
@@ -3784,21 +3781,38 @@ async function createDecaneConnect(config) {
|
|
|
3784
3781
|
}
|
|
3785
3782
|
}
|
|
3786
3783
|
events.on("session-expired", () => dropLiveSession());
|
|
3787
|
-
async function
|
|
3788
|
-
if (!config.
|
|
3789
|
-
const
|
|
3790
|
-
|
|
3791
|
-
const
|
|
3792
|
-
const
|
|
3784
|
+
async function passwordSetup() {
|
|
3785
|
+
if (!config.promptUnlockPassword) throw new PromptPasswordNotConfiguredError();
|
|
3786
|
+
const password = await config.promptUnlockPassword({ kind: "set" });
|
|
3787
|
+
validateUnlockPassword(password);
|
|
3788
|
+
const passwordSalt = generateRandomBytes(32);
|
|
3789
|
+
const { shareKey, tokenKey } = await derivePasswordKeys(password, passwordSalt);
|
|
3793
3790
|
return {
|
|
3794
|
-
wrappingKey,
|
|
3791
|
+
wrappingKey: shareKey,
|
|
3792
|
+
tokenKey,
|
|
3795
3793
|
meta: {
|
|
3796
|
-
unlockMethod: "
|
|
3797
|
-
|
|
3798
|
-
|
|
3794
|
+
unlockMethod: "password",
|
|
3795
|
+
passwordSalt: bufferToB64u(passwordSalt),
|
|
3796
|
+
passwordIterations: PBKDF2_ITERATIONS
|
|
3799
3797
|
}
|
|
3800
3798
|
};
|
|
3801
3799
|
}
|
|
3800
|
+
async function attachUnlockToken(userId, jwt, tokenKey) {
|
|
3801
|
+
try {
|
|
3802
|
+
const stored = await storage.getShare(userId);
|
|
3803
|
+
if (!stored) return;
|
|
3804
|
+
const { token } = await api.issueUnlockToken(jwt);
|
|
3805
|
+
const unlockTokenIv = generateRandomBytes(12);
|
|
3806
|
+
const wrappedUnlockToken = await aesGcmEncrypt(
|
|
3807
|
+
tokenKey,
|
|
3808
|
+
new TextEncoder().encode(token),
|
|
3809
|
+
unlockTokenIv
|
|
3810
|
+
);
|
|
3811
|
+
await storage.putShare({ ...stored, wrappedUnlockToken, unlockTokenIv });
|
|
3812
|
+
} catch (e) {
|
|
3813
|
+
console.warn("decane-connect-kit: could not store an unlock token for this device.", e);
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3802
3816
|
async function persistRotatedDeviceShare(userId, deviceShare) {
|
|
3803
3817
|
const stored = await storage.getShare(userId);
|
|
3804
3818
|
if (!stored) {
|
|
@@ -3892,6 +3906,7 @@ async function createDecaneConnect(config) {
|
|
|
3892
3906
|
let unlockMethod;
|
|
3893
3907
|
let wrappingKey;
|
|
3894
3908
|
let meta = {};
|
|
3909
|
+
let unlockTokenKey = null;
|
|
3895
3910
|
if (isPasskeySupported()) {
|
|
3896
3911
|
const prfSalt = generateRandomBytes(32);
|
|
3897
3912
|
try {
|
|
@@ -3905,18 +3920,18 @@ async function createDecaneConnect(config) {
|
|
|
3905
3920
|
prfSalt: bufferToB64u(prfSalt)
|
|
3906
3921
|
};
|
|
3907
3922
|
} else {
|
|
3908
|
-
({ wrappingKey, meta } = await
|
|
3909
|
-
unlockMethod = "
|
|
3923
|
+
({ wrappingKey, meta, tokenKey: unlockTokenKey } = await passwordSetup());
|
|
3924
|
+
unlockMethod = "password";
|
|
3910
3925
|
}
|
|
3911
3926
|
} catch (e) {
|
|
3912
3927
|
if (e.name === "UserCancelledError")
|
|
3913
3928
|
throw new UserCancelledError();
|
|
3914
|
-
({ wrappingKey, meta } = await
|
|
3915
|
-
unlockMethod = "
|
|
3929
|
+
({ wrappingKey, meta, tokenKey: unlockTokenKey } = await passwordSetup());
|
|
3930
|
+
unlockMethod = "password";
|
|
3916
3931
|
}
|
|
3917
3932
|
} else {
|
|
3918
|
-
({ wrappingKey, meta } = await
|
|
3919
|
-
unlockMethod = "
|
|
3933
|
+
({ wrappingKey, meta, tokenKey: unlockTokenKey } = await passwordSetup());
|
|
3934
|
+
unlockMethod = "password";
|
|
3920
3935
|
}
|
|
3921
3936
|
const provisioningStartedAt = Date.now();
|
|
3922
3937
|
const remainingBudget = () => PROVISIONING_BUDGET_MS - (Date.now() - provisioningStartedAt);
|
|
@@ -3948,8 +3963,11 @@ async function createDecaneConnect(config) {
|
|
|
3948
3963
|
prfSalt: meta.prfSalt ? b64uToBuffer(meta.prfSalt) : void 0,
|
|
3949
3964
|
pinSalt: meta.pinSalt ? b64uToBuffer(meta.pinSalt) : void 0,
|
|
3950
3965
|
pinIterations: meta.pinIterations,
|
|
3966
|
+
passwordSalt: meta.passwordSalt ? b64uToBuffer(meta.passwordSalt) : void 0,
|
|
3967
|
+
passwordIterations: meta.passwordIterations,
|
|
3951
3968
|
version: 1
|
|
3952
3969
|
});
|
|
3970
|
+
if (unlockTokenKey) await attachUnlockToken(userId, jwt, unlockTokenKey);
|
|
3953
3971
|
const serverIv = generateRandomBytes(12);
|
|
3954
3972
|
await withDeadline(api.putShare(jwt, {
|
|
3955
3973
|
ciphertext: shareSet.server,
|