https://1984.ninja
=T0k3n!z3R=
=T0k3n!z3R= =T0k3n!z3R= A quick and dirty password key derivation tool. Only one good master password for an infinity of strong unique tokens. No subscription - no account - no storage - no leaks - works offline & from terminal « One Ring to rule them all, One Ring to find them, One Ring to bring them all and in the darkness bind them. » — J.R.R. Tolkien Private & secret User: (your name) Password: (secret key or passphrase) Public & known Login: (e-mail or alias or pseudonym) Server: (domain or hostname) (may take a while...) ∞ Alternative PIN code: ∞ ☞ powered by https://developer.mozilla.org/en-US/docs/Web/API/Crypto Node.js ▾ #!/usr/bin/node "use strict"; const util = require('util'); const strenc = new util.TextEncoder('utf-8'); const {subtle} = require('crypto').webcrypto; var readline = require('readline'); var reader = readline.createInterface({input: process.stdin, output: process.stdout, terminal: true}); var prompt = (query) => new Promise((resolve) => reader.question(query, resolve)); (async () => { const buff2hex = function(buffer) { return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); } const buff2pin = function(token_buffer) { var hex_data = buff2hex(token_buffer); var hex_word = hex_data.match(/(.{1,6})/g); var hexpin = parseInt(hex_word.shift(), 16); for (var i=0; i
subtle.deriveBits(pbkdf2_pref, pbkdf2_key, 64*8)) .then(pbkdf2_hash => subtle.importKey('raw', strenc.encode(buff2hex(pbkdf2_hash)), hmac_pref, false, ['sign'])) .then(hmac_key => subtle.sign('HMAC', hmac_key, strenc.encode(host))) .then(hmac_hash => subtle.digest('SHA-1', hmac_hash)) .then(function(token_sha1) { var token = btoa(String.fromCharCode(...new Uint8Array(token_sha1))); var pin = token.substring(token.length - 4) + buff2pin(token_sha1); resolve({token: token, pin: pin}); }); }) } const digest = async function(user, login, server, password) { const key = await subtle.digest('SHA-512', strenc.encode(password)); const host = await subtle.digest('SHA-512', strenc.encode(login + server)); const auth = await subtle.digest('SHA-512', strenc.encode(user + buff2hex(host))); return {auth: auth, host: host, key: key}; } //--[ User inputs ]----------------------------------------------- const user = await prompt("User: "); console.log("Password:"); reader._writeToOutput = function(input){this.output.write('')}; const password = await prompt("\n"); reader._writeToOutput = function(input){this.output.write(input)}; const login = await prompt("\nLogin: "); const server = await prompt("Server: "); //--[ SHA512 digest + Tokenize with PBKDF2 / HMAC ]--------------- digest(user, login, server, password) .then(hash => tokenizer(buff2hex(hash.auth), buff2hex(hash.host), buff2hex(hash.key))) .then(function(results) { console.log("\nToken: !" + results.token); console.log("PIN: !" + results.pin); }); reader.close(); })() (use Web Crypto API) JavaScript ▾ function tokenizer(auth, host, key) { var pbkdf2 = CryptoJS.PBKDF2(auth, key, {hasher: CryptoJS.algo.SHA256, keySize: 512/32, iterations: 300000}); var hmac512 = CryptoJS.HmacSHA512(host, pbkdf2.toString()); return CryptoJS.SHA1(hmac512).toString(CryptoJS.enc.Base64); } function token2pin(token_b64) { var hex_data = CryptoJS.enc.Base64.parse(token_b64).toString(); var hex_word = hex_data.match(/(.{1,6})/g); var hexpin = parseInt(hex_word.shift(), 16); for (var i=0; i