Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@lo-fi/local-data-lock

Package Overview
Dependencies
Maintainers
0
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lo-fi/local-data-lock - npm Package Compare versions

Comparing version 0.14.2 to 0.14.3

4

dist/auto/ldl.js
/*! mylofi/Local-Data-Lock: ldl.js
v0.14.2 (c) 2024 Kyle Simpson
v0.14.3 (c) 2024 Kyle Simpson
MIT License: http://getify.mit-license.org
*/
import{supportsWebAuthn as e,regDefaults as t,register as r,authDefaults as a,auth as n,verifyAuthResponse as o,packPublicKeyJSON as i,unpackPublicKeyJSON as s,toBase64String as c,fromBase64String as l,toUTF8String as y,fromUTF8String as u,resetAbortReason as p}from"@lo-fi/webauthn-local-client";const f=1,d=sodium.crypto_sign_SEEDBYTES;var g=setLockKeyCacheLifetime(18e5),k="idb",b=null,h=null,w={},m=null,K=new WeakMap;export{e as supportsWebAuthn,i as packPublicKeyJSON,s as unpackPublicKeyJSON,c as toBase64String,l as fromBase64String,y as toUTF8String,u as fromUTF8String,p as resetAbortReason,listLocalIdentities,clearLockKeyCache,removeLocalAccount,getLockKey,generateEntropy,deriveLockKey,lockData,unlockData,signData,verifySignature,configure};var L={supportsWebAuthn:e,packPublicKeyJSON:i,unpackPublicKeyJSON:s,toBase64String:c,fromBase64String:l,toUTF8String:y,fromUTF8String:u,resetAbortReason:p,listLocalIdentities:listLocalIdentities,clearLockKeyCache:clearLockKeyCache,removeLocalAccount:removeLocalAccount,getLockKey:getLockKey,generateEntropy:generateEntropy,deriveLockKey:deriveLockKey,lockData:lockData,unlockData:unlockData,signData:signData,verifySignature:verifySignature,configure:configure};export default L;async function listLocalIdentities(){return await checkStorage(),Object.keys(h)}function cacheLockKey(e,t,r=!1){e in w&&!r||(w[e]={...t,timestamp:Date.now()})}function clearLockKeyCache(e){null!=e?delete w[e]:w={}}async function removeLocalAccount(e){return await checkStorage(),delete w[e],delete h[e],storeLocalIdentities()}async function getLockKey({localIdentity:e=c(generateEntropy(15)),username:i="local-user",displayName:s="Local User",relyingPartyID:l=document.location.hostname,relyingPartyName:y="Local Data Lock",addNewPasskey:u=!1,resetLockKey:p=!1,useLockKey:f=null,verify:k=!0,signal:b}={}){await checkStorage();var K=null!=e?h[e]:null;if(null!=K){let t=function getCachedLockKey(e){var t=Date.now();if(e in w&&w[e].timestamp>=t-Math.min(g,t)){let{timestamp:t,...r}=w[e];return r}}(e);if(null!=t&&!p){if(u){resetAbortToken(b);let{record:e}=await registerLocalIdentity(t)||{};cleanupExternalSignalHandler(m),m=null,null!=e&&(K.lastSeq=e.lastSeq,K.passkeys=[...K.passkeys,...e.passkeys],await storeLocalIdentities())}return Object.freeze({...t,localIdentity:e})}if(delete w[e],p){if(resetAbortToken(b),({record:h[e],lockKey:t}=await registerLocalIdentity(f&&"object"==typeof f?checkLockKey(f):void 0)),cleanupExternalSignalHandler(m),m=null,null==h[e])delete h[e];else if(null!=t)return await storeLocalIdentities(),cacheLockKey(e,t),Object.freeze({...t,localIdentity:e})}else{if(u)throw new Error("Encryption/Decryption key not currently cached, unavailable for new passkey");{resetAbortToken(b);let t=a({relyingPartyID:l,mediation:"optional",allowCredentials:K.passkeys.map((({credentialID:e})=>({type:"public-key",id:e}))),signal:m.signal}),r=await n(t);if(cleanupExternalSignalHandler(m),m=null,null!=r){if(k){let e=K.passkeys.find((e=>e.credentialID==r.response.credentialID)),t=e?.publicKey;if(!(null!=t&&await o(r.response,t)))throw new Error("Auth verification failed")}return{...extractLockKey(r),localIdentity:e}}}}}else if(u){resetAbortToken(b);let{record:t,lockKey:r}=await registerLocalIdentity(f&&"object"==typeof f?checkLockKey(f):void 0)||{};if(cleanupExternalSignalHandler(m),m=null,null!=t&&null!=r)return h[e]=t,cacheLockKey(e,r),await storeLocalIdentities(),Object.freeze({...r,localIdentity:e})}else{resetAbortToken(b);let t=a({relyingPartyID:l,mediation:"optional",signal:m.signal}),r=await n(t);if(cleanupExternalSignalHandler(m),m=null,null!=r){let t=extractLockKey(r),[a]=Object.entries(h).find((([,e])=>null!=e.passkeys.find((e=>e.credentialID==r.response.credentialID))))||[];if(null!=a){if(delete w[e],K=h[e=a],k){let e=K.passkeys.find((e=>e.credentialID==r.response.credentialID)),t=e?.publicKey;if(!(null!=t&&await o(r.response,t)))throw new Error("Auth verification failed")}cacheLockKey(e,t)}else if(k)throw new Error("Auth verification requested but skipped, against unrecognized passkey (no matching local-identity)");return Object.freeze({...t,localIdentity:e})}}async function registerLocalIdentity(a=deriveLockKey()){try{let o=((h[e]||{}).lastSeq||0)+1,c=new Uint8Array(a.iv.byteLength+2),u=new DataView(new ArrayBuffer(2));u.setInt16(0,o,!1),c.set(a.iv,0),c.set(new Uint8Array(u.buffer),a.iv.byteLength);let p=t({relyingPartyID:l,relyingPartyName:y,user:{id:c,name:i,displayName:s},signal:m.signal}),f=await r(p);if(null!=f)return{record:{lastSeq:o,passkeys:[(n={seq:o,credentialID:f.response.credentialID,publicKey:f.response.publicKey},{...n,hash:computePasskeyEntryHash(n)})]},lockKey:a}}catch(e){throw new Error("Identity/Passkey registration failed",{cause:e})}var n}function extractLockKey(t){try{if(t&&t.response&&isByteArray(t.response.userID)&&t.response.userID.byteLength==d+2){let r=deriveLockKey(t.response.userID.subarray(0,d));return cacheLockKey(e,r),r}throw new Error("Passkey info missing")}catch(e){throw new Error("Chosen passkey did not provide a valid encryption/decryption key",{cause:e})}}}function resetAbortToken(e){if(m&&(cleanupExternalSignalHandler(m),m.aborted||m.abort("Passkey operation abandoned.")),m=new AbortController,null!=e)if(e.aborted)m.abort(e.reason);else{let handlerFn=()=>{cleanupExternalSignalHandler(m),m.abort(e.reason),m=e=handlerFn=null};e.addEventListener("abort",handlerFn),K.set(m,[e,handlerFn])}}function cleanupExternalSignalHandler(e){if(null!=e&&K.has(e)){let[t,r]=K.get(e);t.removeEventListener("abort",r),K.delete(e)}}function generateEntropy(e=16){return sodium.randombytes_buf(e)}function deriveLockKey(e=generateEntropy(d)){try{let t=sodium.crypto_sign_seed_keypair(e);return{keyFormatVersion:f,iv:e,publicKey:t.publicKey,privateKey:t.privateKey,encPK:sodium.crypto_sign_ed25519_pk_to_curve25519(t.publicKey),encSK:sodium.crypto_sign_ed25519_sk_to_curve25519(t.privateKey)}}catch(e){throw new Error("Encryption/decryption key derivation failed.",{cause:e})}}function checkLockKey(e){if(e&&"object"==typeof e){if(e.keyFormatVersion===f)return e;if(isByteArray(e.iv)&&e.iv.byteLength==d)return deriveLockKey(e.iv)}throw new Error("Unrecongnized lock-key")}function lockData(e,t,{outputFormat:r="base64"}={}){try{let a=dataToBuffer(e),n=sodium.crypto_box_seal(a,t.encPK);return["base64","base-64"].includes(r.toLowerCase())?c(n):n}catch(e){throw new Error("Data encryption failed.",{cause:e})}}function unlockData(e,t,{outputFormat:r="utf8",parseJSON:a=!0}={}){try{let n=sodium.crypto_box_seal_open("string"==typeof e?l(e):e,t.encPK,t.encSK);if(["utf8","utf-8"].includes(r.toLowerCase())){let e=y(n);return a?JSON.parse(e):e}return n}catch(e){throw new Error("Data decryption failed.",{cause:e})}}function signData(e,{privateKey:t}={},{outputFormat:r="base64"}={}){try{let a=sodium.crypto_sign_detached(dataToBuffer(e),t);return["base64","base-64"].includes(r.toLowerCase())?c(a):a}catch(e){throw new Error("Data signature failed.",{cause:e})}}function verifySignature(e,{publicKey:t}={},r){try{return sodium.crypto_sign_verify_detached("string"==typeof r?l(r):r,dataToBuffer(e),t)}catch(e){throw new Error("Data signature failed.",{cause:e})}}async function storeLocalIdentities(){await checkStorage();var e=Object.fromEntries(Object.entries(h).map((([e,t])=>[e,{...t,passkeys:t.passkeys.map((e=>({...e,publicKey:i(e.publicKey)})))}])));Object.keys(e).length>0?await b.set("local-identities",e):await b.remove("local-identities")}function setLockKeyCacheLifetime(e){return g=Math.max(0,Number(e)||0)}function configure({accountStorage:e,cacheLifetime:t}={}){null!=e&&function configureStorage(e){if(["idb","local-storage","session-storage","cookie","opfs","opfs-worker"].includes(e))k=e,h=b=null;else{if("object"!=typeof e||"string"!=typeof e.storageType||!["has","get","set","remove","keys","entries"].every((t=>"function"==typeof e[t])))throw new Error(`Unrecognized storage type ('${storageType}')`);b=e,k=e.storageType,h=null}}(e),null!=t&&setLockKeyCacheLifetime(t)}function dataToBuffer(e){var t=null==e?null:e instanceof ArrayBuffer?new Uint8Array(e):isByteArray(e)?e:u("object"==typeof e?JSON.stringify(e):"string"==typeof e?e:String(e));if(null==t)throw new Error("Non-empty data required.");return t}function isByteArray(e){return e instanceof Uint8Array&&e.buffer instanceof ArrayBuffer}function computePasskeyEntryHash(e){let{hash:t,...r}=e;return c(sodium.crypto_hash(JSON.stringify({...r,publicKey:i(r.publicKey)})))}async function checkStorage(){if(null==b){if(!["idb","local-storage","session-storage","cookie","opfs","opfs-worker"].includes(k))throw new Error(`Unrecognized storage type ('${k}')`);b="idb"==k?await import("@byojs/storage/idb"):"local-storage"==k?await import("@byojs/storage/local-storage"):"session-storage"==k?await import("@byojs/storage/session-storage"):"cookie"==k?await import("@byojs/storage/cookie"):"opfs"==k?await import("@byojs/storage/opfs"):"opfs-worker"==k?await import("@byojs/storage/opfs-worker"):null}null!=b&&null==h&&(h=await async function loadLocalIdentities(){return Object.fromEntries(Object.entries(await b.get("local-identities")||{}).filter((([e,t])=>"number"==typeof t.lastSeq&&Array.isArray(t.passkeys)&&t.passkeys.length>0&&t.passkeys.every((e=>"string"==typeof e.credentialID&&""!=e.credentialID&&"number"==typeof e.seq&&null!=e.publicKey&&"object"==typeof e.publicKey&&"number"==typeof e.publicKey.algoCOSE&&"string"==typeof e.publicKey.raw&&""!=e.publicKey.raw&&"string"==typeof e.publicKey.spki&&""!=e.publicKey.spki&&"string"==typeof e.hash&&""!=e.hash&&e.hash==computePasskeyEntryHash(e))))).map((([e,t])=>[e,{...t,passkeys:t.passkeys.map((e=>({...e,publicKey:s(e.publicKey)})))}])))}())}
import{supportsWebAuthn as e,regDefaults as t,register as r,authDefaults as a,auth as n,verifyAuthResponse as i,packPublicKeyJSON as o,unpackPublicKeyJSON as s,toBase64String as c,fromBase64String as l,toUTF8String as u,fromUTF8String as y,resetAbortReason as p}from"@lo-fi/webauthn-local-client";const f=1,d=sodium.crypto_sign_SEEDBYTES;var g=null,k=null,h={},b=null,m=new WeakMap,w=null,K=setLockKeyCacheLifetime(18e5),L="idb";export{e as supportsWebAuthn,o as packPublicKeyJSON,s as unpackPublicKeyJSON,c as toBase64String,l as fromBase64String,u as toUTF8String,y as fromUTF8String,p as resetAbortReason,listLocalIdentities,clearLockKeyCache,removeLocalAccount,getLockKey,generateEntropy,deriveLockKey,lockData,unlockData,signData,verifySignature,configure};var v={supportsWebAuthn:e,packPublicKeyJSON:o,unpackPublicKeyJSON:s,toBase64String:c,fromBase64String:l,toUTF8String:u,fromUTF8String:y,resetAbortReason:p,listLocalIdentities:listLocalIdentities,clearLockKeyCache:clearLockKeyCache,removeLocalAccount:removeLocalAccount,getLockKey:getLockKey,generateEntropy:generateEntropy,deriveLockKey:deriveLockKey,lockData:lockData,unlockData:unlockData,signData:signData,verifySignature:verifySignature,configure:configure};export default v;async function listLocalIdentities(){return await checkStorage(),Object.keys(k)}function cacheLockKey(e,t,r=!1){e in h&&!r||(h[e]={...t,timestamp:Date.now()},resetCachePurgeTimer())}function clearLockKeyCache(e){null!=e?delete h[e]:h={},resetCachePurgeTimer()}function resetCachePurgeTimer(){null!=w&&(clearTimeout(w),w=null),function setCachePurgeTimer(){if(null==w){let e=function nextCacheTimestamp(){return(Object.values(h).map((e=>e.timestamp))||[])[0]}();if(null!=e){let t=Math.max(6e4,Math.max(e+K-Date.now(),0)+Math.round(1e4*Math.random()));w=setTimeout(purgeExpiredCacheEntries,t)}}}()}function purgeExpiredCacheEntries(){w=null;var e=Date.now(),t=e-Math.min(K,e);Object.entries(h).filter((([e,r])=>r.timestamp<t)).forEach((([e])=>{delete h[e]})),resetCachePurgeTimer()}async function removeLocalAccount(e){return await checkStorage(),delete h[e],delete k[e],storeLocalIdentities()}async function getLockKey({localIdentity:e=c(generateEntropy(15)),username:o="local-user",displayName:s="Local User",relyingPartyID:l=document.location.hostname,relyingPartyName:u="Local Data Lock",addNewPasskey:y=!1,resetLockKey:p=!1,useLockKey:f=null,verify:g=!0,signal:m}={}){await checkStorage();var w=null!=e?k[e]:null;if(null!=w){let t=function getCachedLockKey(e){var t=Date.now();if(e in h&&h[e].timestamp>=t-Math.min(K,t)){let{timestamp:t,...r}=h[e];return r}}(e);if(null!=t&&!p){if(y){resetAbortToken(m);let{record:e}=await registerLocalIdentity(t)||{};cleanupExternalSignalHandler(b),b=null,null!=e&&(w.lastSeq=e.lastSeq,w.passkeys=[...w.passkeys,...e.passkeys],await storeLocalIdentities())}return Object.freeze({...t,localIdentity:e})}if(delete h[e],p){if(resetAbortToken(m),({record:k[e],lockKey:t}=await registerLocalIdentity(f&&"object"==typeof f?checkLockKey(f):void 0)),cleanupExternalSignalHandler(b),b=null,null==k[e])delete k[e];else if(null!=t)return await storeLocalIdentities(),cacheLockKey(e,t),Object.freeze({...t,localIdentity:e})}else{if(y)throw new Error("Encryption/Decryption key not currently cached, unavailable for new passkey");{resetAbortToken(m);let t=a({relyingPartyID:l,mediation:"optional",allowCredentials:w.passkeys.map((({credentialID:e})=>({type:"public-key",id:e}))),signal:b.signal}),r=await n(t);if(cleanupExternalSignalHandler(b),b=null,null!=r){if(g){let e=w.passkeys.find((e=>e.credentialID==r.response.credentialID)),t=e?.publicKey;if(!(null!=t&&await i(r.response,t)))throw new Error("Auth verification failed")}return{...extractLockKey(r),localIdentity:e}}}}}else if(y){resetAbortToken(m);let{record:t,lockKey:r}=await registerLocalIdentity(f&&"object"==typeof f?checkLockKey(f):void 0)||{};if(cleanupExternalSignalHandler(b),b=null,null!=t&&null!=r)return k[e]=t,cacheLockKey(e,r),await storeLocalIdentities(),Object.freeze({...r,localIdentity:e})}else{resetAbortToken(m);let t=a({relyingPartyID:l,mediation:"optional",signal:b.signal}),r=await n(t);if(cleanupExternalSignalHandler(b),b=null,null!=r){let t=extractLockKey(r),[a]=Object.entries(k).find((([,e])=>null!=e.passkeys.find((e=>e.credentialID==r.response.credentialID))))||[];if(null!=a){if(delete h[e],w=k[e=a],g){let e=w.passkeys.find((e=>e.credentialID==r.response.credentialID)),t=e?.publicKey;if(!(null!=t&&await i(r.response,t)))throw new Error("Auth verification failed")}cacheLockKey(e,t)}else if(g)throw new Error("Auth verification requested but skipped, against unrecognized passkey (no matching local-identity)");return Object.freeze({...t,localIdentity:e})}}async function registerLocalIdentity(a=deriveLockKey()){try{let i=((k[e]||{}).lastSeq||0)+1,c=new Uint8Array(a.iv.byteLength+2),y=new DataView(new ArrayBuffer(2));y.setInt16(0,i,!1),c.set(a.iv,0),c.set(new Uint8Array(y.buffer),a.iv.byteLength);let p=t({relyingPartyID:l,relyingPartyName:u,user:{id:c,name:o,displayName:s},signal:b.signal}),f=await r(p);if(null!=f)return{record:{lastSeq:i,passkeys:[(n={seq:i,credentialID:f.response.credentialID,publicKey:f.response.publicKey},{...n,hash:computePasskeyEntryHash(n)})]},lockKey:a}}catch(e){throw new Error("Identity/Passkey registration failed",{cause:e})}var n}function extractLockKey(t){try{if(t&&t.response&&isByteArray(t.response.userID)&&t.response.userID.byteLength==d+2){let r=deriveLockKey(t.response.userID.subarray(0,d));return cacheLockKey(e,r),r}throw new Error("Passkey info missing")}catch(e){throw new Error("Chosen passkey did not provide a valid encryption/decryption key",{cause:e})}}}function resetAbortToken(e){if(b&&(cleanupExternalSignalHandler(b),b.aborted||b.abort("Passkey operation abandoned.")),b=new AbortController,null!=e)if(e.aborted)b.abort(e.reason);else{let handlerFn=()=>{cleanupExternalSignalHandler(b),b.abort(e.reason),b=e=handlerFn=null};e.addEventListener("abort",handlerFn),m.set(b,[e,handlerFn])}}function cleanupExternalSignalHandler(e){if(null!=e&&m.has(e)){let[t,r]=m.get(e);t.removeEventListener("abort",r),m.delete(e)}}function generateEntropy(e=16){return sodium.randombytes_buf(e)}function deriveLockKey(e=generateEntropy(d)){try{let t=sodium.crypto_sign_seed_keypair(e);return{keyFormatVersion:f,iv:e,publicKey:t.publicKey,privateKey:t.privateKey,encPK:sodium.crypto_sign_ed25519_pk_to_curve25519(t.publicKey),encSK:sodium.crypto_sign_ed25519_sk_to_curve25519(t.privateKey)}}catch(e){throw new Error("Encryption/decryption key derivation failed.",{cause:e})}}function checkLockKey(e){if(e&&"object"==typeof e){if(e.keyFormatVersion===f)return e;if(isByteArray(e.iv)&&e.iv.byteLength==d)return deriveLockKey(e.iv)}throw new Error("Unrecongnized lock-key")}function lockData(e,t,{outputFormat:r="base64"}={}){try{let a=dataToBuffer(e),n=sodium.crypto_box_seal(a,t.encPK);return["base64","base-64"].includes(r.toLowerCase())?c(n):n}catch(e){throw new Error("Data encryption failed.",{cause:e})}}function unlockData(e,t,{outputFormat:r="utf8",parseJSON:a=!0}={}){try{let n=sodium.crypto_box_seal_open("string"==typeof e?l(e):e,t.encPK,t.encSK);if(["utf8","utf-8"].includes(r.toLowerCase())){let e=u(n);return a?JSON.parse(e):e}return n}catch(e){throw new Error("Data decryption failed.",{cause:e})}}function signData(e,{privateKey:t}={},{outputFormat:r="base64"}={}){try{let a=sodium.crypto_sign_detached(dataToBuffer(e),t);return["base64","base-64"].includes(r.toLowerCase())?c(a):a}catch(e){throw new Error("Data signature failed.",{cause:e})}}function verifySignature(e,{publicKey:t}={},r){try{return sodium.crypto_sign_verify_detached("string"==typeof r?l(r):r,dataToBuffer(e),t)}catch(e){throw new Error("Data signature failed.",{cause:e})}}async function storeLocalIdentities(){await checkStorage();var e=Object.fromEntries(Object.entries(k).map((([e,t])=>[e,{...t,passkeys:t.passkeys.map((e=>({...e,publicKey:o(e.publicKey)})))}])));Object.keys(e).length>0?await g.set("local-identities",e):await g.remove("local-identities")}function setLockKeyCacheLifetime(e){try{return K=Math.max(0,Number(e)||0)}finally{resetCachePurgeTimer()}}function configure({accountStorage:e,cacheLifetime:t}={}){null!=e&&function configureStorage(e){if(["idb","local-storage","session-storage","cookie","opfs","opfs-worker"].includes(e))L=e,k=g=null;else{if("object"!=typeof e||"string"!=typeof e.storageType||!["has","get","set","remove","keys","entries"].every((t=>"function"==typeof e[t])))throw new Error(`Unrecognized storage type ('${storageType}')`);g=e,L=e.storageType,k=null}}(e),null!=t&&setLockKeyCacheLifetime(t)}function dataToBuffer(e){var t=null==e?null:e instanceof ArrayBuffer?new Uint8Array(e):isByteArray(e)?e:y("object"==typeof e?JSON.stringify(e):"string"==typeof e?e:String(e));if(null==t)throw new Error("Non-empty data required.");return t}function isByteArray(e){return e instanceof Uint8Array&&e.buffer instanceof ArrayBuffer}function computePasskeyEntryHash(e){let{hash:t,...r}=e;return c(sodium.crypto_hash(JSON.stringify({...r,publicKey:o(r.publicKey)})))}async function checkStorage(){if(null==g){if(!["idb","local-storage","session-storage","cookie","opfs","opfs-worker"].includes(L))throw new Error(`Unrecognized storage type ('${L}')`);g="idb"==L?await import("@byojs/storage/idb"):"local-storage"==L?await import("@byojs/storage/local-storage"):"session-storage"==L?await import("@byojs/storage/session-storage"):"cookie"==L?await import("@byojs/storage/cookie"):"opfs"==L?await import("@byojs/storage/opfs"):"opfs-worker"==L?await import("@byojs/storage/opfs-worker"):null}null!=g&&null==k&&(k=await async function loadLocalIdentities(){return Object.fromEntries(Object.entries(await g.get("local-identities")||{}).filter((([e,t])=>"number"==typeof t.lastSeq&&Array.isArray(t.passkeys)&&t.passkeys.length>0&&t.passkeys.every((e=>"string"==typeof e.credentialID&&""!=e.credentialID&&"number"==typeof e.seq&&null!=e.publicKey&&"object"==typeof e.publicKey&&"number"==typeof e.publicKey.algoCOSE&&"string"==typeof e.publicKey.raw&&""!=e.publicKey.raw&&"string"==typeof e.publicKey.spki&&""!=e.publicKey.spki&&"string"==typeof e.hash&&""!=e.hash&&e.hash==computePasskeyEntryHash(e))))).map((([e,t])=>[e,{...t,passkeys:t.passkeys.map((e=>({...e,publicKey:s(e.publicKey)})))}])))}())}
{
"name": "@lo-fi/local-data-lock",
"description": "Protect local-first app data with encryption/decryption key secured in WebAuthn (biometric) passkeys",
"version": "0.14.2",
"version": "0.14.3",
"exports": {

@@ -6,0 +6,0 @@ ".": "./dist/bundlers/ldl.mjs",

@@ -22,4 +22,2 @@ import {

const IV_BYTE_LENGTH = sodium.crypto_sign_SEEDBYTES;
var LOCK_KEY_CACHE_LIFETIME = setLockKeyCacheLifetime(30 * 60 * 1000); // 30 min (default)
var DEFAULT_STORAGE_TYPE = "idb";
var store = null;

@@ -30,2 +28,5 @@ var localIdentities = null;

var externalSignalCache = new WeakMap();
var cachePurgeIntv = null;
var LOCK_KEY_CACHE_LIFETIME = setLockKeyCacheLifetime(30 * 60 * 1000); // 30 min (default)
var DEFAULT_STORAGE_TYPE = "idb";

@@ -95,2 +96,3 @@

var now = Date.now();
if (

@@ -105,3 +107,3 @@ // lock-key currently in cache?

) {
// discard cache-internal timestamp field
// hide cache-internal timestamp field
let { timestamp, ...lockKey } = lockKeyCache[localID];

@@ -121,2 +123,3 @@ return lockKey;

};
resetCachePurgeTimer();
}

@@ -127,3 +130,3 @@ }

if (localID != null) {
delete lockKeyCache[localID]
delete lockKeyCache[localID];
}

@@ -133,4 +136,51 @@ else {

}
resetCachePurgeTimer();
}
function resetCachePurgeTimer() {
if (cachePurgeIntv != null) {
clearTimeout(cachePurgeIntv);
cachePurgeIntv = null;
}
setCachePurgeTimer();
}
function setCachePurgeTimer() {
if (cachePurgeIntv == null) {
let nextTimestamp = nextCacheTimestamp();
if (nextTimestamp != null) {
let when = Math.max(
// at least 1 minute
60_000,
(
// time left until expiration (if any)
Math.max(nextTimestamp + LOCK_KEY_CACHE_LIFETIME - Date.now(),0) +
// up to 10 more seconds
Math.round(Math.random() * 1E4)
)
);
cachePurgeIntv = setTimeout(purgeExpiredCacheEntries,when);
}
}
}
function nextCacheTimestamp() {
return ((
Object.values(lockKeyCache).map(entry => entry.timestamp)
) || [])[0];
}
function purgeExpiredCacheEntries() {
cachePurgeIntv = null;
var now = Date.now();
var when = now - Math.min(LOCK_KEY_CACHE_LIFETIME,now);
Object.entries(lockKeyCache)
.filter(([ localID, entry, ]) => entry.timestamp < when)
.forEach(([ localID, ]) => { delete lockKeyCache[localID]; });
resetCachePurgeTimer();
}
async function removeLocalAccount(localID) {

@@ -697,3 +747,8 @@ await checkStorage();

function setLockKeyCacheLifetime(ms) {
return (LOCK_KEY_CACHE_LIFETIME = Math.max(0,Number(ms) || 0));
try {
return (LOCK_KEY_CACHE_LIFETIME = Math.max(0,Number(ms) || 0));
}
finally {
resetCachePurgeTimer();
}
}

@@ -700,0 +755,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc