#include "target.h" #include #include #include #include #include using namespace std; #include "cpucycles.h" class uint32 { unsigned int x; public: inline uint32() { } inline uint32(unsigned int u) { x = u; } inline uint32(const uint32 &a) { x = a.x; } inline void setbigendian(const unsigned char *s) { x = (((unsigned int) s[0]) << 24) | (((unsigned int) s[1]) << 16) | (((unsigned int) s[2]) << 8) | (((unsigned int) s[3])); } int hammingweight() { return __builtin_popcount(x); } friend inline uint32 operator+(uint32 a,uint32 b) { return a.x + b.x; } friend inline uint32 operator|(uint32 a,uint32 b) { return a.x | b.x; } friend inline uint32 operator&(uint32 a,uint32 b) { return a.x & b.x; } friend inline uint32 operator^(uint32 a,uint32 b) { return a.x ^ b.x; } friend inline uint32 andnot(uint32 a,uint32 b) { return a.x & ~b.x; } friend inline uint32 rotate1(uint32 a) { return (a.x << 1) | (a.x >> 31); } friend inline uint32 rotate5(uint32 a) { return (a.x << 5) | (a.x >> 27); } friend inline uint32 rotate30(uint32 a) { return (a.x << 30) | (a.x >> 2); } friend ostream& operator<<(ostream& o,const uint32& u) { o << hex << setw(2) << setfill('0') << ((u.x >> 24) & 255); o << hex << setw(2) << setfill('0') << ((u.x >> 16) & 255); o << hex << setw(2) << setfill('0') << ((u.x >> 8) & 255); o << hex << setw(2) << setfill('0') << ((u.x) & 255); return o; } } ; class hash { uint32 state[5]; public: hash() { } hash(const unsigned char *); int hammingweight() { return state[0].hammingweight() + state[1].hammingweight() + state[2].hammingweight() + state[3].hammingweight() + state[4].hammingweight(); } friend inline hash operator^(hash a,hash b) { hash result; result.state[0] = a.state[0] ^ b.state[0]; result.state[1] = a.state[1] ^ b.state[1]; result.state[2] = a.state[2] ^ b.state[2]; result.state[3] = a.state[3] ^ b.state[3]; result.state[4] = a.state[4] ^ b.state[4]; return result; } friend ostream& operator<<(ostream& o,const hash& h) { o << h.state[0]; o << h.state[1]; o << h.state[2]; o << h.state[3]; o << h.state[4]; return o; } void blocks(const unsigned char *in,unsigned long long inlen) { uint32 a = state[0]; uint32 b = state[1]; uint32 c = state[2]; uint32 d = state[3]; uint32 e = state[4]; uint32 f; uint32 tmp; uint32 roundcon; uint32 x[80]; int i; while (inlen >= 64) { for (i = 0;i < 16;++i) x[i].setbigendian(in + 4 * i); for (i = 16;i < 80;++i) x[i] = rotate1(x[i - 3] ^ x[i - 8] ^ x[i - 14] ^ x[i - 16]); for (i = 0;i < 80;++i) { if (i < 20) { f = (c & b) | andnot(d,b); roundcon = 0x5a827999; } else if (i < 40) { f = b ^ c ^ d; roundcon = 0x6ed9eba1; } else if (i < 60) { f = (b & c) | (b & d) | (c & d); roundcon = 0x8f1bbcdc; } else { f = b ^ c ^ d; roundcon = 0xca62c1d6; } tmp = rotate5(a) + f + e + roundcon + x[i]; e = d; d = c; c = rotate30(b); b = a; a = tmp; } a = a + state[0]; b = b + state[1]; c = c + state[2]; d = d + state[3]; e = e + state[4]; state[0] = a; state[1] = b; state[2] = c; state[3] = d; state[4] = e; inlen -= 64; in += 64; } } } ; hash::hash(const unsigned char *in) { unsigned long long inlen = 0; while (in[inlen]) ++inlen; unsigned long long bits = inlen << 3; unsigned char padded[128]; int i; state[0] = 0x67452301; state[1] = 0xefcdab89; state[2] = 0x98badcfe; state[3] = 0x10325476; state[4] = 0xc3d2e1f0; blocks(in,inlen); in += inlen; inlen &= 63; in -= inlen; for (i = 0;i < inlen;++i) padded[i] = in[i]; padded[inlen] = 0x80; if (inlen < 56) { for (i = inlen + 1;i < 56;++i) padded[i] = 0; padded[56] = bits >> 56; padded[57] = bits >> 48; padded[58] = bits >> 40; padded[59] = bits >> 32; padded[60] = bits >> 24; padded[61] = bits >> 16; padded[62] = bits >> 8; padded[63] = bits; blocks(padded,64); } else { for (i = inlen + 1;i < 120;++i) padded[i] = 0; padded[120] = bits >> 56; padded[121] = bits >> 48; padded[122] = bits >> 40; padded[123] = bits >> 32; padded[124] = bits >> 24; padded[125] = bits >> 16; padded[126] = bits >> 8; padded[127] = bits; blocks(padded,128); } } const char ALPHABET[64] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/_"; #define ALPHABETUSED 32 int main() { int i; int c0; int c1; int c2; int c3; int c4; long long startcycles = cpucycles(); long long hashes = 1; hash targethash(target); cout << 0 << " " << targethash << " " << target << "\n"; unsigned char flip[sizeof s]; long long slen = 0; while (s[slen]) ++slen; if (slen < 5) return 100; #ifndef NONRANDOM srandom(cpucycles()); // XXX: randomize better #endif for (i = 0;i < slen;++i) { flip[i] = 0; if (random() & 1) if (s[i] != ' ') s[i] ^= 32; } for (;;) { for (c0 = 0;c0 < ALPHABETUSED;++c0) { s[slen - 5] = ALPHABET[c0]; cout << "cycles/hash " << dec << (cpucycles() - startcycles) / hashes << " " << s << "\n"; for (c1 = 0;c1 < ALPHABETUSED;++c1) { s[slen - 4] = ALPHABET[c1]; for (c2 = 0;c2 < ALPHABETUSED;++c2) { s[slen - 3] = ALPHABET[c2]; for (c3 = 0;c3 < ALPHABETUSED;++c3) { s[slen - 2] = ALPHABET[c3]; for (c4 = 0;c4 < ALPHABETUSED;++c4) { s[slen - 1] = ALPHABET[c4]; int d = (hash(s) ^ targethash).hammingweight(); if (d < 49) cout << dec << d << " " << hash(s) << " " << s << "\n" << flush; } hashes += c4; } } } } for (i = 0;i < slen - 5;++i) if (s[i] != ' ') { s[i] ^= 32; flip[i] ^= 32; if (flip[i]) break; } if (i == slen - 5) return 0; } }