<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
</body>
</html>
// Somebody asked for help reversing a "hashing" function as they've got a list of hashes, but no passwords
// Of course if it was a proper hashing function then you'd be stuffed and the only way to do it would be rainbow tables.
// Entertainingly the hashing function they provided as flawed as all hell so we can build something that shall easily generate collisions - multiple passwords that generate the same "hash".
// The original encoding cipher
var alpha="1qazxsw23edcvfr€45tgbnhy67ujm,ki89ol./;p0-['#]=!QAZXSW£EDCVFR$%TGBNHY^&UJM<KI*(OL>?:P)_{@~}+`¬ ";
// The original "hash" function
// Ignore the bad style where they're using a global variable and using str.substring where str.charAt would be better...
function makehash(str,mult){ // makehash("doogle",6);
hash=0; // Output
for (j=0;j<str.length;j++) hash=hash*mult+alpha.indexOf(str.substring(j,j+1),0)+1; // Generate hash code, on first loop,
// hash is 0 so hash*mult is also 0.
return hash; // Return output
}
///////////////////////
// Let's get reversing!
///////////////////////
// The original has function is flawed in such a way, that you can determine valid final characters for a password for a given "hash".
function potentialFinalCharacter(hash, mult) {
var newhash, charnum, char;
charnum = (hash - 1)%mult;
newhash = (hash - 1 - charnum)/mult;
char = alpha[charnum];
return [newhash, char];
}
// Finding a collision is a case of reducing the inital "large" hash down to a smaller "hash" (Saving the letter we expect to see at the end), then repeating that process till the "hash" is equal to 0, which means we've found our collision
function findCollision(initialHash, mult, alpha) {
var chars = [];
var hash = initialHash;
do {
result = potentialFinalCharacter(hash, mult);
hash = result[0];
chars.push(result[1]);
} while(hash > 0);
return chars.reverse().join('');
}
// Should be 139402
var originalPassword ='doogle';
var originalHash = makehash(originalPassword,6);
var collisionPassword = findCollision(originalHash, 6, alpha);
var collisionedHash = makehash(collisionPassword,6);
document.write('Original Password: ' + originalPassword + '<br>');
document.write('Original Hash: ' + originalHash + '<br>');
document.write('Collision Password: ' + collisionPassword + '<br>');
document.write('Collision Hash: ' + collisionedHash + '<br>');
document.write('Collision Hashes are EQUAL: ' + (originalHash == collisionedHash ) + '<br>');
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |