// A simple guess-and-determine solution for ZC4 cipher // Copyright (c) 2008 by Marcos el Ruptor // Warning! ZC4 is insecure. // Use it for educational purposes only, as a challenge for students. // Finds the initial keyed state given a known pt/ct pair with a // sufficiently long consecutive repetition of some byte in it. // For the sake of testing, the plaintext is a sequence of 73-byte wide repetitions. // Only one byte needs to be guessed to recover the whole secret state. #include #include #include #define ITEMS 256 #define swap2(a,b) (t=a,a=b,b=t) #define u32 unsigned long static u32 acc,x[ITEMS]; static u32 inv (const u32 n) {u32 i;for(i=0;i= ITEMS) break; // guessing another byte here can improve the odds at the cost of performance d = ((ct[j] ^ pt[j]) - z[pt[j]]) % ITEMS; k = (z[pt[j]] + acc) % ITEMS; if (z[k] >= ITEMS) known++; z[k] = z[pt[j]]; z[pt[j]] = d; if (known >= ITEMS) { // check our guess acc = ct[j] ^ pt[j]; memcpy (x, z, sizeof (x)); for (i = 0; (i < ITEMS*2) && (i+j+1 < ITEMS*ITEMS); i++) { if (zc4(pt[j+i+1]) != (ct[j+i+1] ^ pt[j+i+1])) goto _next; // Damn C won't break out of two loops! } // rewind acc = ct[j] ^ pt[j]; memcpy (x, z, sizeof (x)); for (i = j; i != -1; i--) zc4i (pt[i]); // output the initial keyed state printf ("Round %d:\n\n", j); printf ("%02X:\n", acc); for (i = 0; i < ITEMS; i++) printf ("%02X%s", x[i], (i%32==31)?"\n":" "); printf ("\n"); return; } } _next:; } } }