-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
128a1c3
commit 3b7dfe8
Showing
4 changed files
with
216 additions
and
191 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
<div class=""> | ||
<slot /> | ||
</div> | ||
<main class="flex flex-col px-8 py-2 w-screen"> | ||
<h1 class="text-2xl font-semibold mt-4"> | ||
Welcome to Integrity Apps, a Secure Bookmark WebAssembly Loader | ||
</h1> | ||
<slot name="finger" /> | ||
<div class="border-2 border-neutral-400 rounded-lg shadow-md outline-lime-50 w-fit"> | ||
<slot name="link" /> | ||
</div> | ||
<slot name="notification" /> | ||
|
||
<details class="my-4"> | ||
<summary class="my-4 cursor-pointer">FAQs</summary> | ||
|
||
<h2>Why do we need this?</h2> | ||
<p> | ||
We need an app architecture that is secure by default, which means the code <span | ||
class="highlighter">cannot change behind your back</span | ||
>, especially when it comes to sensitive data with secrets and personal information. Even the | ||
most cutting edge cryptography organizations are using Browser extensions or Mobile Apps to | ||
hold these secrets, both of which can change code without you knowing. But the | ||
<a | ||
href="https://github.com/coins/secure-bookmark?tab=readme-ov-file#traditional-solutions-do-not-work" | ||
target="_blank">traditional solutions do not work</a | ||
> and this a more secure alternative. | ||
</p> | ||
|
||
<h2>How does this work?</h2> | ||
<p> | ||
When you copy/paste or drag the link into the address bar, the app will be loaded. This is a | ||
secure way to load the app because the app code cannot change behind your back. Once the data | ||
URL has loaded, you can bookmark it and use it in the future. | ||
</p> | ||
|
||
<h2>Why is this secure?</h2> | ||
<p> | ||
This is secure because the browser will check the integrity of the app code before loading it. | ||
This means you (or a nerdy friend) can review the app code once, then know that it hasn't | ||
changed after that. This is important so that "updates" aren't applied without your knowledge | ||
or active consent! | ||
</p> | ||
|
||
<h2>What if I want to update?</h2> | ||
<p> | ||
If you want to update the app, you can simply revisit this page and copy/paste or drag the | ||
link into the address bar again. This will load the new version of the app. If there have been | ||
updates since you last book marked, you'll get a new integrity hash for the new code. | ||
</p> | ||
|
||
<h2>Can I run this page myself?</h2> | ||
<p> | ||
Yes! Everything is public and open source. You can run this page yourself by forking the <a | ||
href="https://github.com/DougAnderson444/integrity-app" | ||
target="_blank">code repository</a | ||
> with one click. GitHub will even host your Intergrity App for you if you like, for free. | ||
</p> | ||
|
||
<h2>What is the app?</h2> | ||
<p> | ||
The Integrity App uses a <a href="https://github.com/DougAnderson444/wurbo" target="_blank" | ||
>Wurbo</a | ||
> Loader by default, which means you can safely load any WebAsembly App that implements the Wurbo | ||
interfaces. Wurbo is a cutting edge Wasm framework that uses a minimal amount of JavaScript to | ||
make the WebAssembly Component interactive, but not enough to make it dangerous. It's just enough | ||
JavaScript to run the WebAssembly Component, nothing else! | ||
</p> | ||
|
||
<h2>What is the Wurbo Loader?</h2> | ||
<p> | ||
The Wurbo Loader is a WebAssembly Loader that uses a minimal amount of JavaScript to make the | ||
WebAssembly Component interactive, but not enough to make it dangerous. It's just enough | ||
JavaScript to run the WebAssembly Component, nothing else! | ||
</p> | ||
</details> | ||
</main> | ||
|
||
<style> | ||
h2 { | ||
@apply text-xl font-semibold mt-8 mb-2; | ||
} | ||
p { | ||
@apply leading-normal; | ||
} | ||
.highlighter { | ||
@apply border-b-2 border-lime-500; | ||
} | ||
a { | ||
@apply border border-neutral-400/50 rounded-lg shadow-md outline-lime-50 px-2 py-1 w-full bg-sky-200/50; | ||
} | ||
a:not(#el_link)::after { | ||
content: '➚'; | ||
margin-left: 0.5rem; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<script> | ||
import { onMount } from 'svelte'; | ||
import { base } from '$app/paths'; | ||
import { encodeURLSafe } from '@stablelib/base64'; | ||
import Finger from '$lib/Finger.svelte'; | ||
import Format from '$lib/Format.svelte'; | ||
/** | ||
* Default wrapper is the Format component | ||
* @type {SvelteComponent} | ||
*/ | ||
export let wrapper = Format; | ||
/** | ||
* @type {string} | ||
*/ | ||
let path; | ||
/** | ||
* @type {string} | ||
*/ | ||
let dataUrl; | ||
/** | ||
* @type {HTMLAnchorElement} | ||
*/ | ||
let el_link; | ||
/** | ||
* @type {HTMLDivElement} | ||
*/ | ||
let el_notification; | ||
/** | ||
* @type {Uint8Array} | ||
*/ | ||
let hash; | ||
let integrity; | ||
// Test whether it's isSafari | ||
let isSafari = false; | ||
onMount(async () => { | ||
const name = 'innerApp.js'; | ||
// fetch the text | ||
const appRaw = await fetch(`${base}/${name}`).then((res) => res.text()); | ||
// generate sha256 Subresource Integrity of app.js (appRaw) | ||
// and use it as integrity attribute of script tag | ||
// to prevent MITM attacks | ||
let algo = 'SHA-256'; | ||
const hashBuffer = await crypto.subtle.digest(algo, new TextEncoder().encode(appRaw)); | ||
hash = new Uint8Array(hashBuffer); | ||
integrity = algo.toLowerCase().replace('-', '') + `-${encodeURLSafe(hash)}`; | ||
path = | ||
window.location.origin + | ||
window.location.pathname.replace('index.html', '').replace(/\/$/, ''); | ||
dataUrl = | ||
`data:text/html,<script src="${path}/${name}" integrity="${integrity}" crossorigin></scr` + | ||
`ipt><!-` + | ||
'-'; | ||
el_link.href = dataUrl; | ||
// FIXME: This device detection is quite fragile | ||
// const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); | ||
isSafari = navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome'); | ||
const isAndroid = navigator.userAgent.toLowerCase().indexOf('android') > -1; | ||
// if safari simply click the link | ||
if (isSafari) { | ||
el_link.textContent = 'Click to open app'; | ||
return; | ||
} | ||
el_link.onclick = (e) => { | ||
e.preventDefault(); | ||
navigator.clipboard.writeText(dataUrl); | ||
el_notification.hidden = false; | ||
setTimeout((_) => (el_notification.hidden = true), 5000); | ||
}; | ||
if (isAndroid) { | ||
// if Android fallback to copy to clipboard | ||
el_link.textContent = 'Click to copy link'; | ||
return; | ||
} | ||
// if Desktop fallback to drag and drop | ||
el_link.textContent = 'Drag me into tab bar'; | ||
}); | ||
</script> | ||
|
||
<svelte:component this={wrapper}> | ||
<svelte:fragment slot="finger"> | ||
{#if !isSafari} | ||
<!-- Safari can just click the link --> | ||
<Finger /> | ||
{/if} | ||
</svelte:fragment> | ||
|
||
<svelte:fragment slot="link"> | ||
<a id="el_link" bind:this={el_link} class="h-full w-full px-4 py-2 overflow-auto block" | ||
>Drag me into tab bar</a | ||
> | ||
</svelte:fragment> | ||
|
||
<svelte:fragment slot="notification"> | ||
<div id="el_notification" bind:this={el_notification} hidden> | ||
✅ Data URL copied to clipboard. Paste it into your browser's address bar. | ||
</div> | ||
</svelte:fragment> | ||
</svelte:component> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,2 @@ | ||
// place files you want to import through the `$lib` alias in this folder. | ||
import { default as Finger } from './Finger.svelte'; | ||
export { Finger }; | ||
export { hashOutputFiles } from './plugin.js'; |
Oops, something went wrong.