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
3
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.12.0 to 0.13.0

20

BUNDLERS.md

@@ -13,11 +13,11 @@ # Deploying Local-Data-Lock WITH A Bundler

* `node_modules/@lo-fi/local-data-lock/dist/bundlers/ldl.mjs`
* `@lo-fi/local-data-lock/dist/bundlers/ldl.mjs`
ESM library module that's suitable for bundling and `import`ing into your web app.
**Note:** this is *not* the same as `node_modules/@lo-fi/local-data-lock/dist/auto/ldl.js`, which is only intended [for web application projects WITHOUT a bundler](NON-BUNDLERS.md)
**Note:** this is *not* the same as `@lo-fi/local-data-lock/dist/auto/ldl.js`, which is only intended [for web application projects WITHOUT a bundler](NON-BUNDLERS.md)
* `node_modules/@lo-fi/webauthn-local-client/dist/bundlers/walc.mjs`
* `@lo-fi/webauthn-local-client/dist/bundlers/walc.mjs`
* `node_modules/@lo-fi/webauthn-local-client/dist/bundlers/walc-external-bundle.js`
* `@lo-fi/webauthn-local-client/dist/bundlers/walc-external-bundle.js`

@@ -63,5 +63,5 @@ Non-ESM (plain global .js) bundle of dependencies that must be loaded separately from (and prior to) your app's bundle.

This plugin works for the `astro dev` (dev-server), as well as `astro build` / `astro preview` modes. In all cases, it copies the WebAuthn-Local-Client (`@lo-fi/webauthn-local-client`) dependency bundle file (`/dist/bundlers/walc-external-bundle.js`) into the `public/` directory of your project root, as well as the `dist/` directory when running a build. It also injects an inline `<script>` element into the `<head>` of all generated pages, which dynamically loads the `/walc-external-bundle.js` script file (which has all the dependencies WALC needs).
This plugin works for the `astro dev` (dev-server), as well as `astro build` / `astro preview` modes. In all cases, it copies the `@lo-fi/local-data-lock/dist/bundlers/walc-external-bundle.js` file into the `public/` directory of your project root, as well as the `dist/` directory when running a build. It also injects an inline `<script>` element into the `<head>` of all generated pages, which dynamically loads the `/walc-external-bundle.js` script file (which has all the dependencies WALC needs).
**Note:** At present, this plugin is not configurable in any way (i.e., calling `LDL()` above with no arguments). If something about its behavior is not compatible with your Astro project setup -- which can vary widely and be quite complex to predict or support by a basic plugin -- it's recommended you simply copy over the `local-data-lock/bundler-plugins/astro.mjs` plugin and make necessary changes.
**Note:** At present, this plugin is not configurable in any way (i.e., calling `LDL()` above with no arguments). If something about its behavior is not compatible with your Astro project setup -- which can vary widely and be quite complex to predict or support by a basic plugin -- it's recommended you simply copy over the `@lo-fi/local-data-lock/bundler-plugins/astro.mjs` plugin and make necessary changes.

@@ -97,5 +97,5 @@ ### Vite Plugin

This plugin works for the `vite dev` (dev-server), `vite preview` (also dev-server), and `vite build` modes. In all cases, it copies the `node_modules/@lo-fi/webauthn-local-client/dist/bundlers/walc-external-bundle.js` file into the `public/` directory of your project root. It also injects a `<script src="/walc-external-bundle.js"></script>` tag into the markup of the `index.html` file that Vite produces for your app.
This plugin works for the `vite dev` (dev-server), `vite preview` (also dev-server), and `vite build` modes. In all cases, it copies the `@lo-fi/webauthn-local-client/dist/bundlers/walc-external-bundle.js` file into the `public/` directory of your project root. It also injects a `<script src="/walc-external-bundle.js"></script>` tag into the markup of the `index.html` file that Vite produces for your app.
**Note:** At present, this plugin is not configurable in any way (i.e., calling `LDL()` above with no arguments). If something about its behavior is not compatible with your Vite project setup -- which can vary widely and be quite complex to predict or support by a basic plugin -- it's recommended you simply copy over the `node_modules/@lo-fi/local-data-lock/bundler-plugins/vite.mjs` plugin and make necessary changes.
**Note:** At present, this plugin is not configurable in any way (i.e., calling `LDL()` above with no arguments). If something about its behavior is not compatible with your Vite project setup -- which can vary widely and be quite complex to predict or support by a basic plugin -- it's recommended you simply copy over the `@lo-fi/local-data-lock/bundler-plugins/vite.mjs` plugin and make necessary changes.

@@ -157,5 +157,5 @@ #### Top-level `await`

This plugin copies the `node_modules/@lo-fi/webauthn-local-client/dist/bundlers/walc-external-bundle.js` file into the build root (default `dist/`), along with the other bundled files. It also injects a `<script src="walc-external-bundle.js"></script>` tag into the markup of the `index.html` file (and any other HTML files) that Webpack produces for your app.
This plugin copies the `@lo-fi/webauthn-local-client/dist/bundlers/walc-external-bundle.js` file into the build root (default `dist/`), along with the other bundled files. It also injects a `<script src="walc-external-bundle.js"></script>` tag into the markup of the `index.html` file (and any other HTML files) that Webpack produces for your app.
**Note:** At present, this plugin is not configurable in any way (i.e., calling `LDL()` above with no arguments). If something about its behavior is not compatible with your Webpack project setup -- which can vary widely and be quite complex to predict or support by a basic plugin -- it's recommended you simply copy over the `local-data-lock/bundler-plugins/webpack.mjs` plugin and make necessary changes.
**Note:** At present, this plugin is not configurable in any way (i.e., calling `LDL()` above with no arguments). If something about its behavior is not compatible with your Webpack project setup -- which can vary widely and be quite complex to predict or support by a basic plugin -- it's recommended you simply copy over the `@lo-fi/local-data-lock/bundler-plugins/webpack.mjs` plugin and make necessary changes.

@@ -162,0 +162,0 @@ ## Import/Usage

/*! WebAuthn-Local-Client: external.js
v0.999.7 (c) 2024 Kyle Simpson
v0.1000.2 (c) 2024 Kyle Simpson
MIT License: http://getify.mit-license.org

@@ -4,0 +4,0 @@ */

@@ -9,5 +9,5 @@ /*!

https://www.npmjs.com/package/@yoursunny/asn1
https://github.com/yoursunny/asn1.js
https://www.npmjs.com/package/@root/asn1
https://github.com/therootcompany/asn1.js
*/
(function(){"use strict";var Enc=window.Encoding={};Enc.bufToBase64=function(u8){var bin="";u8.forEach(function(i){bin+=String.fromCharCode(i)});return btoa(bin)};Enc.strToBase64=function(str){return btoa(Enc.strToBin(str))};function _base64ToBin(b64){return atob(Enc.urlBase64ToBase64(b64))}Enc._base64ToBin=_base64ToBin;Enc.base64ToBuf=function(b64){return Enc.binToBuf(_base64ToBin(b64))};Enc.base64ToStr=function(b64){return Enc.binToStr(_base64ToBin(b64))};Enc.urlBase64ToBase64=function(u64){var r=u64%4;if(2===r){u64+="=="}else if(3===r){u64+="="}return u64.replace(/-/g,"+").replace(/_/g,"/")};Enc.base64ToUrlBase64=function(b64){return b64.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")};Enc.bufToUrlBase64=function(buf){return Enc.base64ToUrlBase64(Enc.bufToBase64(buf))};Enc.strToUrlBase64=function(str){return Enc.bufToUrlBase64(Enc.strToBuf(str))};Enc.bufToHex=function(u8){var hex=[];var i,h;var len=u8.byteLength||u8.length;for(i=0;i<len;i+=1){h=u8[i].toString(16);if(2!==h.length){h="0"+h}hex.push(h)}return hex.join("").toLowerCase()};Enc.numToHex=function(d){d=d.toString(16);if(d.length%2){return"0"+d}return d};Enc.strToHex=function(str){return Enc._binToHex(Enc.strToBin(str))};Enc._binToHex=function(bin){return bin.split("").map(function(ch){var h=ch.charCodeAt(0).toString(16);if(2!==h.length){h="0"+h}return h}).join("")};Enc.hexToBuf=function(hex){var arr=[];hex.match(/.{2}/g).forEach(function(h){arr.push(parseInt(h,16))});return"undefined"!==typeof Uint8Array?new Uint8Array(arr):arr};Enc.hexToStr=function(hex){return Enc.binToStr(_hexToBin(hex))};function _hexToBin(hex){return hex.replace(/([0-9A-F]{2})/gi,function(_,p1){return String.fromCharCode("0x"+p1)})}Enc._hexToBin=_hexToBin;Enc.bufToBin=function(buf){var bin="";buf.forEach(function(ch){bin+=String.fromCharCode(ch)});return bin};Enc.strToBin=function(str){var escstr=encodeURIComponent(str);var binstr=escstr.replace(/%([0-9A-F]{2})/g,function(_,p1){return String.fromCharCode("0x"+p1)});return binstr};Enc.binToBuf=function(bin){var arr=bin.split("").map(function(ch){return ch.charCodeAt(0)});return"undefined"!==typeof Uint8Array?new Uint8Array(arr):arr};Enc.strToBuf=function(str){return Enc.binToBuf(Enc.strToBin(str))};Enc.binToStr=function(binstr){var escstr=binstr.replace(/(.)/g,function(m,p){var code=p.charCodeAt(0).toString(16).toUpperCase();if(code.length<2){code="0"+code}return"%"+code});return decodeURIComponent(escstr)};Enc.bufToStr=function(buf){return Enc.binToStr(Enc.bufToBin(buf))};Enc.base64ToHex=function(b64){return Enc.bufToHex(Enc.base64ToBuf(b64))};Enc.hexToBase64=function(hex){return btoa(Enc._hexToBin(hex))}})();(function(){"use strict";var ASN1=window.ASN1={};var Enc=window.Encoding;ASN1.ELOOPN=102;ASN1.ELOOP="uASN1.js Error: iterated over "+ASN1.ELOOPN+"+ elements (probably a malformed file)";ASN1.EDEEPN=60;ASN1.EDEEP="uASN1.js Error: element nested "+ASN1.EDEEPN+"+ layers deep (probably a malformed file)";ASN1.CTYPES=[48,49,160,161];ASN1.VTYPES=[1,2,5,6,12,130];ASN1.parseVerbose=function parseAsn1Helper(buf,opts){if(!opts){opts={}}function parseAsn1(buf,depth,eager){if(depth.length>=ASN1.EDEEPN){throw new Error(ASN1.EDEEP)}var index=2;var asn1={type:buf[0],lengthSize:0,length:buf[1]};var child;var iters=0;var adjust=0;var adjustedLen;if(128&asn1.length){asn1.lengthSize=127&asn1.length;asn1.length=parseInt(Enc.bufToHex(buf.slice(index,index+asn1.lengthSize)),16);index+=asn1.lengthSize}if(0===buf[index]&&(2===asn1.type||3===asn1.type)){if(asn1.length>1){index+=1;adjust=-1}}adjustedLen=asn1.length+adjust;function parseChildren(eager){asn1.children=[];while(iters<ASN1.ELOOPN&&index<2+asn1.length+asn1.lengthSize){iters+=1;depth.length+=1;child=parseAsn1(buf.slice(index,index+adjustedLen),depth,eager);depth.length-=1;index+=2+child.lengthSize+child.length;if(index>2+asn1.lengthSize+asn1.length){throw new Error("Parse error: child value length ("+child.length+") is greater than remaining parent length ("+(asn1.length-index)+" = "+asn1.length+" - "+index+")")}asn1.children.push(child)}if(index!==2+asn1.lengthSize+asn1.length){throw new Error("premature end-of-file")}if(iters>=ASN1.ELOOPN){throw new Error(ASN1.ELOOP)}delete asn1.value;return asn1}if(-1!==ASN1.CTYPES.indexOf(asn1.type)){return parseChildren(eager)}asn1.value=buf.slice(index,index+adjustedLen);if(opts.json){asn1.value=Enc.bufToHex(asn1.value)}if(-1!==ASN1.VTYPES.indexOf(asn1.type)){return asn1}try{return parseChildren(true)}catch(e){asn1.children.length=0;return asn1}}var asn1=parseAsn1(buf,[]);var len=buf.byteLength||buf.length;if(len!==2+asn1.lengthSize+asn1.length){throw new Error("Length of buffer does not match length of ASN.1 sequence.")}return asn1};ASN1._toArray=function toArray(next,opts){var typ=opts.json?Enc.numToHex(next.type):next.type;var val=next.value;if(val){if("string"!==typeof val&&opts.json){val=Enc.bufToHex(val)}return[typ,val]}return[typ,next.children.map(function(child){return toArray(child,opts)})]};ASN1.parse=function(opts){var opts2={json:false!==opts.json};var verbose=ASN1.parseVerbose(opts.der,opts2);if(opts.verbose){return verbose}return ASN1._toArray(verbose,opts2)};ASN1._replacer=function(k,v){if("type"===k){return"0x"+Enc.numToHex(v)}if(v&&"value"===k){return"0x"+Enc.bufToHex(v.data||v)}return v};function Any(){var args=Array.prototype.slice.call(arguments);var typ=args.shift();var str=args.join("").replace(/\s+/g,"").toLowerCase();var len=str.length/2;var lenlen=0;var hex=typ;if("number"===typeof hex){hex=Enc.numToHex(hex)}if(len!==Math.round(len)){throw new Error("invalid hex")}if(len>127){lenlen+=1;while(len>255){lenlen+=1;len=len>>8}}if(lenlen){hex+=Enc.numToHex(128+lenlen)}return hex+Enc.numToHex(str.length/2)+str}ASN1.Any=Any;ASN1.UInt=function UINT(){var str=Array.prototype.slice.call(arguments).join("");var first=parseInt(str.slice(0,2),16);if(128&first){str="00"+str}return Any("02",str)};ASN1.BitStr=function BITSTR(){var str=Array.prototype.slice.call(arguments).join("");return Any("03","00"+str)};ASN1._toArray=function toArray(next,opts){var typ=opts.json?Enc.numToHex(next.type):next.type;var val=next.value;if(val){if("string"!==typeof val&&opts.json){val=Enc.bufToHex(val)}return[typ,val]}return[typ,next.children.map(function(child){return toArray(child,opts)})]};ASN1._pack=function(arr){var typ=arr[0];if("number"===typeof arr[0]){typ=Enc.numToHex(arr[0])}var str="";if(Array.isArray(arr[1])){arr[1].forEach(function(a){str+=ASN1._pack(a)})}else if("string"===typeof arr[1]){str=arr[1]}else if(arr[1].byteLength){str=Enc.bufToHex(arr[1])}else{throw new Error("unexpected array")}if("03"===typ){return ASN1.BitStr(str)}else if("02"===typ){return ASN1.UInt(str)}else{return Any(typ,str)}};ASN1.pack=function(asn1,opts){if(!opts){opts={}}if(!Array.isArray(asn1)){asn1=ASN1._toArray(asn1,{json:true})}var result=ASN1._pack(asn1);if(opts.json){return result}return Enc.hexToBuf(result)}})();
(function(){"use strict";var Enc=window.Encoding={};Enc.bufToBase64=function(u8){var bin="";u8.forEach(function(i){bin+=String.fromCharCode(i)});return btoa(bin)};Enc.strToBase64=function(str){return btoa(Enc.strToBin(str))};function _base64ToBin(b64){return atob(Enc.urlBase64ToBase64(b64))}Enc._base64ToBin=_base64ToBin;Enc.base64ToBuf=function(b64){return Enc.binToBuf(_base64ToBin(b64))};Enc.base64ToStr=function(b64){return Enc.binToStr(_base64ToBin(b64))};Enc.urlBase64ToBase64=function(u64){var r=u64%4;if(2===r){u64+="=="}else if(3===r){u64+="="}return u64.replace(/-/g,"+").replace(/_/g,"/")};Enc.base64ToUrlBase64=function(b64){return b64.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")};Enc.bufToUrlBase64=function(buf){return Enc.base64ToUrlBase64(Enc.bufToBase64(buf))};Enc.strToUrlBase64=function(str){return Enc.bufToUrlBase64(Enc.strToBuf(str))};Enc.bufToHex=function(u8){var hex=[];var i,h;var len=u8.byteLength||u8.length;for(i=0;i<len;i+=1){h=u8[i].toString(16);if(2!==h.length){h="0"+h}hex.push(h)}return hex.join("").toLowerCase()};Enc.numToHex=function(d){d=d.toString(16);if(d.length%2){return"0"+d}return d};Enc.strToHex=function(str){return Enc._binToHex(Enc.strToBin(str))};Enc._binToHex=function(bin){return bin.split("").map(function(ch){var h=ch.charCodeAt(0).toString(16);if(2!==h.length){h="0"+h}return h}).join("")};Enc.hexToBuf=function(hex){var arr=[];hex.match(/.{2}/g).forEach(function(h){arr.push(parseInt(h,16))});return"undefined"!==typeof Uint8Array?new Uint8Array(arr):arr};Enc.hexToStr=function(hex){return Enc.binToStr(_hexToBin(hex))};function _hexToBin(hex){return hex.replace(/([0-9A-F]{2})/gi,function(_,p1){return String.fromCharCode("0x"+p1)})}Enc._hexToBin=_hexToBin;Enc.bufToBin=function(buf){var bin="";buf.forEach(function(ch){bin+=String.fromCharCode(ch)});return bin};Enc.strToBin=function(str){var escstr=encodeURIComponent(str);var binstr=escstr.replace(/%([0-9A-F]{2})/g,function(_,p1){return String.fromCharCode("0x"+p1)});return binstr};Enc.binToBuf=function(bin){var arr=bin.split("").map(function(ch){return ch.charCodeAt(0)});return"undefined"!==typeof Uint8Array?new Uint8Array(arr):arr};Enc.strToBuf=function(str){return Enc.binToBuf(Enc.strToBin(str))};Enc.binToStr=function(binstr){var escstr=binstr.replace(/(.)/g,function(m,p){var code=p.charCodeAt(0).toString(16).toUpperCase();if(code.length<2){code="0"+code}return"%"+code});return decodeURIComponent(escstr)};Enc.bufToStr=function(buf){return Enc.binToStr(Enc.bufToBin(buf))};Enc.base64ToHex=function(b64){return Enc.bufToHex(Enc.base64ToBuf(b64))};Enc.hexToBase64=function(hex){return btoa(Enc._hexToBin(hex))}})();(function(){"use strict";var ASN1=window.ASN1={};var Enc=window.Encoding;ASN1.ELOOPN=102;ASN1.ELOOP="uASN1.js Error: iterated over "+ASN1.ELOOPN+"+ elements (probably a malformed file)";ASN1.EDEEPN=60;ASN1.EDEEP="uASN1.js Error: element nested "+ASN1.EDEEPN+"+ layers deep (probably a malformed file)";ASN1.CTYPES=[48,49,160,161];ASN1.VTYPES=[1,2,5,6,12,130];ASN1.parseVerbose=function parseAsn1Helper(buf,opts){if(!opts){opts={}}function parseAsn1(buf,depth,eager){if(depth.length>=ASN1.EDEEPN){throw new Error(ASN1.EDEEP)}var index=2;var asn1={type:buf[0],lengthSize:0,length:buf[1]};var child;var iters=0;var adjust=0;var adjustedLen;if(128&asn1.length){asn1.lengthSize=127&asn1.length;asn1.length=parseInt(Enc.bufToHex(buf.slice(index,index+asn1.lengthSize)),16);index+=asn1.lengthSize}if(0===buf[index]&&(2===asn1.type||3===asn1.type)){if(asn1.length>1){index+=1;adjust=-1}}adjustedLen=asn1.length+adjust;function parseChildren(eager){asn1.children=[];while(iters<ASN1.ELOOPN&&index<2+asn1.length+asn1.lengthSize){iters+=1;depth.length+=1;child=parseAsn1(buf.slice(index,index+adjustedLen),depth,eager);depth.length-=1;index+=2+child.lengthSize+child.length;if(index>2+asn1.lengthSize+asn1.length){throw new Error("Parse error: child value length ("+child.length+") is greater than remaining parent length ("+(asn1.length-index)+" = "+asn1.length+" - "+index+")")}asn1.children.push(child)}if(index!==2+asn1.lengthSize+asn1.length){throw new Error("premature end-of-file")}if(iters>=ASN1.ELOOPN){throw new Error(ASN1.ELOOP)}delete asn1.value;return asn1}if(-1!==ASN1.CTYPES.indexOf(asn1.type)){return parseChildren(eager)}asn1.value=buf.slice(index,index+adjustedLen);if(opts.json){asn1.value=Enc.bufToHex(asn1.value)}if(-1!==ASN1.VTYPES.indexOf(asn1.type)){return asn1}try{return parseChildren(true)}catch(e){asn1.children.length=0;return asn1}}var asn1=parseAsn1(buf,[]);var len=buf.byteLength||buf.length;if(len!==2+asn1.lengthSize+asn1.length){throw new Error("Length of buffer does not match length of ASN.1 sequence.")}return asn1};ASN1._toArray=function toArray(next,opts){var typ=opts.json?Enc.numToHex(next.type):next.type;var val=next.value;if(val){if("string"!==typeof val&&opts.json){val=Enc.bufToHex(val)}return[typ,val]}return[typ,next.children.map(function(child){return toArray(child,opts)})]};ASN1.parse=function(opts){var opts2={json:false!==opts.json};var verbose=ASN1.parseVerbose(opts.der,opts2);if(opts.verbose){return verbose}return ASN1._toArray(verbose,opts2)};ASN1._replacer=function(k,v){if("type"===k){return"0x"+Enc.numToHex(v)}if(v&&"value"===k){return"0x"+Enc.bufToHex(v.data||v)}return v};function Any(){var args=Array.prototype.slice.call(arguments);var typ=args.shift();var str=args.join("").replace(/\s+/g,"").toLowerCase();var len=str.length/2;var lenlen=0;var hex=typ;if("number"===typeof hex){hex=Enc.numToHex(hex)}if(len!==Math.round(len)){throw new Error("invalid hex")}if(len>127){lenlen+=1;while(len>255){lenlen+=1;len=len>>8}}if(lenlen){hex+=Enc.numToHex(128+lenlen)}return hex+Enc.numToHex(str.length/2)+str}ASN1.Any=Any;ASN1.UInt=function UINT(){var str=Array.prototype.slice.call(arguments).join("");var first=parseInt(str.slice(0,2),16);if(128&first){str="00"+str}return Any("02",str)};ASN1.BitStr=function BITSTR(){var str=Array.prototype.slice.call(arguments).join("");return Any("03","00"+str)};ASN1._toArray=function toArray(next,opts){var typ=opts.json?Enc.numToHex(next.type):next.type;var val=next.value;if(val){if("string"!==typeof val&&opts.json){val=Enc.bufToHex(val)}return[typ,val]}return[typ,next.children.map(function(child){return toArray(child,opts)})]};ASN1._pack=function(arr){var typ=arr[0];if("number"===typeof arr[0]){typ=Enc.numToHex(arr[0])}var str="";if(Array.isArray(arr[1])){arr[1].forEach(function(a){str+=ASN1._pack(a)})}else if("string"===typeof arr[1]){str=arr[1]}else if(arr[1].byteLength){str=Enc.bufToHex(arr[1])}else{throw new Error("unexpected array")}if("03"===typ){return ASN1.BitStr(str)}else if("02"===typ){return ASN1.UInt(str)}else{return Any(typ,str)}};ASN1.pack=function(asn1,opts){if(!opts){opts={}}if(!Array.isArray(asn1)){asn1=ASN1._toArray(asn1,{json:true})}var result=ASN1._pack(asn1);if(opts.json){return result}return Enc.hexToBuf(result)}})();
/*! WebAuthn-Local-Client: walc.js
v0.999.7 (c) 2024 Kyle Simpson
v0.1000.2 (c) 2024 Kyle Simpson
MIT License: http://getify.mit-license.org
*/
import{sodium as e,CBOR as t,ASN1 as r}from"./external.js";const n=[{name:"Ed25519",COSEID:-8,cipherOpts:{name:"Ed25519",hash:{name:"SHA-512"}}},{name:"ES256",COSEID:-7,cipherOpts:{name:"ECDSA",namedCurve:"P-256",hash:{name:"SHA-256"}}},{name:"RSASSA-PSS",COSEID:-37,cipherOpts:{name:"RSA-PSS",hash:{name:"SHA-256"}}},{name:"RS256",COSEID:-257,cipherOpts:{name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}}}],i=Object.fromEntries(n.flatMap((e=>[[e.name,e],[e.COSEID,e]]))),a=Symbol("credential-type"),o=Symbol("reset-abort"),s="undefined"!=typeof navigator&&void 0!==navigator.credentials&&void 0!==navigator.credentials.create&&void 0!==navigator.credentials.get&&"undefined"!=typeof PublicKeyCredential&&void 0!==PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable&&await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),l=s&&void 0!==PublicKeyCredential.isConditionalMediationAvailable&&await PublicKeyCredential.isConditionalMediationAvailable();export{s as supportsWebAuthn,l as supportsConditionalMediation,regDefaults,register,authDefaults,auth,verifyAuthResponse,packPublicKeyJSON,unpackPublicKeyJSON,toBase64String,fromBase64String,toUTF8String,fromUTF8String,o as resetAbortReason};var u={supportsWebAuthn:s,supportsConditionalMediation:l,regDefaults:regDefaults,register:register,authDefaults:authDefaults,auth:auth,verifyAuthResponse:verifyAuthResponse,packPublicKeyJSON:packPublicKeyJSON,unpackPublicKeyJSON:unpackPublicKeyJSON,toBase64String:toBase64String,fromBase64String:fromBase64String,toUTF8String:toUTF8String,fromUTF8String:fromUTF8String,resetAbortReason:o};export default u;async function register(n=regDefaults()){try{if(s){n[n[a]].excludeCredentials=normalizeCredentialsList(n[n[a]].excludeCredentials);let i=await navigator.credentials.create(n),o=new Uint8Array(i.response.clientDataJSON),s=JSON.parse(toUTF8String(o));if("webauthn.create"!=s.type)throw new Error("Invalid registration response");let l=e.to_base64(n[n[a]].challenge,e.base64_variants.URLSAFE_NO_PADDING);if(s.challenge!=l)throw new Error("Challenge not accepted");let u=i.response.getPublicKeyAlgorithm(),c=new Uint8Array(i.response.getPublicKey()),{algo:g,raw:f}=function parsePublicKeySPKI(t){var n=r.parseVerbose(new Uint8Array(t));return{algo:e.to_hex(findValue(n.children[0])),raw:findValue(n.children[1])};function findValue(e){if(e.value&&e.value instanceof Uint8Array)return e.value;if(e.children)for(let t of e.children){let e=findValue(t);if(null!=e)return e}return null}}(c),y=parseAuthenticatorData(void 0!==i.response.getAuthenticatorData?new Uint8Array(i.response.getAuthenticatorData()):t.decode(i.response.attestationObject).authData);if(!checkRPID(y.rpIdHash,n.relyingPartyID))throw new Error("Unexpected relying-party ID");return 0==y.signCount&&delete y.signCount,{request:{credentialType:i.type,...n[n[a]],challenge:toBase64String(n[n[a]].challenge),...Object.fromEntries(Object.entries(s).filter((([e,t])=>["origin","crossOrigin"].includes(e))))},response:{credentialID:toBase64String(new Uint8Array(i.rawId)),credentialType:i.type,authenticatorAttachment:i.authenticatorAttachment,publicKey:{algoCOSE:u,algoOID:g,spki:c,raw:f},...Object.fromEntries(Object.entries(y).filter((([e,t])=>["flags","signCount","userPresence","userVerification"].includes(e)))),raw:i.response}}}throw new Error("WebAuthentication not supported on this device")}catch(e){if(e!=o)throw new Error("Credential registration failed",{cause:e})}}function regDefaults({credentialType:t="publicKey",authenticatorSelection:{authenticatorAttachment:r="platform",userVerification:i="required",residentKey:o="required",requireResidentKey:s=!0,...l}={},relyingPartyID:u=document.location.hostname,relyingPartyName:c="wacg",attestation:g="none",challenge:f=e.randombytes_buf(20),excludeCredentials:y=[],user:{name:d="wacg-user",displayName:p=d,id:h=e.randombytes_buf(5)}={},publicKeyCredentialParams:S=n.map((e=>({type:"public-key",alg:e.COSEID}))),signal:b,...m}={}){var w={[t]:{authenticatorSelection:{authenticatorAttachment:r,userVerification:i,residentKey:o,requireResidentKey:s,...l},attestation:g,rp:{id:u,name:c},user:{name:d,displayName:p,id:h},challenge:f,excludeCredentials:y,pubKeyCredParams:S,...m},...null!=b?{signal:b}:null};return Object.defineProperty(w,a,{enumerable:!1,writable:!1,configurable:!1,value:t}),w}async function auth(t=authDefaults()){try{if(s){t[t[a]].allowCredentials=normalizeCredentialsList(t[t[a]].allowCredentials);let r=await navigator.credentials.get(t),n=new Uint8Array(r.response.clientDataJSON),i=JSON.parse(toUTF8String(n));if("webauthn.get"!=i.type)throw new Error("Invalid auth response");let o=e.to_base64(t[t[a]].challenge,e.base64_variants.URLSAFE_NO_PADDING);if(i.challenge!=o)throw new Error("Challenge not accepted");let s=parseAuthenticatorData(new Uint8Array(r.response.authenticatorData));if(!checkRPID(s.rpIdHash,t.relyingPartyID))throw new Error("Unexpected relying-party ID");0==s.signCount&&delete s.signCount;let l=new Uint8Array(r.response.signature);return{request:{credentialType:r.type,mediation:t.mediation,...t[t[a]],...Object.fromEntries(Object.entries(i).filter((([e,t])=>["origin","crossOrigin"].includes(e))))},response:{credentialID:toBase64String(new Uint8Array(r.rawId)),signature:l,...Object.fromEntries(Object.entries(s).filter((([e,t])=>["flags","signCount","userPresence","userVerification"].includes(e)))),...null!=r.response.userHandle?{userID:new Uint8Array(r.response.userHandle)}:null,raw:r.response}}}throw new Error("WebAuthentication not supported on this device")}catch(e){if(e!=o)throw new Error("Credential auth failed",{cause:e})}}function authDefaults({credentialType:t="publicKey",relyingPartyID:r=document.location.hostname,userVerification:n="required",challenge:i=e.randombytes_buf(20),allowCredentials:o=[],mediation:s="optional",signal:l,...u}={}){var c={[t]:{rpId:r,userVerification:n,challenge:i,allowCredentials:o},mediation:s,...null!=l?{signal:l}:null,...u};return Object.defineProperty(c,a,{enumerable:!1,writable:!1,configurable:!1,value:t}),c}async function verifyAuthResponse({signature:t,raw:{clientDataJSON:n,authenticatorData:a}}={},{algoCOSE:o,spki:s,raw:l}={}){try{if(t&&n&&a&&s&&l&&Number.isInteger(o)){let u=function parseSignature(e,t){if(isPublicKeyAlgorithm("ES256",e)){let e=r.parseVerbose(t);return new Uint8Array([...e.children[0].value,...e.children[1].value])}return t}(o,t),c=await async function computeVerificationData(e,t){var r=await computeSHA256Hash(t),n=new Uint8Array(e.byteLength+r.byteLength);return n.set(new Uint8Array(e),0),n.set(r,e.byteLength),n}(a,n),g=await(isPublicKeyAlgorithm("Ed25519",o)?function verifySignatureSodium(t,r,n,i){if(isPublicKeyAlgorithm("Ed25519",r))try{return e.crypto_sign_verify_detached(n,i,t)}catch(e){return console.log(e),!1}throw new Error("Unrecognized signature for sodium verification")}(l,o,u,c):isPublicKeyAlgorithm("ES256",o)||isPublicKeyAlgorithm("RS256",o)||isPublicKeyAlgorithm("RSASSA-PSS",o)?async function verifySignatureSubtle(e,t,r,n){if(isPublicKeyAlgorithm("ES256",t)||isPublicKeyAlgorithm("RSASSA-PSS",t)||isPublicKeyAlgorithm("RS256",t))try{let a=await crypto.subtle.importKey("spki",e,i[t].cipherOpts,!1,["verify"]);return await crypto.subtle.verify(i[t].cipherOpts,a,r,n)}catch(e){return console.log(e),!1}throw new Error("Unrecognized signature for subtle-crypto verification")}(s,o,u,c):null);if(null==g)throw new Error("Unrecognized signature, failed validation");return g}throw new Error("Auth verification missing required inputs")}catch(e){throw new Error("Auth verification failed",{cause:e})}}function parseAuthenticatorData(e){return{rpIdHash:e.slice(0,32),flags:e[32],userPresence:!(1&~e[32]),userVerification:!(4&~e[32]),signCount:byteArrayTo32Int(e.slice(33,37))}}async function checkRPID(e,t){var r=await computeSHA256Hash(fromUTF8String(t));return e.length>0&&e.byteLength==r.byteLength&&e.toString()==r.toString()}function byteArrayTo32Int(e){if(e.byteLength<4){let t=new Uint8Array(4);t.set(e,4-e.byteLength),e=t}return new DataView(e.buffer).getInt32(0)}async function computeSHA256Hash(e){return new Uint8Array(await window.crypto.subtle.digest("SHA-256",new Uint8Array(e)))}function isPublicKeyAlgorithm(e,t){return i[e]==i[t]}function packPublicKeyJSON(e,t=!1){return e={...e,spki:"string"!=typeof e.spki?toBase64String(e.spki):e.spki,raw:"string"!=typeof e.raw?toBase64String(e.raw):e.raw},t?JSON.stringify(e):e}function unpackPublicKeyJSON(e){var t="string"==typeof e?JSON.parse(e):e;return{...t,spki:"string"==typeof t.spki?fromBase64String(t.spki):t.spki,raw:"string"==typeof t.raw?fromBase64String(t.raw):t.raw}}function normalizeCredentialsList(e){if(Array.isArray(e))return e.map((e=>({...e,id:"string"==typeof e.id?fromBase64String(e.id):e.id})))}function toBase64String(t){return e.to_base64(t,e.base64_variants.ORIGINAL)}function fromBase64String(t){return e.from_base64(t,e.base64_variants.ORIGINAL)}function toUTF8String(t){return e.to_string(t)}function fromUTF8String(t){return e.from_string(t)}
import{sodium as e,CBOR as t,ASN1 as r}from"./external.js";const n=[{name:"Ed25519",COSEID:-8,cipherOpts:{name:"Ed25519",hash:{name:"SHA-512"}}},{name:"ES256",COSEID:-7,cipherOpts:{name:"ECDSA",namedCurve:"P-256",hash:{name:"SHA-256"}}},{name:"RSASSA-PSS",COSEID:-37,cipherOpts:{name:"RSA-PSS",hash:{name:"SHA-256"}}},{name:"RS256",COSEID:-257,cipherOpts:{name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}}}],i=Object.fromEntries(n.flatMap((e=>[[e.name,e],[e.COSEID,e]]))),a=Symbol("credential-type"),o=Symbol("reset-abort"),s="undefined"!=typeof navigator&&void 0!==navigator.credentials&&void 0!==navigator.credentials.create&&void 0!==navigator.credentials.get&&"undefined"!=typeof PublicKeyCredential&&void 0!==PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable&&await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),l=s&&void 0!==PublicKeyCredential.isConditionalMediationAvailable&&await PublicKeyCredential.isConditionalMediationAvailable();export{s as supportsWebAuthn,l as supportsConditionalMediation,regDefaults,register,authDefaults,auth,verifyAuthResponse,packPublicKeyJSON,unpackPublicKeyJSON,toBase64String,fromBase64String,toUTF8String,fromUTF8String,o as resetAbortReason};var u={supportsWebAuthn:s,supportsConditionalMediation:l,regDefaults:regDefaults,register:register,authDefaults:authDefaults,auth:auth,verifyAuthResponse:verifyAuthResponse,packPublicKeyJSON:packPublicKeyJSON,unpackPublicKeyJSON:unpackPublicKeyJSON,toBase64String:toBase64String,fromBase64String:fromBase64String,toUTF8String:toUTF8String,fromUTF8String:fromUTF8String,resetAbortReason:o};export default u;async function register(n=regDefaults()){try{if(s){n[n[a]].excludeCredentials=normalizeCredentialsList(n[n[a]].excludeCredentials);let i=await navigator.credentials.create(n),o=new Uint8Array(i.response.clientDataJSON),s=JSON.parse(toUTF8String(o));if("webauthn.create"!=s.type)throw new Error("Invalid registration response");let l=e.to_base64(n[n[a]].challenge,e.base64_variants.URLSAFE_NO_PADDING);if(s.challenge!=l)throw new Error("Challenge not accepted");let u=i.response.getPublicKeyAlgorithm(),c=new Uint8Array(i.response.getPublicKey()),{algo:g,raw:f}=function parsePublicKeySPKI(t){var n=r.parseVerbose(t);return{algo:e.to_hex(findValue(n.children[0])),raw:findValue(n.children[1])};function findValue(e){if(e.value&&e.value instanceof Uint8Array)return e.value;if(e.children)for(let t of e.children){let e=findValue(t);if(null!=e)return e}return null}}(c),y=parseAuthenticatorData(void 0!==i.response.getAuthenticatorData?new Uint8Array(i.response.getAuthenticatorData()):t.decode(i.response.attestationObject).authData);if(!checkRPID(y.rpIdHash,n.relyingPartyID))throw new Error("Unexpected relying-party ID");return 0==y.signCount&&delete y.signCount,{request:{credentialType:i.type,...n[n[a]],challenge:toBase64String(n[n[a]].challenge),...Object.fromEntries(Object.entries(s).filter((([e,t])=>["origin","crossOrigin"].includes(e))))},response:{credentialID:toBase64String(new Uint8Array(i.rawId)),credentialType:i.type,authenticatorAttachment:i.authenticatorAttachment,publicKey:{algoCOSE:u,algoOID:g,spki:c,raw:f},...Object.fromEntries(Object.entries(y).filter((([e,t])=>["flags","signCount","userPresence","userVerification"].includes(e)))),raw:i.response}}}throw new Error("WebAuthentication not supported on this device")}catch(e){if(e!=o)throw new Error("Credential registration failed",{cause:e})}}function regDefaults({credentialType:t="publicKey",authenticatorSelection:{authenticatorAttachment:r="platform",userVerification:i="required",residentKey:o="required",requireResidentKey:s=!0,...l}={},relyingPartyID:u=document.location.hostname,relyingPartyName:c="wacl",attestation:g="none",challenge:f=e.randombytes_buf(20),excludeCredentials:y=[],user:{name:d="wacl-user",displayName:p=d,id:h=e.randombytes_buf(5)}={},publicKeyCredentialParams:S=n.map((e=>({type:"public-key",alg:e.COSEID}))),signal:b,...m}={}){var w={[t]:{authenticatorSelection:{authenticatorAttachment:r,userVerification:i,residentKey:o,requireResidentKey:s,...l},attestation:g,rp:{id:u,name:c},user:{name:d,displayName:p,id:h},challenge:f,excludeCredentials:y,pubKeyCredParams:S,...m},...null!=b?{signal:b}:null};return Object.defineProperty(w,a,{enumerable:!1,writable:!1,configurable:!1,value:t}),w}async function auth(t=authDefaults()){try{if(s){t[t[a]].allowCredentials=normalizeCredentialsList(t[t[a]].allowCredentials);let r=await navigator.credentials.get(t),n=new Uint8Array(r.response.clientDataJSON),i=JSON.parse(toUTF8String(n));if("webauthn.get"!=i.type)throw new Error("Invalid auth response");let o=e.to_base64(t[t[a]].challenge,e.base64_variants.URLSAFE_NO_PADDING);if(i.challenge!=o)throw new Error("Challenge not accepted");let s=parseAuthenticatorData(new Uint8Array(r.response.authenticatorData));if(!checkRPID(s.rpIdHash,t.relyingPartyID))throw new Error("Unexpected relying-party ID");0==s.signCount&&delete s.signCount;let l=new Uint8Array(r.response.signature);return{request:{credentialType:r.type,mediation:t.mediation,...t[t[a]],...Object.fromEntries(Object.entries(i).filter((([e,t])=>["origin","crossOrigin"].includes(e))))},response:{credentialID:toBase64String(new Uint8Array(r.rawId)),signature:l,...Object.fromEntries(Object.entries(s).filter((([e,t])=>["flags","signCount","userPresence","userVerification"].includes(e)))),...null!=r.response.userHandle?{userID:new Uint8Array(r.response.userHandle)}:null,raw:r.response}}}throw new Error("WebAuthentication not supported on this device")}catch(e){if(e!=o)throw new Error("Credential auth failed",{cause:e})}}function authDefaults({credentialType:t="publicKey",relyingPartyID:r=document.location.hostname,userVerification:n="required",challenge:i=e.randombytes_buf(20),allowCredentials:o=[],mediation:s="optional",signal:l,...u}={}){var c={[t]:{rpId:r,userVerification:n,challenge:i,allowCredentials:o},mediation:s,...null!=l?{signal:l}:null,...u};return Object.defineProperty(c,a,{enumerable:!1,writable:!1,configurable:!1,value:t}),c}async function verifyAuthResponse({signature:t,raw:{clientDataJSON:n,authenticatorData:a}}={},{algoCOSE:o,spki:s,raw:l}={}){try{if(t&&n&&a&&s&&l&&Number.isInteger(o)){let u=function parseSignature(e,t){if(isPublicKeyAlgorithm("ES256",e)){let e=r.parseVerbose(t);return new Uint8Array([...e.children[0].value,...e.children[1].value])}return t}(o,t),c=await async function computeVerificationData(e,t){var r=await computeSHA256Hash(t),n=new Uint8Array(e.byteLength+r.byteLength);return n.set(new Uint8Array(e),0),n.set(r,e.byteLength),n}(a,n),g=await(isPublicKeyAlgorithm("Ed25519",o)?function verifySignatureSodium(t,r,n,i){if(isPublicKeyAlgorithm("Ed25519",r))try{return e.crypto_sign_verify_detached(n,i,t)}catch(e){return console.log(e),!1}throw new Error("Unrecognized signature for sodium verification")}(l,o,u,c):isPublicKeyAlgorithm("ES256",o)||isPublicKeyAlgorithm("RS256",o)||isPublicKeyAlgorithm("RSASSA-PSS",o)?async function verifySignatureSubtle(e,t,r,n){if(isPublicKeyAlgorithm("ES256",t)||isPublicKeyAlgorithm("RSASSA-PSS",t)||isPublicKeyAlgorithm("RS256",t))try{let a=await crypto.subtle.importKey("spki",e,i[t].cipherOpts,!1,["verify"]);return await crypto.subtle.verify(i[t].cipherOpts,a,r,n)}catch(e){return console.log(e),!1}throw new Error("Unrecognized signature for subtle-crypto verification")}(s,o,u,c):null);if(null==g)throw new Error("Unrecognized signature, failed validation");return g}throw new Error("Auth verification missing required inputs")}catch(e){throw new Error("Auth verification failed",{cause:e})}}function parseAuthenticatorData(e){return{rpIdHash:e.slice(0,32),flags:e[32],userPresence:!(1&~e[32]),userVerification:!(4&~e[32]),signCount:byteArrayTo32Int(e.slice(33,37))}}async function checkRPID(e,t){var r=await computeSHA256Hash(fromUTF8String(t));return e.length>0&&e.byteLength==r.byteLength&&e.toString()==r.toString()}function byteArrayTo32Int(e){if(e.byteLength<4){let t=new Uint8Array(4);t.set(e,4-e.byteLength),e=t}return new DataView(e.buffer).getInt32(0)}async function computeSHA256Hash(e){return new Uint8Array(await window.crypto.subtle.digest("SHA-256",new Uint8Array(e)))}function isPublicKeyAlgorithm(e,t){return i[e]==i[t]}function packPublicKeyJSON(e,t=!1){return e={...e,spki:"string"!=typeof e.spki?toBase64String(e.spki):e.spki,raw:"string"!=typeof e.raw?toBase64String(e.raw):e.raw},t?JSON.stringify(e):e}function unpackPublicKeyJSON(e){var t="string"==typeof e?JSON.parse(e):e;return{...t,spki:"string"==typeof t.spki?fromBase64String(t.spki):t.spki,raw:"string"==typeof t.raw?fromBase64String(t.raw):t.raw}}function normalizeCredentialsList(e){if(Array.isArray(e))return e.map((e=>({...e,id:"string"==typeof e.id?fromBase64String(e.id):e.id})))}function toBase64String(t){return e.to_base64(t,e.base64_variants.ORIGINAL)}function fromBase64String(t){return e.from_base64(t,e.base64_variants.ORIGINAL)}function toUTF8String(t){return e.to_string(t)}function fromUTF8String(t){return e.from_string(t)}
/*! Local-Data-Lock: ldl.js
v0.12.0 (c) 2024 Kyle Simpson
v0.13.0 (c) 2024 Kyle Simpson
MIT License: http://getify.mit-license.org
*/
import{supportsWebAuthn as e,regDefaults as t,register as r,authDefaults as n,auth as a,verifyAuthResponse as i,packPublicKeyJSON as o,unpackPublicKeyJSON as l,toBase64String as c,fromBase64String as s,toUTF8String as y,fromUTF8String as u,resetAbortReason as p}from"@lo-fi/webauthn-local-client";const f=1,d=sodium.crypto_sign_SEEDBYTES;var k=setLockKeyCacheLifetime(18e5),g="idb",b=null,h=null,w={},K=null,L=new WeakMap;export{e as supportsWebAuthn,o as packPublicKeyJSON,l as unpackPublicKeyJSON,c as toBase64String,s as fromBase64String,y as toUTF8String,u as fromUTF8String,p as resetAbortReason,listLocalIdentities,clearLockKeyCache,removeLocalAccount,getLockKey,generateEntropy,deriveLockKey,lockData,unlockData,configure};var m={supportsWebAuthn:e,packPublicKeyJSON:o,unpackPublicKeyJSON:l,toBase64String:c,fromBase64String:s,toUTF8String:y,fromUTF8String:u,resetAbortReason:p,listLocalIdentities:listLocalIdentities,clearLockKeyCache:clearLockKeyCache,removeLocalAccount:removeLocalAccount,getLockKey:getLockKey,generateEntropy:generateEntropy,deriveLockKey:deriveLockKey,lockData:lockData,unlockData:unlockData,configure:configure};export default m;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:o="local-user",displayName:l="Local User",relyingPartyID:s=document.location.hostname,relyingPartyName:y="Local Data Lock",addNewPasskey:u=!1,resetLockKey:p=!1,useLockKey:f=null,verify:g=!0,signal:b}={}){await checkStorage();var L=null!=e?h[e]:null;if(null!=L){let t=function getCachedLockKey(e){var t=Date.now();if(e in w&&w[e].timestamp>=t-Math.min(k,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(K),K=null,null!=e&&(L.lastSeq=e.lastSeq,L.passkeys=[...L.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(K),K=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=n({relyingPartyID:s,mediation:"optional",allowCredentials:L.passkeys.map((({credentialID:e})=>({type:"public-key",id:e}))),signal:K.signal}),r=await a(t);if(cleanupExternalSignalHandler(K),K=null,null!=r){if(g){let e=L.passkeys.find((e=>e.credentialID==r.response.credentialID)),t=null!=e?e.publicKey:null;if(!(null!=t&&await i(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(K),K=null,null!=t&&null!=r)return h[e]=t,cacheLockKey(e,r),await storeLocalIdentities(),Object.freeze({...r,localIdentity:e})}else{resetAbortToken(b);let t=n({relyingPartyID:s,mediation:"optional",signal:K.signal}),r=await a(t);if(cleanupExternalSignalHandler(K),K=null,null!=r){let t=extractLockKey(r),[n]=Object.entries(h).find((([,e])=>null!=e.passkeys.find((e=>e.credentialID==r.response.credentialID))))||[];if(null!=n){if(delete w[e],L=h[e=n],g){let e=L.passkeys.find((e=>e.credentialID==r.response.credentialID)),t=null!=e?e.publicKey:null;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(n=deriveLockKey()){try{let i=((h[e]||{}).lastSeq||0)+1,c=new Uint8Array(n.iv.byteLength+2),u=new DataView(new ArrayBuffer(2));u.setInt16(0,i,!1),c.set(n.iv,0),c.set(new Uint8Array(u.buffer),n.iv.byteLength);let p=t({relyingPartyID:s,relyingPartyName:y,user:{id:c,name:o,displayName:l},signal:K.signal}),f=await r(p);if(null!=f)return{record:{lastSeq:i,passkeys:[(a={seq:i,credentialID:f.response.credentialID,publicKey:f.response.publicKey},{...a,hash:computePasskeyEntryHash(a)})]},lockKey:n}}catch(e){throw new Error("Identity/Passkey registration failed",{cause:e})}var a}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(K&&(cleanupExternalSignalHandler(K),K.aborted||K.abort("Passkey operation abandoned.")),K=new AbortController,null!=e)if(e.aborted)K.abort(e.reason);else{let handlerFn=()=>{cleanupExternalSignalHandler(K),K.abort(e.reason),K=e=handlerFn=null};e.addEventListener("abort",handlerFn),L.set(K,[e,handlerFn])}}function cleanupExternalSignalHandler(e){if(null!=e&&L.has(e)){let[t,r]=L.get(e);t.removeEventListener("abort",r),L.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 n=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==e)throw new Error("Non-empty data required.");let a=sodium.crypto_box_seal(n,t.encPK);return["base64","base-64"].includes(r.toLowerCase())?c(a):a}catch(e){throw new Error("Data encryption failed.",{cause:e})}}function unlockData(e,t,{outputFormat:r="utf8",parseJSON:n=!0}={}){try{let a=sodium.crypto_box_seal_open("string"==typeof e?s(e):e,t.encPK,t.encSK);if(["utf8","utf-8"].includes(r.toLowerCase())){let e=y(a);return n?JSON.parse(e):e}return a}catch(e){throw new Error("Data decryption 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:o(e.publicKey)})))}])));Object.keys(e).length>0?await b.set("local-identities",e):await b.remove("local-identities")}function setLockKeyCacheLifetime(e){return k=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"].includes(e))g=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,g=e.storageType,h=null}}(e),null!=t&&setLockKeyCacheLifetime(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==b){if(!["idb","local-storage","session-storage","cookie","opfs"].includes(g))throw new Error(`Unrecognized storage type ('${g}')`);b=await import(`@lo-fi/client-storage/${g}`)}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:l(e.publicKey)})))}])))}())}
import{supportsWebAuthn as e,regDefaults as t,register as r,authDefaults as n,auth as a,verifyAuthResponse as i,packPublicKeyJSON as o,unpackPublicKeyJSON as l,toBase64String as c,fromBase64String as s,toUTF8String as y,fromUTF8String as u,resetAbortReason as f}from"@lo-fi/webauthn-local-client";const p=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,o as packPublicKeyJSON,l as unpackPublicKeyJSON,c as toBase64String,s as fromBase64String,y as toUTF8String,u as fromUTF8String,f as resetAbortReason,listLocalIdentities,clearLockKeyCache,removeLocalAccount,getLockKey,generateEntropy,deriveLockKey,lockData,unlockData,signData,verifySignature,configure};var L={supportsWebAuthn:e,packPublicKeyJSON:o,unpackPublicKeyJSON:l,toBase64String:c,fromBase64String:s,toUTF8String:y,fromUTF8String:u,resetAbortReason:f,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:o="local-user",displayName:l="Local User",relyingPartyID:s=document.location.hostname,relyingPartyName:y="Local Data Lock",addNewPasskey:u=!1,resetLockKey:f=!1,useLockKey:p=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&&!f){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],f){if(resetAbortToken(b),({record:h[e],lockKey:t}=await registerLocalIdentity(p&&"object"==typeof p?checkLockKey(p):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=n({relyingPartyID:s,mediation:"optional",allowCredentials:K.passkeys.map((({credentialID:e})=>({type:"public-key",id:e}))),signal:m.signal}),r=await a(t);if(cleanupExternalSignalHandler(m),m=null,null!=r){if(k){let e=K.passkeys.find((e=>e.credentialID==r.response.credentialID)),t=null!=e?e.publicKey:null;if(!(null!=t&&await i(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(p&&"object"==typeof p?checkLockKey(p):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=n({relyingPartyID:s,mediation:"optional",signal:m.signal}),r=await a(t);if(cleanupExternalSignalHandler(m),m=null,null!=r){let t=extractLockKey(r),[n]=Object.entries(h).find((([,e])=>null!=e.passkeys.find((e=>e.credentialID==r.response.credentialID))))||[];if(null!=n){if(delete w[e],K=h[e=n],k){let e=K.passkeys.find((e=>e.credentialID==r.response.credentialID)),t=null!=e?e.publicKey:null;if(!(null!=t&&await i(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(n=deriveLockKey()){try{let i=((h[e]||{}).lastSeq||0)+1,c=new Uint8Array(n.iv.byteLength+2),u=new DataView(new ArrayBuffer(2));u.setInt16(0,i,!1),c.set(n.iv,0),c.set(new Uint8Array(u.buffer),n.iv.byteLength);let f=t({relyingPartyID:s,relyingPartyName:y,user:{id:c,name:o,displayName:l},signal:m.signal}),p=await r(f);if(null!=p)return{record:{lastSeq:i,passkeys:[(a={seq:i,credentialID:p.response.credentialID,publicKey:p.response.publicKey},{...a,hash:computePasskeyEntryHash(a)})]},lockKey:n}}catch(e){throw new Error("Identity/Passkey registration failed",{cause:e})}var a}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:p,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===p)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 n=dataToBuffer(e),a=sodium.crypto_box_seal(n,t.encPK);return["base64","base-64"].includes(r.toLowerCase())?c(a):a}catch(e){throw new Error("Data encryption failed.",{cause:e})}}function unlockData(e,t,{outputFormat:r="utf8",parseJSON:n=!0}={}){try{let a=sodium.crypto_box_seal_open("string"==typeof e?s(e):e,t.encPK,t.encSK);if(["utf8","utf-8"].includes(r.toLowerCase())){let e=y(a);return n?JSON.parse(e):e}return a}catch(e){throw new Error("Data decryption failed.",{cause:e})}}function signData(e,{privateKey:t}={},{outputFormat:r="base64"}={}){try{let n=sodium.crypto_sign_detached(dataToBuffer(e),t);return["base64","base-64"].includes(r.toLowerCase())?c(n):n}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?s(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:o(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"].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:o(r.publicKey)})))}async function checkStorage(){if(null==b){if(!["idb","local-storage","session-storage","cookie","opfs"].includes(k))throw new Error(`Unrecognized storage type ('${k}')`);b=await import(`@lo-fi/client-storage/${k}`)}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:l(e.publicKey)})))}])))}())}

@@ -5,9 +5,9 @@ # Deploying Local-Data-Lock WITHOUT A Bundler

Then copy over all `dist/auto/*` contents, as-is:
Then copy over all `@lo-fi/local-data-lock/dist/auto/*` contents, as-is:
* `dist/auto/ldl.js`
* `@lo-fi/local-data-lock/dist/auto/ldl.js`
**Note:** this is *not* the same as `dist/bundlers/ldl.mjs`, which is only intended [for web application projects WITH a bundler](BUNDLERS.md)
**Note:** this is *not* the same as `@lo-fi/local-data-lock/dist/bundlers/ldl.mjs`, which is only intended [for web application projects WITH a bundler](BUNDLERS.md)
* `dist/auto/external/*` (preserve the whole `external/` sub-directory):
* `@lo-fi/local-data-lock/dist/auto/external/*` (preserve the whole `external/` sub-directory):
- `@lo-fi/webauthn-local-client/walc.js`

@@ -14,0 +14,0 @@ - `@lo-fi/webauthn-local-client/external.js`

{
"name": "@lo-fi/local-data-lock",
"description": "Protect local-first app data with encryption/decryption key secured in WebAuthn (biometric) passkeys",
"version": "0.12.0",
"version": "0.13.0",
"exports": {

@@ -25,3 +25,3 @@ ".": "./dist/bundlers/ldl.mjs",

"@lo-fi/client-storage": "~0.9.0",
"@lo-fi/webauthn-local-client": "~0.999.7"
"@lo-fi/webauthn-local-client": "~0.1000.2"
},

@@ -28,0 +28,0 @@ "devDependencies": {

@@ -6,3 +6,3 @@ # Local Data Lock

**Local Data Lock** provides a simple utility interface for encrypting and decrypting local-first application data using a keypair stored and protected by [WebAuthn](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API) (biometric passkeys), via the [**WebAuthn Local Client** library](https://github.com/mylofi/webauthn-local-client) -- no servers required!
**Local Data Lock** provides a simple utility interface for encrypting and decrypting (and producing digital signatures for) local-first application data using a keypair stored and protected by [WebAuthn](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API) (biometric passkeys), via the [**WebAuthn Local Client** library](https://github.com/mylofi/webauthn-local-client) -- no servers required!

@@ -29,3 +29,3 @@ ```js

However, the encrypted data (by default, represented as a base64 encoded string) might be transmitted and stored elsewhere, such as on an app's servers. The cryptographic keypair may also be used for digital signatures to verify secure data transmission.
However, the encrypted data (by default, represented as a base64 encoded string) might be transmitted and stored elsewhere, such as on an app's servers. The cryptographic keypair may also be used for digital signatures to verify secure data transmission, using the `signData()` and `verifySignature()` methods.

@@ -287,2 +287,3 @@ This cryptographic keypair is protected locally on the user's device in a biometric passkey; the user can easily unlock (decrypt) their data, or verify a received data transmission from their other device, by presenting a biometric factor to retrieve the keypair.

);
// Uint8Array[ .. ]
```

@@ -322,2 +323,39 @@

## Signing data and verifying signatures
In addition to encryption and decryption, lock-keys can be used for producing and verifying (detached) digital signatures.
To sign a piece of data:
```js
import { signData } from "..";
var signature = signData(someData,lockKey); // "Zt83H.."
```
`someData` can be any string or a JSON-serializable object; any other primitive value will be treated as a string. `lockKey` only strictly requires a `privateKey` property (from a full lock-key value).
The default representation in the return value will be a base64 encoded string (suitable for storing in LocalStorage, transmitting in JSON, etc). If you prefer the `Uint8Array` binary representation:
```js
var signature = signData(
someData,
key,
{ outputFormat: "raw" } // instead of "base64"
);
// Uint8Array[ .. ]
```
To verify a signature:
```js
import { verifySignature } from "..";
verifySignature(someData,lockKey,signature); // true (or false!)
```
Obviously, `someData` needs to hold the exact same data as was passed to `signData()` previously. `lockKey` only strictly requires a `publicKey` property (from a full lock-key value). `signature` may be a string (assumed as the base64 encoded representation) or the raw `Uint8Array` binary representation.
The function returns `true` / `false` for verification -- or throws an exception if the data, key, or signature are malformed/invalid.
## Deriving an encryption/decryption key

@@ -324,0 +362,0 @@

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

unlockData,
signData,
verifySignature,
configure,

@@ -76,2 +78,4 @@ };

unlockData,
signData,
verifySignature,
configure,

@@ -523,28 +527,3 @@ };

try {
let dataBuffer = (
// null/undefined?
data == null ? null :
// raw array buffer?
data instanceof ArrayBuffer ? new Uint8Array(data) :
// already uint8 byte array?
isByteArray(data) ? data :
// encode text to uint8 buffer
fromUTF8String(
// JSON-compatible object (hopefully)?
typeof data == "object" ? JSON.stringify(data) :
// already a string?
typeof data == "string" ? data :
// some other value type that needs to be
// stringified
String(data)
)
);
if (data == null) {
throw new Error("Non-empty data required.");
}
let dataBuffer = dataToBuffer(data);
let encData = sodium.crypto_box_seal(dataBuffer,lockKey.encPK);

@@ -595,2 +574,49 @@ return (

function signData(
data,
/*lockKey=*/{
privateKey,
} = {},
/*options=*/{
outputFormat = "base64", // "base64", "raw"
} = {}
) {
try {
let signatureBuffer = sodium.crypto_sign_detached(
dataToBuffer(data),
privateKey
);
return (
[ "base64", "base-64", ].includes(outputFormat.toLowerCase()) ?
toBase64String(signatureBuffer) :
signatureBuffer
);
}
catch (err) {
throw new Error("Data signature failed.",{ cause: err, });
}
}
function verifySignature(
data,
/*lockKey=*/{
publicKey,
} = {},
signature
) {
try {
return sodium.crypto_sign_verify_detached(
(
typeof signature == "string" ? fromBase64String(signature) :
signature
),
dataToBuffer(data),
publicKey
);
}
catch (err) {
throw new Error("Data signature failed.",{ cause: err, });
}
}
async function loadLocalIdentities() {

@@ -712,2 +738,32 @@ return (

function dataToBuffer(data) {
var dataBuffer = (
// null/undefined?
data == null ? null :
// raw array buffer?
data instanceof ArrayBuffer ? new Uint8Array(data) :
// already uint8 byte array?
isByteArray(data) ? data :
// encode text to uint8 buffer
fromUTF8String(
// JSON-compatible object (hopefully)?
typeof data == "object" ? JSON.stringify(data) :
// already a string?
typeof data == "string" ? data :
// some other value type that needs to be
// stringified
String(data)
)
);
if (dataBuffer == null) {
throw new Error("Non-empty data required.");
}
return dataBuffer;
}
function isByteArray(val) {

@@ -714,0 +770,0 @@ return (

import {
supportsWebAuthn,
listLocalIdentities,

@@ -8,2 +9,4 @@ clearLockKeyCache,

unlockData,
signData,
verifySignature,
configure,

@@ -44,2 +47,3 @@ resetAbortReason,

var saveDataBtn;
var signVerifyBtn;

@@ -75,2 +79,3 @@ var currentAccountID;

saveDataBtn = document.getElementById("save-data-btn");
signVerifyBtn = document.getElementById("sign-verify-btn");

@@ -90,2 +95,3 @@ selectAccountEl.addEventListener("change",changeSelectedAccount,false);

saveDataBtn.addEventListener("click",saveData,false);
signVerifyBtn.addEventListener("click",signAndVerify,false);

@@ -120,2 +126,3 @@ updateElements();

lockAccountBtn.disabled = false;
signVerifyBtn.disabled = false;
accountDataEl.disabled = false;

@@ -127,2 +134,3 @@ }

lockAccountBtn.disabled = true;
signVerifyBtn.disabled = true;
accountDataEl.disabled = true;

@@ -168,2 +176,4 @@ accountDataEl.value = "";

async function promptAddPasskey() {
if (!checkWebAuthnSupport()) return;
var passkeyUsernameEl;

@@ -209,3 +219,3 @@ var passkeyDisplayNameEl;

async preConfirm() {
preConfirm() {
var passkeyUsername = passkeyUsernameEl.value.trim();

@@ -284,2 +294,4 @@ var passkeyDisplayName = passkeyDisplayNameEl.value.trim();

async function detectAccount() {
if (!checkWebAuthnSupport()) return;
var { signal, intv } = createTimeoutToken(passkeyTimeout) || {};

@@ -334,2 +346,4 @@ try {

async function unlockAccount() {
if (!checkWebAuthnSupport()) return;
if (selectAccountEl.selectedIndex == 0) {

@@ -397,2 +411,4 @@ return;

async function resetAccount() {
if (!checkWebAuthnSupport()) return;
var confirmResult = await Swal.fire({

@@ -462,2 +478,4 @@ text: "Resetting an account regenerates a new encryption/decryption key and a new passkey, while discarding previously associated passkeys. Are you sure?",

async function saveData() {
if (!checkWebAuthnSupport()) return;
var { signal, intv } = createTimeoutToken(passkeyTimeout) || {};

@@ -489,2 +507,80 @@ try {

async function signAndVerify() {
if (!checkWebAuthnSupport()) return;
var result = await Swal.fire({
title: "Enter some text to sign",
input: "text",
inputLabel: "Text",
inputValue: accountDataEl.value,
inputAttributes: {
autocapitalize: "off",
},
showConfirmButton: true,
confirmButtonText: "Sign",
confirmButtonColor: "darkslateblue",
showCancelButton: true,
cancelButtonColor: "darkslategray",
allowOutsideClick: true,
allowEscapeKey: true,
preConfirm(textToSign) {
if (!textToSign) {
Swal.showValidationMessage("Please enter text to sign.");
return false;
}
return textToSign;
},
});
if (result.isConfirmed) {
let { signal, intv } = createTimeoutToken(passkeyTimeout) || {};
try {
startSpinner();
let key = await getLockKey({
localIdentity: currentAccountID,
signal,
});
if (intv != null) { clearTimeout(intv); }
let msg = {
text: result.value,
timestamp: Date.now(),
};
let signature = signData(msg,key);
let verified = verifySignature(msg,key,signature);
stopSpinner();
await Swal.fire({
title: "Signature & Verification",
html: `
<div style="text-align:left;">
<p style="white-space:nowrap;">
<code style="max-width:100%;overflow:auto;font-family:monospace;white-space:pre;"><pre>${
JSON.stringify(msg,null," ")
}</pre></code>
</p>
<p style="white-space:pre-line;">
Signature: <strong>${signature}</strong>
</p>
<h2>${verified ? "Verified!" : "Not verified"}</h2>
</div>
`,
showConfirmButton: true,
confirmButtonText: "OK",
confirmButtonColor: "darkslateblue",
showCancelButton: false,
allowOutsideClick: true,
allowEscapeKey: true,
});
}
catch (err) {
if (intv != null) { clearTimeout(intv); }
logError(err);
stopSpinner();
showError("Signing/verifying failed.");
}
}
}
async function unlockAccountData(accountID,key) {

@@ -561,1 +657,8 @@ var data = await loadAccountData(accountID);

}
async function checkWebAuthnSupport() {
if (!supportsWebAuthn) {
showError("Sorry, but this device doesn't seem to support the proper passkey functionality.");
return false;
}
}

Sorry, the diff of this file is not supported yet

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