writeups/2020/wpictf/acurless_kdf/decrypt.c
// phase one produces O, which is half the length of input,
// given input and an initialization vector iv, which always takes the value of 0xC0FFEE
phase one produces O, which is half the length of input,
given input and an initialization vector iv, which always takes the value of 0xC0FFEE
phase one produces O which is half the length of input given input and an initialization vector iv which always takes the value of 0xC0FFEE
void phase1(const char *input, uint32_t iv, uint8_t *o) {
	size_t input_len = strlen(input);
	size_t output_len = input_len/2;
	printf("phase1 input len: %d\n",input_len);
	printf("phase1 output len: %d\n",output_len);
	char *t = alloca(input_len);
	int o_pos = 0;
	for (int i = 0; i < input_len; i += 8) {
		uint64_t block = 0L;
		for (int j = 0; j < 8; j++) {
			int pos = i+j;
			char c;
			if (pos > input_len)
				c = 0; 
			else
				c = input[pos];
			printf("%c",c);
			block = (block << 8) | (uint64_t)c;
		}
		printf("\nblock: %llx\n",block);
		uint32_t low = (block);
		uint32_t high = (block >> 32);
		high ^= iv;
		low ^= iv;
		block = (uint64_t)high << 32 | (uint64_t)low;
		printf("transformed: %llx\n",block);
		char *key = (char *)&block;
		int keylen = sizeof(block);
		bcopy(P_orig, P, sizeof(P));
		bcopy(S_orig, S, sizeof(S));
		for (int i=0 ; i<18 ; ++i)
			P[i] ^= key[i % keylen];
		uint32_t L = 0, R = 0;
		for (int i=0 ; i<18 ; i+=2) {
			encrypt (&L, &R);
			P[i] = L; P[i+1] = R;
		}
		for (int i=0 ; i<4 ; ++i) {
			for (int j=0 ; j<256; j+=2) {
				encrypt (&L, &R);
				S[i][j] = L; S[i][j+1] = R;
			}
		}
		bcopy(L,o[o_pos],4);
		o_pos += 4;
		iv = R;
	}
}
void phase1 ( const char * input , uint32_t iv , uint8_t * o ) { size_t input_len = strlen ( input ) ; size_t output_len = input_len / 2 ; printf ( " \n " , input_len ) ; printf ( " \n " , output_len ) ; char * t = alloca ( input_len ) ; int o_pos = 0 ; for ( int i = 0 ; i < input_len ; i += 8 ) { uint64_t block = 0L ; for ( int j = 0 ; j < 8 ; j ++ ) { int pos = i + j ; char c ; if ( pos > input_len ) c = 0 ; else c = input [ pos ] ; printf ( " " , c ) ; block = ( block << 8 ) | ( uint64_t ) c ; } printf ( " \n \n " , block ) ; uint32_t low = ( block ) ; uint32_t high = ( block >> 32 ) ; high ^= iv ; low ^= iv ; block = ( uint64_t ) high << 32 | ( uint64_t ) low ; printf ( " \n " , block ) ; char * key = ( char * ) & block ; int keylen = sizeof ( block ) ; bcopy ( P_orig , P , sizeof ( P ) ) ; bcopy ( S_orig , S , sizeof ( S ) ) ; for ( int i = 0 ; i < 18 ; ++ i ) P [ i ] ^= key [ i % keylen ] ; uint32_t L = 0 , R = 0 ; for ( int i = 0 ; i < 18 ; i += 2 ) { encrypt ( & L , & R ) ; P [ i ] = L ; P [ i + 1 ] = R ; } for ( int i = 0 ; i < 4 ; ++ i ) { for ( int j = 0 ; j < 256 ; j += 2 ) { encrypt ( & L , & R ) ; S [ i ] [ j ] = L ; S [ i ] [ j + 1 ] = R ; } } bcopy ( L , o [ o_pos ] , 4 ) ; o_pos += 4 ; iv = R ; } }
phase one produces O, which is half the length of input,
given input and an initialization vector iv, which always takes the value of 0xC0FFEE
phase one produces O which is half the length of input given input and an initialization vector iv which always takes the value of 0xC0FFEE
// divide the input data into 64-bit blocks // padding // acurless kdf key transformation // for each block of input: // - initialize a blowfish key // - blowfish encrypt the current block of input // - append the upper 32 bits of the output to O. // - use the lower 32 bits of the output as the IV for the next block // TODO: Uh... ran out of time in the CTF. // Leaving it incomplete.