Last active
April 30, 2024 09:10
-
-
Save prigaux/624909692f0f0121a800c3513c0a1b3c to your computer and use it in GitHub Desktop.
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
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>easy unique password per website</title> | |
<style type="text/css"> | |
body { | |
font-family: Verdana, Arial, Helvetica, sans-serif, monospace; | |
} | |
</style> | |
<script type="text/javascript"> | |
// force https for Clipboard API | |
if (location.protocol === "http:") { | |
location.protocol = "https:" | |
} | |
/* | |
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined | |
* in FIPS 180-1 | |
* Version 2.2 Copyright Paul Johnston 2000 - 2009. | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* Distributed under the BSD License | |
* See http://pajhome.org.uk/crypt/md5 for details. | |
*/ | |
/* | |
* Configurable variables. You may need to tweak these to be compatible with | |
* the server-side, but the defaults work in most cases. | |
*/ | |
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ | |
/* | |
* These are the functions you'll usually want to call | |
* They take string arguments and return either hex or base-64 encoded strings | |
*/ | |
function b64_sha1(s) { return rstr2b64(rstr_sha1(str2rstr_utf8(s))); } | |
/* | |
* Calculate the SHA1 of a raw string | |
*/ | |
function rstr_sha1(s) | |
{ | |
return binb2rstr(binb_sha1(rstr2binb(s), s.length * 8)); | |
} | |
/* | |
* Calculate the HMAC-SHA1 of a key and some data (raw strings) | |
*/ | |
function rstr_hmac_sha1(key, data) | |
{ | |
var bkey = rstr2binb(key); | |
if(bkey.length > 16) bkey = binb_sha1(bkey, key.length * 8); | |
var ipad = Array(16), opad = Array(16); | |
for(var i = 0; i < 16; i++) | |
{ | |
ipad[i] = bkey[i] ^ 0x36363636; | |
opad[i] = bkey[i] ^ 0x5C5C5C5C; | |
} | |
var hash = binb_sha1(ipad.concat(rstr2binb(data)), 512 + data.length * 8); | |
return binb2rstr(binb_sha1(opad.concat(hash), 512 + 160)); | |
} | |
/* | |
* Convert a raw string to a base-64 string | |
*/ | |
function rstr2b64(input) | |
{ | |
try { b64pad } catch(e) { b64pad=''; } | |
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
var output = ""; | |
var len = input.length; | |
for(var i = 0; i < len; i += 3) | |
{ | |
var triplet = (input.charCodeAt(i) << 16) | |
| (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) | |
| (i + 2 < len ? input.charCodeAt(i+2) : 0); | |
for(var j = 0; j < 4; j++) | |
{ | |
if(i * 8 + j * 6 > input.length * 8) output += b64pad; | |
else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); | |
} | |
} | |
return output; | |
} | |
/* | |
* Encode a string as utf-8. | |
* For efficiency, this assumes the input is valid utf-16. | |
*/ | |
function str2rstr_utf8(input) | |
{ | |
var output = ""; | |
var i = -1; | |
var x, y; | |
while(++i < input.length) | |
{ | |
/* Decode utf-16 surrogate pairs */ | |
x = input.charCodeAt(i); | |
y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; | |
if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) | |
{ | |
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); | |
i++; | |
} | |
/* Encode output as utf-8 */ | |
if(x <= 0x7F) | |
output += String.fromCharCode(x); | |
else if(x <= 0x7FF) | |
output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), | |
0x80 | ( x & 0x3F)); | |
else if(x <= 0xFFFF) | |
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), | |
0x80 | ((x >>> 6 ) & 0x3F), | |
0x80 | ( x & 0x3F)); | |
else if(x <= 0x1FFFFF) | |
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), | |
0x80 | ((x >>> 12) & 0x3F), | |
0x80 | ((x >>> 6 ) & 0x3F), | |
0x80 | ( x & 0x3F)); | |
} | |
return output; | |
} | |
/* | |
* Convert a raw string to an array of big-endian words | |
* Characters >255 have their high-byte silently ignored. | |
*/ | |
function rstr2binb(input) | |
{ | |
var output = Array(input.length >> 2); | |
for(var i = 0; i < output.length; i++) | |
output[i] = 0; | |
for(var i = 0; i < input.length * 8; i += 8) | |
output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); | |
return output; | |
} | |
/* | |
* Convert an array of big-endian words to a string | |
*/ | |
function binb2rstr(input) | |
{ | |
var output = ""; | |
for(var i = 0; i < input.length * 32; i += 8) | |
output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF); | |
return output; | |
} | |
/* | |
* Calculate the SHA-1 of an array of big-endian words, and a bit length | |
*/ | |
function binb_sha1(x, len) | |
{ | |
/* append padding */ | |
x[len >> 5] |= 0x80 << (24 - len % 32); | |
x[((len + 64 >> 9) << 4) + 15] = len; | |
var w = Array(80); | |
var a = 1732584193; | |
var b = -271733879; | |
var c = -1732584194; | |
var d = 271733878; | |
var e = -1009589776; | |
for(var i = 0; i < x.length; i += 16) | |
{ | |
var olda = a; | |
var oldb = b; | |
var oldc = c; | |
var oldd = d; | |
var olde = e; | |
for(var j = 0; j < 80; j++) | |
{ | |
if(j < 16) w[j] = x[i + j]; | |
else w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); | |
var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), | |
safe_add(safe_add(e, w[j]), sha1_kt(j))); | |
e = d; | |
d = c; | |
c = bit_rol(b, 30); | |
b = a; | |
a = t; | |
} | |
a = safe_add(a, olda); | |
b = safe_add(b, oldb); | |
c = safe_add(c, oldc); | |
d = safe_add(d, oldd); | |
e = safe_add(e, olde); | |
} | |
return Array(a, b, c, d, e); | |
} | |
/* | |
* Perform the appropriate triplet combination function for the current | |
* iteration | |
*/ | |
function sha1_ft(t, b, c, d) | |
{ | |
if(t < 20) return (b & c) | ((~b) & d); | |
if(t < 40) return b ^ c ^ d; | |
if(t < 60) return (b & c) | (b & d) | (c & d); | |
return b ^ c ^ d; | |
} | |
/* | |
* Determine the appropriate additive constant for the current iteration | |
*/ | |
function sha1_kt(t) | |
{ | |
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : | |
(t < 60) ? -1894007588 : -899497514; | |
} | |
/* | |
* Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
* to work around bugs in some JS interpreters. | |
*/ | |
function safe_add(x, y) | |
{ | |
var lsw = (x & 0xFFFF) + (y & 0xFFFF); | |
var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
return (msw << 16) | (lsw & 0xFFFF); | |
} | |
/* | |
* Bitwise rotate a 32-bit number to the left. | |
*/ | |
function bit_rol(num, cnt) | |
{ | |
return (num << cnt) | (num >>> (32 - cnt)); | |
} | |
function clear_msg() { | |
document.getElementById('clipboard_msg').innerText = '' | |
} | |
function gen_check() { | |
document.getElementById('generatedcheck').innerText = b64_sha1(document.getElementById('password').value + '|foo.org').substring(0, 8); | |
} | |
function gen() { | |
gen_check(); | |
var hostname = document.getElementById('url').value.replace(/https?:\/\//, '').replace(/(:\d+)?\/.*/, ''); | |
document.getElementById('generated').value = b64_sha1(document.getElementById('password').value + '|' + hostname); | |
document.getElementById('generatedshort').value = document.getElementById('generated').value.substring(0, 8); | |
navigator.clipboard.writeText(document.getElementById('generated').value) | |
document.getElementById('clipboard_msg').innerText = 'exported to clipboard' | |
} | |
</script> | |
</head> | |
<body> | |
<form action="javascript:gen()"> | |
Password: <input type="password" id="password" autocomplete="off" onkeypress="clear_msg()" onfocusout="gen_check()"> <span id="generatedcheck" size="10" style="color: orange"></span> <br> | |
Website URL or hostname: <input type="text" id="url" size="50" onkeypress="clear_msg()"><br> | |
<input type="submit" value="Generate website-specific password"><br><br> | |
Result: <br> | |
<input type="text" id="generated" size="30"> (long) | |
<i style="color: orange" id="clipboard_msg"></i> | |
<br><input type="text" id="generatedshort" size="10"> (first 8 chars) | |
</form> | |
<br> | |
Thanks Odie :) | |
<p></p> | |
Purpose: generate a unique password per website so that if your | |
password is compromised, your logins on other sites aren't - we | |
all know passwords are either not securely transmitted, not | |
securely stored, not stored hashed, or all of these | |
:(<br><br>Enter below a password (the principle is that it's | |
the same for all the sites - don't use a trivially simple | |
password else a simple dictionary attack would allow to get | |
back to it easily) and copy-paste the URL of the site; | |
SHA1(password + hostname) will be generated locally with | |
javascript and shown in base64 (good for sites forcing | |
lowercase, uppercase and digits); your password entered below, | |
and the generated one, will NOT be transmitted on the network, | |
this is local javascript only.<br><br><font color="red">Don't see that | |
as more secure than it is, if there is a keylogger on the machine | |
you're using, or if this page has a malware inside, you're | |
compromised (better copy this page locally and quickly check | |
the source)! Also, it's of course less secure than using | |
real different passwords for all sites.</font><br><br> | |
<p> | |
<a href="https://web.archive.org/web/20210514220411/http://pajhome.org.uk/crypt/md5/">SHA-1 in JavaScript thanks Paul Johnston</a> | |
</p> | |
<script type="text/javascript"> | |
document.getElementById('password').focus(); | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment