/* wrappers for the blowfish function. * Updates the subkeys and divides the data block in two 32b halves. * Return encrypted or decrypted text. * * Strategy: * - calculates the output length, depending on the input. * - updates the subkeys according to the user key. * - for every 64-bit blocks of data, apply the blowfish algorithm. * - when there are less than 64 bits remaining, complete with 0's. */ int encrypt(const char* user_key, byte_t* content, byte_t** cipher, int* safe) { int i, j; int data_block_counter; byte_t* data = (byte_t*) content; goldeen_32b_block remaining_bytes; byte_t* input_pointer; byte_t* output_pointer; int input_length = strlen((char*) content); int output_length = calculate_output_length(input_length); *cipher = (byte_t*) malloc(output_length*sizeof(byte_t)); byte_t* stream = *cipher; update_subkeys(user_key, strlen(user_key)); *safe = check_keys(); for (data_block_counter = 0; data_block_counter < output_length; data_block_counter += 8) { if (data_block_counter < input_length - 7) { input_pointer = data; output_pointer = stream; for (i = 0; i < 8; ++i) { *output_pointer++ = *input_pointer++; } blowfish((goldeen_32b_block*) stream, (goldeen_32b_block*) (stream + 4), ENCRYPT); } else { remaining_bytes = input_length - data_block_counter; input_pointer = data; output_pointer = stream; for (i = 0; i < (int) remaining_bytes; ++i) { *output_pointer++ = *input_pointer++; } for (j = i; j < 8; j++) { *output_pointer++ = 0; } blowfish((goldeen_32b_block*) stream, (goldeen_32b_block*) (stream + 4), ENCRYPT); } data += 8; stream += 8; } return output_length; }
void decrypt(const char* user_key, void* cipher, int cipher_length, byte_t** plain_text) { int i, data_block_counter; byte_t* input_pointer; byte_t* output_pointer; *plain_text = (byte_t*) malloc(cipher_length*sizeof(byte_t)); byte_t* stream = *plain_text; byte_t* _cipher = (byte_t*) cipher; update_subkeys(user_key, strlen(user_key)); for (data_block_counter = 0; data_block_counter < cipher_length; data_block_counter += 8) { input_pointer = _cipher; output_pointer = stream; for (i = 0; i < 8; ++i) { *output_pointer++ = *input_pointer++; } blowfish((goldeen_32b_block*) stream, (goldeen_32b_block*) (stream + 4), DECRYPT); _cipher += 8; stream += 8; } }
void update_subkeys(const char* user_key, int length) { goldeen_32b_block xL = 0, xR = 0; int i, j, k; goldeen_32b_block key_chunk; /* 1 */ for (i = 0; i < 18; ++i) { keys.P[i] = initial_keys[i]; } k = 18; for (i = 0; i < 4; ++i) { for (j = 0; j < 256; ++j) { keys.S[i][j] = initial_keys[k++]; } } /* 2 */ key_chunk = 0; for (i = j = 0; i < 18; ++i) { for (k = 0; k < 4; ++k) { key_chunk = (key_chunk << 8) | user_key[j]; if (++j >= length) { j = 0; } } keys.P[i] ^= key_chunk; } /* 3 to 7 */ for (i = 0; i < 18; i += 2) { blowfish(&xL, &xR, ENCRYPT); keys.P[i] = xL; keys.P[i + 1] = xR; } for (i = 0; i < 4; ++i) { for (j = 0; j < 256; j += 2) { blowfish(&xL, &xR, ENCRYPT); keys.S[i][j] = xL; keys.S[i][j + 1] = xR; } } }
std::string HashUtils::blowfish(const ByteArrayType &data, const ByteArrayType &key, const char *ivec) { return blowfish(&*data.begin(), data.size(), &*key.begin(), key.size(), ivec); }
std::string HashUtils::blowfish(const char *data, const char *key, const char *ivec) { return blowfish(data, strlen(data), key, strlen(key), ivec); }