Hey I'm looking for some explanation regarding
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length,
const AES_KEY *key, unsigned char *ivec, int *num, int enc)
I understand the straightforward variables like
in is our input buffer
out is our output buffer
length is size of our input/number of bytes of input buffer
key is pointer to our key which we set by AES_set_encrypt_key
enc is the mode we want(whether encryption or decryption)
However, I don't understand what ivec and num do.
I just know (might be wrong) is that ivec stands for initial vector and another thing in a code that i found online there was a comment:
/* set where on the 128 bit encrypted block to begin encryption*/. At first, I thought this left gaps of unencrypted data in the midst of encrypted one, but that wasn't the case when I looked at the byte values while debugging and printing values.
ivec is an Initialisation Vector and commonly written as IV. The keyword is the probabilistic encryption;
If the encryption is not probabilistic then when you re-encrypt a message under the same key, you will get the same result and an eavesdropper will notice this. This is a simple attack, in some modes, this is more catastrophic like CTR mode where encryption of two messages under the same IV can cause loss of confidentiality.
In CFB mode, if you encrypt two different messages then the first blocks are under attack where the attacker gets x-or of the messages.
One should generate random IV's per message since the IV must be unpredictable for CFB mode ( as in CBC mode).
Note that, you need to send the IV to the receiver so that the decryption works. The IV need not be secret, one can prepend it to cyphertext.
Don't forget that, those are archaic mode of operation, in modern cryptography we prefer authenticated encryption modes like AES-GCM, AES-CCM, and ChaCha20-Poly1305.
And, the key is still secure even if you don't generate random per message!
Related
I've generated a random 256 bit symmetric key, in a file, to use for encrypting some data using the OpenSSL command line which I need to decrypt later programmatically using the OpenSSL library. I'm not having success, and I think the problem might be in the initialization vector I'm using (or not using).
I encrypt the data using this command:
/usr/bin/openssl enc -aes-256-cbc -salt -in input_filename -out output_filename -pass file:keyfile
I'm using the following call to initialize the decrypting of the data:
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))
keyfile is a vector<unsigned char> that holds the 32 bytes of the key. My question is regarding that last parameter. It's supposed to be an initialization vector to the cipher algorithm. I didn't specify an IV when encrypting, so some default must have been used.
Does passing nullptr for that parameter mean "use the default"? Is the default null, and nothing is added to the first cipher block?
I should mention that I'm able to decrypt from the command line without supplying an IV.
What is the default IV when encrypting with EVP_aes_256_cbc() [sic] cipher...
Does passing nullptr for that parameter mean "use the default"? Is the default null, and nothing is added to the first cipher block?
There is none. You have to supply it. For completeness, the IV should be non-predictable.
Non-Predictable is slightly different than both Unique and Random. For example, SSLv3 used to use the last block of ciphertext for the next block's IV. It was Unique, but it was neither Random nor Non-Predictable, and it made SSLv3 vulnerable to chosen plaintext attacks.
Other libraries do clever things like provide a null vector (a string of 0's). Their attackers thank them for it. Also see Why is using a Non-Random IV with CBC Mode a vulnerability? on Stack Overflow and Is AES in CBC mode secure if a known and/or fixed IV is used? on Crypto.SE.
/usr/bin/openssl enc -aes-256-cbc...
I should mention that I'm able to decrypt from the command line without supplying an IV.
OpenSSL uses an internal mashup/key derivation function which takes the password, and derives a key and iv. Its called EVP_BytesToKey, and you can read about it in the man pages. The man pages also say:
If the total key and IV length is less than the digest length and MD5 is used then the derivation algorithm is compatible with PKCS#5 v1.5 otherwise a non standard extension is used to derive the extra data.
There are plenty of examples of EVP_BytesToKey once you know what to look for. Openssl password to key is one in C. How to decrypt file in Java encrypted with openssl command using AES in one in Java.
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))
I didn't specify an IV when encrypting, so some default must have been used.
Check your return values. A call should have failed somewhere along the path. Maybe not at EVP_DecryptInit_ex, but surely before EVP_DecryptFinal.
If its not failing, then please file a bug report.
EVP_DecryptInit_ex is an interface to the AES decryption primitive. That is just one piece of what you need to decrypt the OpenSSL encryption format. The OpenSSL encryption format is not well documented, but you can work it backwards from the code and some of the docs. The key and IV computation is explained in the EVP_BytesToKey documentation:
The key and IV is derived by concatenating D_1, D_2, etc until enough
data is available for the key and IV. D_i is defined as:
D_i = HASH^count(D_(i-1) || data || salt)
where || denotes concatentaion, D_0 is empty, HASH is the digest
algorithm in use, HASH^1(data) is simply HASH(data), HASH^2(data) is
HASH(HASH(data)) and so on.
The initial bytes are used for the key and the subsequent bytes for the
IV.
"HASH" here is MD5. In practice, this means you compute hashes like this:
Hash0 = ''
Hash1 = MD5(Hash0 + Password + Salt)
Hash2 = MD5(Hash1 + Password + Salt)
Hash3 = MD5(Hash2 + Password + Salt)
...
Then you pull of the bytes you need for the key, and then pull the bytes you need for the IV. For AES-128 that means Hash1 is the key and Hash2 is the IV. For AES-256, the key is Hash1+Hash2 (concatenated, not added) and Hash3 is the IV.
You need to strip off the leading Salted___ header, then use the salt to compute the key and IV. Then you'll have the pieces to feed into EVP_DecryptInit_ex.
Since you're doing this in C++, though, you can probably just dig through the enc code and reuse it (after verifying its license is compatible with your use).
Note that the OpenSSL IV is randomly generated, since it's the output of a hashing process involving a random salt. The security of the first block doesn't depend on the IV being random per se; it just requires that a particular IV+Key pair never be repeated. The OpenSSL process ensures that as long as the random salt is never repeated.
It is possible that using MD5 this way entangles the key and IV in a way that leaks information, but I've never seen an analysis that claims that. If you have to use the OpenSSL format, I wouldn't have any hesitations over its IV generation. The big problems with the OpenSSL format is that it's fast to brute force (4 rounds of MD5 is not enough stretching) and it lacks any authentication.
So I am using the Crypto++ Library to encrypt a file. I need to save the key and iv for future use. I am following this tutorial. Here is my function :
void AESUtil::encrypt(string filename,bool savekeys,string savefilename){
AutoSeededRandomPool rnd;
// Generate a random key
byte key[AES::DEFAULT_KEYLENGTH];
rnd.GenerateBlock(key, AES::DEFAULT_KEYLENGTH);
// Generate a random IV
byte iv[AES::BLOCKSIZE];
rnd.GenerateBlock(iv, AES::BLOCKSIZE);
Binary b;
string plaintext = b.decoder(filename);
unsigned char *ciphertext= new unsigned char[plaintext.size()+1];
ciphertext[plaintext.size()]='\0';
if(savekeys){
ofstream("key.bin", ios::binary).write((char*)key, sizeof(key));
}
CFB_Mode<AES>::Encryption cfbEncryption(key, AES::DEFAULT_KEYLENGTH, iv);
cfbEncryption.ProcessData(ciphertext,reinterpret_cast<const unsigned char*>(plaintext.c_str()),plaintext.size()+1);
ofstream outfile(savefilename.c_str());
outfile.write((char*)ciphertext,sizeof(ciphertext));
}
The files contain data in �/���� format. I want to know the best method to save the key and iv programmatically which are a byte array to a file and the ciphertext which is a unsigned char* to a separate file.
The key could be saved in a separate file. Normally the key is established between sender / receiver in advance, or it is encrypted using a public key of the receiver. Note that it doesn't make sense to save the key next to the ciphertext, as it would provide no protection whatsoever. The handling of keys is called key management and entire books have been written about it.
The IV is a different animal. The IV should be randomly generated. For CFB it should at least be unique and identical at both sides. Usually the IV is simply prefixed to the ciphertext, it doesn't have to be kept secret.
Your key and iv variables are the key and IV used to encrypt the plain text.
You didn't fill either; you're actually using an array filled with 0 bytes as both the key and IV for your encryption.
The IV is public information. You don't need to hide it. Save it the way you want.
The KEY is what you must keep safe. To do that you may decide how much effort you want to put on it to hide it from the external factors.
I have some keys that I don't care to leave them as a "plain text" in the binary code. (NO SECURITY, but my mom can't figure out what to do, but a beginner in reverse engineer will laugh at it.)
Some keys I do a play with the bytes, like inverting parts, separating them, XOR with something. (Very unsafe, but better than nothing, a programmer with decent knowledge in reverse engineering will be able to spend some time and eventually break the security)
Some other cases I use 3rd party advanced obfuscation... If possible, depending on what you want, you may even replace your encryption engine with some "white-box" cryptography. Then you will have your keys very well protected. But this is usually hard/expensive. It doesn't seem to be your case. (Yes, even a very advanced assembly guru will not be happy to start reverse engineer this case.)
Another solution, if you don't need the key on your binary, is to give it to the system's password manager. On Windows, it's called "Data Protection API", and on Mac, it's called "Keychain". Take a look at these, and then you will understand why this is considered security. But it's because all the passwords here are encrypted with the "user password" so nothing is stored "on disk". A turned-off device in this scenario is considered very secure.
When using Botan encryption with botansqlite3, what are the optimal configuration settings for performance?
OR
How can I configure Botansqlite3 to use CAST5?
I am currently using AES and it is too slow. My use case is a game.
I am looking for weak or moderate encryption to protect my game's data (not end user data) so security is less of a consideration than performance.
Here is my current BotanSqlite3 codec.h
/*These constants can be used to tweak the codec behavior as follows */
//BLOCK_CIPHER_STR: Cipher and mode used for encrypting the database
//make sure to add "/NoPadding" for modes that use padding schemes
const string BLOCK_CIPHER_STR = "Twofish/XTS";
//PBKDF_STR: Key derivation function used to derive both the encryption
//and IV derivation keys from the given database passphrase
const string PBKDF_STR = "PBKDF2(SHA-160)";
//SALT_STR: Hard coded salt used to derive the key from the passphrase.
const string SALT_STR = "&g#nB'9]";
//SALT_SIZE: Size of the salt in bytes (as given in SALT_STR)
const int SALT_SIZE = 64/8; //64 bit, 8 byte salt
//MAC_STR: CMAC used to derive the IV that is used for db page
//encryption
const string MAC_STR = "CMAC(Twofish)";
//PBKDF_ITERATIONS: Number of hash iterations used in the key derivation
//process.
const int PBKDF_ITERATIONS = 10000;
//KEY_SIZE: Size of the encryption key. Note that XTS splits the key
//between two ciphers, so if you're using XTS, double the intended key
//size. (ie, "AES-128/XTS" should have a 256 bit KEY_SIZE)
const int KEY_SIZE = 512/8; //512 bit, 64 byte key. (256 bit XTS key)
//IV_DERIVATION_KEY_SIZE: Size of the key used with the CMAC (MAC_STR)
//above.
const int IV_DERIVATION_KEY_SIZE = 256/8; //256 bit, 32 byte key
//This is definited in sqlite.h and very unlikely to change
#define SQLITE_MAX_PAGE_SIZE 32768
I believe that I need to find replacements for BLOCK_CIPHER_STR, PBKDF_STR, MAC_STR, KEY_SIZE and IV_DERIVATION_KEY_SIZE to reconfigure BotanSqlite3 to use a different codec.
I found a extensive comparison test of Botan codec performance here:
http://panthema.net/2008/0714-cryptography-speedtest-comparison/crypto-speedtest-0.1/results/cpu-sidebyside-comparison-3x2.pdf#page=5
However, the testing was done with Botan directly, not botansqlite3 as I intend to use it. Looking at the charts, a good candidate appears to be CAST5 from a performance perspective.
The database in question is 300KB, mostly INTEGER fields with some text blobs.
I am configuring Botan as suggested by OlivierJG of botansqlite3 fame, using the amalgamation
'./configure.py --no-autoload --enable-modules=twofish,xts,pbkdf2,cmac,sha1 --gen-amalgamation --cc=msvc --os=win32 --cpu=x86 --disable-shared --disable-asm'
References:
http://github.com/OlivierJG/botansqlite3 - botansqlite3 is an encryption codec for SQLite3 that can use any algorithms in Botan for encryption
http://www.sqlite.org - sqlite3 is a cross-platform SQL database
http://botan.randombit.net/ - botan is a C++ encryption library with support for a number of codecs
You can get CAST-128 (or as I was calling it, CAST5) to work, it is a block cipher.
The best bet is the above with different configuration of key size.
Twofish is pretty fast.
Thank you to 'Olivier JG' for all the excellent code.
I need to encrypt single block of AES. I cant use any modes like CBC and other. Every example what i have seen use streaming modes.
EDIT:
ok, i did it in the next manner, but i really dislike this try.
void dec(const byte *key, const byte* xblock, const byte *cipher, byte *plain) {
AESDecryption d;
try {
const NameValuePairs &nvp = MakeParameters("", 0);
d.UncheckedSetKey(key, 16, nvp);
d.ProcessAndXorBlock(cipher, xblock, plain);
}
catch(...) {}
}
AES in ECB mode is identical to single block encryption, except that you can feed it multiple blocks.
If you've got only CBC mode encryption available you can use the first block of a CBC encrypt using a (block sized) IV containing bytes all valued zero. The same goes for counter (CTR) mode encryption and a nonce containing bytes all valued zero (the counter only increases after the first block encrypt).
Crypto++ seems to be a higher level Crypto API, so it is better not to directly call the AES implementation directly.
I need to encrypt single block of AES. I cant use any modes like CBC and other. Every example what i have seen use streaming modes.
EDIT:
ok, i did it in the next manner, but i really dislike this try.
void dec(const byte *key, const byte* xblock, const byte *cipher, byte *plain) {
AESDecryption d;
try {
const NameValuePairs &nvp = MakeParameters("", 0);
d.UncheckedSetKey(key, 16, nvp);
d.ProcessAndXorBlock(cipher, xblock, plain);
}
catch(...) {}
}
AES in ECB mode is identical to single block encryption, except that you can feed it multiple blocks.
If you've got only CBC mode encryption available you can use the first block of a CBC encrypt using a (block sized) IV containing bytes all valued zero. The same goes for counter (CTR) mode encryption and a nonce containing bytes all valued zero (the counter only increases after the first block encrypt).
Crypto++ seems to be a higher level Crypto API, so it is better not to directly call the AES implementation directly.