112 lines
3.9 KiB
HTML
112 lines
3.9 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta charset="UTF-8">
|
||
|
<title>Spectre</title>
|
||
|
|
||
|
<link rel="stylesheet" href="sakura.css"/>
|
||
|
<script src="wasm.js"></script>
|
||
|
<script defer>
|
||
|
const go = new Go();
|
||
|
WebAssembly.instantiateStreaming(fetch("spectre.wasm"), go.importObject).then((result) => {
|
||
|
go.run(result.instance);
|
||
|
|
||
|
const $title = document.getElementById("title");
|
||
|
const $subtitle = document.getElementById("subtitle");
|
||
|
const $username = document.getElementById("username");
|
||
|
const $secret = document.getElementById("secret");
|
||
|
const $counter = document.getElementById("counter");
|
||
|
const $scope = document.getElementById("scope");
|
||
|
const $template = document.getElementById("template");
|
||
|
const $site = document.getElementById("site");
|
||
|
const $password = document.getElementById("password");
|
||
|
|
||
|
// Warning for non-default scoper
|
||
|
if (!defaultScoper) {
|
||
|
$title.innerText = `${$title.innerText}⚠`;
|
||
|
$subtitle.innerText = "This instance is not using the default scoper"
|
||
|
}
|
||
|
|
||
|
// Default scope template
|
||
|
$scope.addEventListener("change", () => {
|
||
|
let tmpl;
|
||
|
switch ($scope.value) {
|
||
|
case "a":
|
||
|
tmpl = "long";
|
||
|
break;
|
||
|
case "i":
|
||
|
tmpl = "name";
|
||
|
break;
|
||
|
case "r":
|
||
|
tmpl = "phrase";
|
||
|
break;
|
||
|
}
|
||
|
$template.value = tmpl;
|
||
|
});
|
||
|
|
||
|
// Generate spectre
|
||
|
let s;
|
||
|
async function checkSpectre() {
|
||
|
if ($username.value === "" || $secret.value === "") return;
|
||
|
s = spectre($username.value, $secret.value);
|
||
|
}
|
||
|
$username.addEventListener("change", () => checkSpectre(), false);
|
||
|
$secret.addEventListener("change", () => checkSpectre(), false);
|
||
|
|
||
|
// Generate password
|
||
|
function checkPassword() {
|
||
|
if ($username.value === "" || $secret.value === "" || $site.value === "") return;
|
||
|
// Site(site, counter, scope, template)
|
||
|
$password.innerText = s.Site($site.value, parseInt($counter.value), $scope.value, $template.value);
|
||
|
}
|
||
|
$counter.addEventListener("change", checkPassword, false);
|
||
|
$scope.addEventListener("change", checkPassword, false);
|
||
|
$template.addEventListener("change", checkPassword, false);
|
||
|
$site.addEventListener("change", checkPassword, false);
|
||
|
});
|
||
|
</script>
|
||
|
</head>
|
||
|
<body>
|
||
|
<h1 id="title">Spectre</h1>
|
||
|
<small id="subtitle"></small>
|
||
|
|
||
|
<hr/>
|
||
|
|
||
|
<label for="username">Username</label>
|
||
|
<input id="username" type="text" placeholder="Robert Lee Mitchell"/>
|
||
|
|
||
|
<label for="secret">Secret</label>
|
||
|
<input id="secret" type="password" placeholder="banana colored duckling"/>
|
||
|
|
||
|
<label for="counter">Counter</label>
|
||
|
<input id="counter" type="number" value="1" min="1"/>
|
||
|
|
||
|
<label for="scope">Scope</label>
|
||
|
<select id="scope">
|
||
|
<option value="a">Authentication</option>
|
||
|
<option value="i">Identification</option>
|
||
|
<option value="r">Recovery</option>
|
||
|
</select>
|
||
|
|
||
|
<label for="template">Template</label>
|
||
|
<select id="template">
|
||
|
<option value="max">Maximum</option>
|
||
|
<option value="long" selected>Long</option>
|
||
|
<option value="med">Medium</option>
|
||
|
<option value="short">Short</option>
|
||
|
<option value="pin">Pin</option>
|
||
|
<option value="name">Name</option>
|
||
|
<option value="phrase">Phrase</option>
|
||
|
<option value="basic">Basic</option>
|
||
|
</select>
|
||
|
|
||
|
<label for="site">Site</label>
|
||
|
<input id="site" type="text" placeholder="twitter.com"/>
|
||
|
|
||
|
<hr/>
|
||
|
|
||
|
<label for="password">Password</label>
|
||
|
<pre id="password"></pre>
|
||
|
|
||
|
</body>
|
||
|
</html>
|