diff --git a/public/crypto.js b/public/crypto.js index c483ce12ef622d501be66b193729573ba6693a8d..166cd8a7b0b88d13866851e6b6590bd3185c7250 100644 --- a/public/crypto.js +++ b/public/crypto.js @@ -1,4 +1,4 @@ -export {b58, saltPass2seed, seed2keyPair,idSecPass2rawAll, raw2b58, idSecPass2cleanKeys} +export {b58,b16, saltPass2seed, seed2keyPair,idSecPass2rawAll, raw2b58, idSecPass2cleanKeys} import {nacl} from "./vendors/nacl.js"; async function idSecPass2rawAll(idSec,pass) { @@ -36,6 +36,7 @@ async function saltPass2seed(idSec,pass) { //inspired by bs58 and base-x module const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; const b58 = basex(ALPHABET); +const b16 = basex('0123456789abcdef'); function basex (ALPHABET) { const ALPHABET_MAP = {}; const BASE = ALPHABET.length; diff --git a/public/dunikey.html b/public/dunikey.html new file mode 100644 index 0000000000000000000000000000000000000000..c988075610326ce22a1e3f29da24a73e46a5ef51 --- /dev/null +++ b/public/dunikey.html @@ -0,0 +1,70 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8" /> + <title>idSec+password or seed or keys => file.dunikey</title> + <link rel="icon" type="image/png" sizes="16x16" href="img/favicon.png"> + <link rel="canonical" href="https://gsper.duniter.io/dunikey.html"/> + + <meta property="og:type" content="website" /> + <meta property="og:locale" content="fr_FR" /> + <meta property="og:title" content="idSec+password or seed or keys => file.dunikey" /> + <meta property="og:site_name" content="gsper.duniter.io" /> + <meta property="og:url" content="https://gsper.duniter.io/dunikey.html" /> + <meta property="og:image" content="https://gsper.duniter.io/img/gsper-logo.png" /> + <meta property="og:description" content="Converti vos secrets d'authentification pour générer un fichier d'authentification file.dunikey" /> + <style> + * {font-family: sans-serif; box-sizing: border-box; margin: 0; padding: 0} + h1{font-weight: normal; width: 100%; text-align: center; line-height: 70px;} + fieldset {margin: 10px;} + .logic {margin-left: 50px;} + input{border: 0; padding: 5px;width: 100%; line-height: 60px; font-size: 16px;} + button {width: 100%; height: 32px} + .gift {position: absolute; top: 10px; left: 10px;} + .gift a{text-decoration-color: rgba(0%,0%,100%,0.2); color: rgba(0%,0%,100%,0.7);} + </style> +</head> +<body> +<h1>DunikeyMaker</h1> +<fieldset> + <fieldset> + <input id="idSec" type="password" placeholder="Identifiant secret"/> + <input id="pass" type="password" placeholder="Mot de passe"/> +</fieldset> + <div class="logic">ou</div> +<fieldset> + <input id="seed" type="text" placeholder="Seed"/> +</fieldset> + <div class="logic">ou</div> +<fieldset> + <input id="secretkey" type="text" placeholder="Clef privée (ou secrète)"/> + <input id="pubkey" type="text" placeholder="Clef publique"/> +</fieldset> +</fieldset> +<div class="logic">et</div> +<fieldset> + <input id="filename" type="text" placeholder="Nom du fichier à générer"/> + <button id="compute">Générer le fichier .dunikey.yml</button> +</fieldset> + <div class="gift"> + <a href="https://cesium.g1.1000i100.fr/#/app/wot/2sZF6j2PkxBDNAqUde7Dgo5x3crkerZpQ4rBqqJGn8QT/1000i100" target="_blank">Ǧ'spère vous avoir été utile.<br/> + Soutenez mon travail avec un don !<br/> + 👤 : 1000i100 🔑 : 2sZF6j2P + </a> + </div> +<footer> + <a href="https://git.duniter.org/tools/gsper" id="sourceRibbon" title="Fork me !"> + <span>AGPL-3.0</span> + <span>Logiciel Libre</span> + <span>Remonter aux sources</span> + <style> + #sourceRibbon {position: fixed; top: 15px; right: -110px; z-index: 500; transform: rotate(45deg); text-align: center;width: 300px; box-shadow: 0 0 5px #000; text-decoration: none;} + #sourceRibbon span {background-color: #0A0; color: white; font-family: sans-serif; display: block; padding: 1px 30px; font-size: 9pt; margin: -1px; text-shadow: 0 0 3px rgba(0,0,0,.5);} + #sourceRibbon span + span {background-color: #06A; font-size: 11pt;} + #sourceRibbon span + span + span {background-color: #E80; font-size: 10pt;} + </style> + </a> +</footer> +<script type="module" src="dunikey.js"></script> +</body> +</html> diff --git a/public/dunikey.js b/public/dunikey.js new file mode 100644 index 0000000000000000000000000000000000000000..f3059d2a2e27cf150fa1ea28c3b4cc3536e9d1a6 --- /dev/null +++ b/public/dunikey.js @@ -0,0 +1,54 @@ +import * as dKey from "./crypto.js"; + +addEventsListeners([ + document.getElementById("idSec"), + document.getElementById("pass"), + ], "keyup change", + async function () { + const idSec = document.getElementById("idSec").value; + const pass = document.getElementById("pass").value; + const keys = await dKey.idSecPass2cleanKeys(idSec, pass); + document.getElementById("seed").value = keys.seed; + document.getElementById("secretkey").value = keys.secretKey; + document.getElementById("pubkey").value = keys.publicKey; + + }); +addEventsListeners([ + document.getElementById("seed"), + ], "keyup change", + async function () { + let rawSeed; + const seed = document.getElementById("seed").value; + console.log(seed.length); + if (seed.length === 64) rawSeed = dKey.b16.decode(seed); + else rawSeed = dKey.b58.decode(seed); + const keys = await dKey.seed2keyPair(rawSeed); + document.getElementById("secretkey").value = dKey.b58.encode(keys.secretKey); + document.getElementById("pubkey").value = dKey.b58.encode(keys.publicKey); + }); +addEventsListeners([ + document.getElementById("compute"), + ], "click", + async function () { + const filename = document.getElementById("filename").value; + const secretkey = document.getElementById("secretkey").value; + const pubkey = document.getElementById("pubkey").value; + exportAsFile(filename, `pub: ${pubkey}\nsec: ${secretkey}`); + }); + +function exportAsFile(fileName, data) { + const a = document.createElement('a'); + a.setAttribute('download', fileName + '.dunikey.yml'); + a.setAttribute('href', 'data:text/yaml;charset=utf-8,' + encodeURIComponent(data)); + clickOn(a); +} +function clickOn(element) { + const event = new MouseEvent('click', {'view': window, 'bubbles': true, 'cancelable': true}); + element.dispatchEvent(event); +} +function addEventsListeners(triggerNodes, events, functions) { + if (!triggerNodes.length) triggerNodes = [triggerNodes]; + if (typeof events !== "object") events = events.split(" "); + if (typeof functions !== "object") functions = [functions]; + for (let n of triggerNodes) events.forEach(e => functions.forEach(f => n.addEventListener(e, f))); +}