11#include < unistd.h>
2+ #include < arpa/inet.h>
23#include < getopt.h>
4+ #include < stdint.h>
35#include < openssl/sha.h>
46#include " SHA1.h"
57#include " MD5ex.h"
@@ -113,15 +115,18 @@ void PrintHelp()
113115 cout << " -d --data The data from the known message." << endl;
114116 cout << " -a --additional The information you would like to add to the known message." << endl;
115117 cout << " -k --keylength The length in bytes of the key being used to sign the original message with." << endl;
118+ cout << " -u --unknown number if leading hash bits unknown (EXPERIMENTAL HACK)" << endl;
119+ cout << " -z --sig2 target signature (EXPERIMENTAL HACK)" << endl;
116120 cout << " Version 1.0 with MD5, SHA1, SHA256 and SHA512 support." << endl;
117121 cout << " <Developed by bwall(@bwallHatesTwits)>" << endl;
118122}
119123
120124int main (int argc, char ** argv)
121125{
122- string sig;
126+ string sig, sig2 ;
123127 string data;
124128 int keylength = 0 ;
129+ int unknown = 0 ;
125130 string datatoadd;
126131 Extender * sex = NULL ;
127132 bool run_tests = false ;
@@ -135,11 +140,13 @@ int main(int argc, char ** argv)
135140 {" data" , required_argument, 0 , 0 },
136141 {" additional" , required_argument, 0 , 0 },
137142 {" keylength" , required_argument, 0 , 0 },
143+ {" unknown" , required_argument, 0 , 0 },
144+ {" sig2" , required_argument, 0 , 0 },
138145 {" help" , no_argument, 0 , 0 },
139146 {0 , 0 , 0 , 0 }
140147 };
141148
142- int c = getopt_long (argc, argv, " ts:d:a:k:h" , long_options, &option_index);
149+ int c = getopt_long (argc, argv, " ts:d:a:k:u:z: h" , long_options, &option_index);
143150 if (c == -1 )
144151 break ;
145152
@@ -149,16 +156,11 @@ int main(int argc, char ** argv)
149156 switch (option_index)
150157 {
151158 case 0 :
159+ case ' t' :
152160 run_tests = true ;
153161 break ;
154162 case 1 :
155163 sig.assign (optarg);
156- sex = GetExtenderForHash (sig);
157- if (sex == NULL )
158- {
159- cout << " Unsupported signature size." << endl;
160- return 0 ;
161- }
162164 break ;
163165 case 2 :
164166 data.assign (optarg);
@@ -170,21 +172,20 @@ int main(int argc, char ** argv)
170172 keylength = atoi (optarg);
171173 break ;
172174 case 5 :
175+ unknown = atoi (optarg);
176+ break ;
177+ case 6 :
178+ sig2.assign (optarg);
179+ break ;
180+ case 7 :
173181 PrintHelp ();
174182 return 0 ;
175183 }
176184 break ;
177- case ' t' :
178185 run_tests = true ;
179186 break ;
180187 case ' s' :
181188 sig.assign (optarg);
182- sex = GetExtenderForHash (sig);
183- if (sex == NULL )
184- {
185- cout << " Unsupported hash size." << endl;
186- return 0 ;
187- }
188189 break ;
189190 case ' d' :
190191 data.assign (optarg);
@@ -195,6 +196,12 @@ int main(int argc, char ** argv)
195196 case ' k' :
196197 keylength = atoi (optarg);
197198 break ;
199+ case ' u' :
200+ unknown = atoi (optarg);
201+ break ;
202+ case ' z' :
203+ sig2.assign (optarg);
204+ break ;
198205 case ' h' :
199206 PrintHelp ();
200207 return 0 ;
@@ -257,9 +264,62 @@ int main(int argc, char ** argv)
257264 vector<unsigned char > vtoadd = StringToVector ((unsigned char *)datatoadd.c_str ());
258265
259266 unsigned char firstSig[128 ];
267+ unsigned char targetSig[128 ];
260268 DigestToRaw (sig, firstSig);
261- unsigned char * secondSig;
262- vector<unsigned char > * secondMessage = sex->GenerateStretchedData (vmessage, keylength, firstSig, vtoadd, &secondSig);
269+ DigestToRaw (sig2, targetSig);
270+ unsigned char * secondSig = 0 ;
271+
272+
273+ sex = GetExtenderForHash (sig);
274+ if (sex == NULL )
275+ {
276+ cout << " Unsupported signature size." << endl;
277+ return 0 ;
278+ }
279+ uint32_t maxval = 1 << unknown;
280+ uint32_t mask = ~ ((1 <<(unknown)) - 1 );
281+ printf (" mask: %x\n " , mask);
282+ vector<unsigned char > * secondMessage = 0 ;
283+ uint32_t *sigStart = (uint32_t *)&firstSig;
284+ uint32_t part1 = htonl (*sigStart);
285+ for (uint32_t prefix =0 ; prefix <= maxval; prefix++) {
286+ if (prefix % (1 <<20 ) == 0 ) {
287+ float part = (float )prefix/maxval;
288+ printf (" progress: 0x%16x, %.4f: " , prefix, part);
289+ #define WIDTH 40
290+ for (int i=0 ; i < WIDTH; i++) {
291+ if (float (i)/WIDTH < part)
292+ printf (" =" );
293+ else {
294+ printf (" " );
295+ }
296+ }
297+ printf (" |\r " );
298+ fflush (stdout);
299+ }
300+ uint32_t shiftedPrefix = prefix << (32 -unknown);
301+ *sigStart = htonl (part1 | shiftedPrefix);
302+
303+ // all this allocation and deallocation is a stupid idea
304+ if (secondSig)
305+ delete[] secondSig;
306+ if (secondMessage)
307+ delete secondMessage;
308+ secondMessage = sex->GenerateStretchedData (vmessage, keylength, firstSig, vtoadd, &secondSig);
309+ // cheating a bit: if the lower 96 bit match, we're probably lucky.
310+ if (memcmp (secondSig+4 , targetSig+4 , 12 ) == 0 ) {
311+ printf (" \n success with origHash = " );
312+ for (unsigned int x = 0 ; x < sig.size ()/2 ; x++)
313+ {
314+ printf (" %02x" , firstSig[x]);
315+ }
316+ printf (" \n " );
317+ printf (" prefix: 0x%x\n " , prefix);
318+ break ;
319+ } else {
320+ }
321+ }
322+ printf (" predicted sig: " );
263323 for (unsigned int x = 0 ; x < sig.size ()/2 ; x++)
264324 {
265325 printf (" %02x" , secondSig[x]);
0 commit comments