Skip to content

Instantly share code, notes, and snippets.

@25A0
Last active April 14, 2017 22:15
Show Gist options
  • Save 25A0/b32c547b57b1346485453084a66f6111 to your computer and use it in GitHub Desktop.
Save 25A0/b32c547b57b1346485453084a66f6111 to your computer and use it in GitHub Desktop.
Dumb bruteforcer to find preimages of capital letters([A-Z ]+) for a JavaScript 'hash' function (this one: http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
String.prototype.hashCode = function() {
var hash = 0, i, chr;
if (this.length === 0) return hash;
for (i = 0; i < this.length; i++) {
chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
};
*/
int advHash(int prev_hash, int buflen, char* buf)
{
int hash = prev_hash;
int i = 0;
for (i = 0; i < buflen; ++i)
{
hash = (hash << 5) - hash + buf[i];
}
return hash;
}
int hashCode(int buflen, char* buf)
{
return advHash(0, buflen, buf);
}
// Stores the numeric representation of c in numbuf. Say c is 'a', then "65"
// will be written to numbuf and numbuf + 1.
void put(char* numbuf, char c)
{
// This assumes that the numeric representation has two digits in base 10
if(c >= 100 || c < 10) exit(42);
numbuf[0] = '0' + (c/10);
numbuf[1] = '0' + (c%10);
}
// Picks the next word by increasing the last character, and subsequently
// increasing previous characters if the last character wrapped around. So,
// the next word after "aaz" is "aba", and the next word after "azz" is "baa".
// len is the current word length, charbuf is the buffer that contains the
// character representation of the current word, and numbuf is the buffer that
// contains the numeric representation of the current word. numbuf is twice
// as long as charbuf, assuming that each character is represented by two
// digits.
// Returns the number of changed characters.
// If the whole word wrapped around, returns the number of changed characters+1
int next(int len, char* charbuf, char* numbuf)
{
if(len == 0) return 0;
int i;
int wrapped;
char newchar;
i = len;
do {
i--; // Go to the previous character
newchar = charbuf[i];
wrapped = newchar == ' ';
newchar = wrapped? 'A': newchar == 'Z'? ' ': newchar + 1;
charbuf[i] = newchar;
put(&numbuf[2 * i], newchar);
} while(wrapped && i > 0);
return wrapped + len - i;
}
int main(int argc, char const *argv[])
{
setvbuf(stdout, NULL, _IONBF, 0);
// How many characters to skip
const char* initial_word;
const int max_wordlen = 32;
int start_len;
if(argc > 1) {
initial_word = argv[1];
printf("Starting with %s...\n", initial_word);
} else {
initial_word = "A";
}
start_len = strlen(initial_word);
if(start_len > max_wordlen) {
printf("Cannot start with words longer than %d characters",
max_wordlen);
exit(1);
}
int h1 = -1113088476;
int h2 = 424205154;
char charbuf[ max_wordlen + 1];
char numbuf [2*max_wordlen + 1];
memset(charbuf, 0, sizeof(char) * max_wordlen + 1 );
memset(numbuf, 0, 2 * (sizeof(char) * max_wordlen)+ 1 );
int i;
for(i = 0; i < start_len; ++i) {
charbuf[i] = initial_word[i];
put(&numbuf[2*i], initial_word[i]);
}
// cache of hashes, since they don't change that much between two words
int hashes[max_wordlen];
int current_len = start_len;
while(current_len <= max_wordlen) {
printf("Checking length %d\n", current_len);
int wrapped;
int changed = current_len;
do {
// Compute the hashes iteratively to speed up computation of
// subsequent hashes.
// Length of unchanged prefix
int unchanged = current_len - changed;
int prev_hash = unchanged == 0? 0: hashes[unchanged - 1];
for (i = 0; i < changed; ++i)
{
hashes[unchanged + i] = advHash(prev_hash, 2,
&numbuf[2*(unchanged + i)]);
prev_hash = hashes[unchanged + i];
}
int hash = prev_hash;
if(hash == h1 || hash == h2) {
printf("%s\n", charbuf);
}
changed = next(current_len, charbuf, numbuf);
wrapped = changed > current_len;
} while(!wrapped);
current_len++;
// Initialize the last character of the longer word
charbuf[current_len - 1] = 'A';
put(&numbuf[2 * (current_len - 1)], 'A');
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment