void CCryptKey::EncryptData(const std::vector<unsigned char>& data, std::vector<unsigned char>& encrypted) { ies_ctx_t *ctx; char error[1024] = "Unknown error"; cryptogram_t *cryptogram; ctx = create_context(pkey); if (!EC_KEY_get0_public_key(ctx->user_key)) throw key_error("Given EC key is not public key"); cryptogram = ecies_encrypt(ctx, (unsigned char*)&data[0], data.size(), error); if (cryptogram == NULL) { free(ctx); ctx = NULL; throw key_error(std::string("Error in encryption: %s") + error); } encrypted.resize(cryptogram_data_sum_length(cryptogram)); unsigned char *key_data = cryptogram_key_data(cryptogram); memcpy(&encrypted[0], key_data, encrypted.size()); cryptogram_free(cryptogram); free(ctx); }
int processor(int iteration) { int tlen; size_t olen; EC_KEY *key = NULL; secure_t *ciphered = NULL; char *hex_pub = NULL, *hex_priv = NULL; unsigned char *text = NULL, *copy = NULL, *original = NULL; // Generate random size for the block of data were going to encrypt. Use a min value of 1 KB and a max of 1 MB. do { tlen = (rand() % (1024 * 1024)); } while (tlen < 1024); if (!(text = malloc(tlen + 1)) || !(copy = malloc(tlen + 1))) { printf("Memory error.\n"); processor_cleanup(key, ciphered, hex_pub, hex_priv, text, copy, original); return -1; } // Wipe and then fill the data blocks with random data. memset(copy, 0, tlen + 1); memset(text, 0, tlen + 1); for (uint64_t j = 0; j < tlen; j++) { *(copy + j) = *(text + j) = (rand() % 255); } // Generate a key for our theoretical user. if (!(key = ecies_key_create())) { printf("Key creation failed.\n"); processor_cleanup(key, ciphered, hex_pub, hex_priv, text, copy, original); return -1; } // Since we'll store the keys as hex values in reali life, extract the appropriate hex values and release the original key structure. if (!(hex_pub = ecies_key_public_get_hex(key)) || !(hex_priv = ecies_key_private_get_hex(key))) { printf("Serialization of the key to a pair of hex strings failed.\n"); processor_cleanup(key, ciphered, hex_pub, hex_priv, text, copy, original); return -1; } if (!(ciphered = ecies_encrypt(hex_pub, text, tlen))) { printf("The encryption process failed!\n"); processor_cleanup(key, ciphered, hex_pub, hex_priv, text, copy, original); return -1; } if (!(original = ecies_decrypt(hex_priv, ciphered, &olen))) { printf("The decryption process failed!\n"); processor_cleanup(key, ciphered, hex_pub, hex_priv, text, copy, original); return -1; } if (olen != tlen || memcmp(original, copy, tlen)) { printf("Comparison failure.\n"); processor_cleanup(key, ciphered, hex_pub, hex_priv, text, copy, original); return -1; } processor_cleanup(key, ciphered, hex_pub, hex_priv, text, copy, original); printf(" ... %i ... %i\n", iteration + 1, tlen); return 0; }
/** * @brief Store a mail message, with its meta-information in the database, and the contents persisted to disk. * @note The stored message is always compressed, but only encrypted if the user's public key is suppplied. * @param usernum the numerical id of the user to which the message belongs. * @param pubkey if not NULL, a public key that will be used to encrypt the message for the intended user. * @param foldernum the folder # that will contain the message. * @param status a pointer to the status flags value for the message, which will be updated if the message is to be encrypted. * @param signum the spam signature for the message. * @param sigkey the spam key for the message. * @param message a managed string containing the raw body of the message. * @return 0 on failure, or the newly inserted id of the message in the database on success. * */ uint64_t mail_store_message(uint64_t usernum, stringer_t *pubkey, uint64_t foldernum, uint32_t *status, uint64_t signum, uint64_t sigkey, stringer_t *message) { chr_t *path; cryptex_t *encrypted = NULL; compress_t *reduced; uint64_t messagenum; int64_t transaction, ret; size_t write_len; uint8_t fflags = FMESSAGE_OPT_COMPRESSED; uchr_t *write_data; bool_t store_result; // Compress the message. if (!(reduced = compress_lzo(message))) { log_error("An error occurred while attempting to compress a message with %zu bytes.", st_length_get(message)); return 0; } // Next, encrypt the message if necessary. if (pubkey) { *status |= MAIL_STATUS_ENCRYPTED; if (!(encrypted = ecies_encrypt(pubkey, ECIES_PUBLIC_BINARY, reduced, compress_total_length(reduced)))) { log_pedantic("Unable to decrypt mail message."); compress_free(reduced); return 0; } compress_free(reduced); write_data = (uchr_t *)encrypted; write_len = cryptex_total_length(encrypted); fflags |= FMESSAGE_OPT_ENCRYPTED; } else { write_data = (uchr_t *)reduced; write_len = compress_total_length(reduced); } // Begin the transaction. if ((transaction = tran_start()) < 0) { log_error("Could not start a transaction. {start = %li}", transaction); if (encrypted) { cryptex_free(encrypted); } else { compress_free(reduced); } return 0; } // Insert a record into the database. if ((messagenum = mail_db_insert_message(usernum, foldernum, *status, st_length_int(message), signum, sigkey, transaction)) == 0) { log_pedantic("Could not create a record in the database. mail_db_insert_message = 0"); tran_rollback(transaction); if (encrypted) { cryptex_free(encrypted); } else { compress_free(reduced); } return 0; } // Now attempt to save everything to disk. store_result = mail_store_message_data(messagenum, fflags, write_data, write_len, &path); if (encrypted) { cryptex_free(encrypted); } else { compress_free(reduced); } // If storage failed, fail out. if (!store_result || !path) { log_pedantic("Failed to store user's message to disk."); tran_rollback(transaction); if (path) { unlink(path); ns_free(path); } return 0; } // Commit the transaction. if ((ret = tran_commit(transaction))) { log_error("Could not commit the transaction. { commit = %li }", ret); unlink(path); ns_free(path); return 0; } ns_free(path); return messagenum; }