I am trying to decrypting using openssl api functions instead of direct system command, I have encrypted through the system command using this
Edit: Solution at below answer by me.
openssl enc -aes-256-cbc -pbkdf2 -iter 310000 -md sha256 -salt -in file.run -out encrypted_data.enc -pass pass:Password!
Before this I have created my symetrickeys and used those for the above.
This is my code used for the decrypting with the system command
bool CryptoProcessor::_decryptData(Any &response)
{
String tempPrefix = String("/tmp/aaaa-") + uuid();
std::ifstream input(_inputFile, std::ios::binary); //the input file is the encrypted file which had signature and symetric key on top of it
input.seekg(SIGNATURE_SIZE + KEY_SIZE, std::ios::beg);
String encryptedDataFileName = tempPrefix + ".encrypted-data";
OutputFileStream encryptedDataFile;
encryptedDataFile.open(encryptedDataFileName, std::ios::binary);
char chunk[CHUNK_SIZE];
while (!input.eof())
{
input.read(chunk, CHUNK_SIZE);
int bytesRead = input.gcount();
encryptedDataFile.write(chunk, bytesRead);
}
encryptedDataFile.close();
input.close();
String runFileName = tempPrefix + ".run";
String command = String("openssl enc -aes-256-cbc -d -pbkdf2 -iter 310000 -p -md sha256 -salt -pass pass:") + _symmetricKey + " -in '" + encryptedDataFileName + "' -out '" + runFileName +"'";
//I added -p to understand how the salt , key and iv are there and identify them as coming right or wrong when i use the openssl api
logger(LOG_INFO) << command << endl;
ANY_ASSERT(system(command.c_str()) == 0, "Decryption failed")
return true;
}
I am trying like this to decrypt it using api but code succcesfully decrypts the file but it is giving the wrong file i.e decrypting not done properly, I checked the salt, key and IV of these in the below code, i found those are very different and not the expected.
// Create an OpenSSL BIO object for input and output
BIO *bio_in = BIO_new_file(encryptedDataFileName.c_str(), "rb");
BIO *bio_out = BIO_new_file(runFileName.c_str(), "wb");
if (!bio_in || !bio_out)
{
logger(LOG_ERROR) << "Failed to open input/output BIOs" << std::endl;
return false;
}
// Create an EVP decryption context
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx)
{
BIO_free_all(bio_in);
BIO_free_all(bio_out);
logger(LOG_ERROR) << "Failed to create cipher context" << std::endl;
return false;
}
// Set the AES-256-CBC cipher
if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, nullptr, nullptr) != 1)
{
EVP_CIPHER_CTX_free(ctx);
BIO_free_all(bio_in);
BIO_free_all(bio_out);
logger(LOG_ERROR) << "Failed to initialize decryption context" << std::endl;
return false;
}
EVP_CIPHER_CTX_set_padding(ctx, 0); // Disable padding
// Set the symmetric key using PBKDF2
unsigned char derivedKey[32]; // 256 bits for AES-256
int iterCount = 310000;
logger(LOG_INFO) << "Iterations: " << iterCount << std::endl;
const char *passphrase = _symmetricKey.c_str();
logger(LOG_INFO) << "Passphrase: " << _symmetricKey << std::endl;
unsigned char salt[PKCS5_SALT_LEN];
RAND_bytes(salt, sizeof(salt))
unsigned char iv[16];
RAND_bytes(iv, sizeof(iv));
if (PKCS5_PBKDF2_HMAC(passphrase, -1, salt, sizeof(salt), iterCount, EVP_sha256(), 32, derivedKey) != 1)
{
EVP_CIPHER_CTX_free(ctx);
BIO_free_all(bio_in);
BIO_free_all(bio_out);
logger(LOG_ERROR) << "Failed to derive encryption key using PBKDF2" << std::endl;
return false;
}
logger(LOG_INFO) << "Derived Key: ";
for (int i = 0; i < 32; ++i)
{
logger(LOG_INFO) << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(derivedKey[i]);
}
logger(LOG_INFO) << std::dec << std::endl;
// Set the key and IV for decryption
if (EVP_DecryptInit_ex(ctx, nullptr, nullptr, derivedKey, nullptr) != 1)
{
EVP_CIPHER_CTX_free(ctx);
BIO_free_all(bio_in);
BIO_free_all(bio_out);
logger(LOG_ERROR) << "Failed to set decryption key and IV" << std::endl;
return false;
}
Help me, In writing the code for the given system command of openssl with api.
Decryption MUST use the same values for salt and IV as encryption used, but you're generating new random values which will be wrong with overwhelming probability.
openssl encstores the salt at offset 8-15 in the file (read it from there), and only offset 16-last is actually ciphertext (decrypt only that part); it also derives both key and IV (if the mode uses it, which CBC does) from password+salt, so do the PBKDF2 call to generate 48 bytes and use the first 32 for the key and the last 16 for the IV. Also for a block mode like CBCencby default uses PKCS5/7 padding, so by turning off padding during decryption you will add some garbage bytes to your plaintext.PS: if you declare
inBuf outBufas array ofunsigned char(not justchar) you don't need to the ugly casts, and as a bonus it more accurately describes what is in at least the encrypted file and potentially the decrypted one, namely raw data that is not actually characters.