I have been implementing AES in C and I am now finalising the program by implementing padding. Reading lots of other SO questions on the padding topic I have found that a popular way to do this is by filling each of the remaining places in the state with the number of places left. For example if I only had 12 bytes to encrypt, I would pad the remaining 4 bytes with 4. My question is when decrypting if I have a block which is full but ends in a 1, how do I know if this is one byte of padding or just the value 1?
DISCLAIMER: I know this program should never be used in production as it probably has all sorts of different insecurities. I am doing this for fun, not to encrypt top secret documents.
What you're describing is the PKCS#7 padding.
In order to disambiguate, you always need to have padding. Additionally, the plaintext for modes like ECB or CBC mode needs to be a multiple of the block size.
Both constraints put together lead to a simple solution: you always add padding up to the next multiple of the block size. If the plaintext is already a multiple of the block size, then you add a full block of padding where each byte represents 16 (for AES).
Related
I'm new to Crypto and am trying to make a block cipher encryption program. And I've stumbled across a doubt while writing the CFB part.
Supposing we have a 64-bit block cipher with. And we use 7-bit CFB along with it. Then, for each block, the block will be run nine times wherein nine 7-bit left shifts to the block (starting with IV) and subsequent additions take place.
This means after 9 rounds of CFB, 63 bits of the 64-bit block are processed. At the end we have one bit remaining. How do I process this bit? Do I take seven bits again or just encrypt the one remaining bit?
I have this same question for any case where the s is not a factor of the block size.
Looking back, this question seems silly.
I've now understood that the plaintext, if it's length isn't a multiple of the block size, must be padded to be so.
Due to some limitation of a client, they are padding the plain text with 0x00 before passing it to the AES alogirhtm, instead of the normal PKCS5/PKCS7 or similar padding.
While it is doable in my server side, I have a question of whether using 0-padding works. Take an example that the plain text ends with exactly the 0-padding character. It is impossible for the server side to distinguish it.
Is 0-padding one of the acceptable padding method and if so how should my side handle the padding correctly?
Thanks in advance.
Unsure what is meant by "ASCII code 0", I will assume a byte with the value 0x00? (Yes hex is still a thing) See Zero padding: Zero padding may not be reversible if the original file ends with one or more zero bytes, making it impossible to distinguish between plaintext data bytes and padding bytes.
Null padding (0x00) can work for data that does not end with a null, ASCII text is an example that works. The deprecated PHP mcrypt does this and the null padding creates interoperability issues.
So: yes null padding does work for some data such as text but fails for binary data. It is best not to use it, PKCS#7.PKCS#5 padding is a better and more generally used padding.
i was wondering exactly how block cipher worked, i need to end up with 10 or less blocks after its done and i really haven't found anything online that can tell me how many blocks it will make and if i can limit it to 10 or less?
If you know of any resources like websites that can help me with this it would be greatly appreciated!
A Block Cypher such as AES encrypts data a block at a time appending the block of encrypted data to the output. Block sized vary and AES uses a 16-byte block. (RSA is not a block cypher)
Since data is frequently not a multiple go the block size data is added to the end of the data, this is called padding and the most commonly used padding is PKCS#7 née PKCS#5. (As an option see CTR mode below)
Additionally there are modes such as ECB, CBC, CTR and others. ECB (Electric Code Book) is mostly a null mode in that it does nothing. CBC (Cypher Block Chaining) is a mode that includes some data from the previous block and also had an IV so that encryption the same data does not produce the same encrypted data. CTR (Counter) is a streaming mode that does not require padding but has other requirements such as a Nonce.
If I encrypt emails so that I can store them in a database, the resulting string is longer than the email itself. Is there a maximum length to this resulting coded string? if so, does it depend on both key length and the email length? I need to know this so I can set my database fields to the correct length.
Thanks.
As Alex K. notes, for block ciphers (like DES), common modes will pad them out to a multiple of the block size. The block size for 3DES is 64-bits (8 bytes). The most common padding scheme is PKCS7, which pads the block with "n x n bytes." This is to say, if you need one bytes of padding, it pads with 0x01. If you need four bytes of padding, it pads with 0x04040404 (4x 4s). If your data is already the right length, it pads with a full block (8 bytes of 0x08 for 3DES).
The short version is that the padded cipher text for 3DES can be up to 8 bytes longer than the plaintext. If your encryption scheme is a typical, insecure implementation, this is the length. The fact that you're using 3DES (an obsolete cipher) makes it a bit more likely that it's also insecurely implemented, and so this is the answer.
But if your scheme is implemented well, then there could be quite a few other things attached to the message. There could be 8 bytes of initialization vector. There could be a salt of arbitrary length if you're using a password. There could be an HMAC. There could be lots of things that could add an arbitrary amount of space. (The RNCryptor format, for example, adds up to 82 bytes to the message.) So you need to know how your format is implemented.
This should be a simple question, but I can't find any examples or figure out the answer from the openssl docs.
I want to encrypt exactly 128 bits, which should fit in one encryption block.
So I call EVP_EncyptInit_ex, and then what?
Do I call EVP_EncryptUpdate_ex (to encrypt the 128 bit block) and EVP_EncryptFinal_ex (even though there is nothing more left to encrypt)?
Or only EVP_EncryptUpdate_ex?
Or only EVP_EncryptFinal_ex?
Here, you have already figured out the steps.
So, it will be
EVP_encryptInit_ex
EVP_EncryptUpdate_ex
EVP_EncryptFinal_ex
EVP_EncryptFinal_ex also take care of the fact that data is not in multiple of block lengths.
In my opinion, if you have only to use AES with no padding (EVP_ interfaces takes care of padding), then go for AES_encrypt.
They are fairly easy to use.
//Step 1: Set encrypt key.
AES_KEY aeskey;
AES_set_encrypt_key(key, bits, &aeskey);
//Step2: Encrypt exactly 128 bits.
AES_encrypt(data, dataout, &aeskey);
AES encryption of 16 bytes without padding
Use the EVP_* interfaces and disable padding on the block.
Use the EVP_* interface because it supports engines and hardware acceleration, like AES-NI. The AES_encrypt functions are software based and do not support alternate implementations. Also, its not readily apparent, but AES_encrypt is not portable - some platforms suffer endianess issues.
You need to call EVP_CIPHER_CTX_set_padding to ensure no padding is added. From the EVP_CIPHER_CTX_set_padding(3) man page:
EVP_CIPHER_CTX_set_padding() enables or disables padding. By default
encryption operations are padded using standard block padding and the
padding is checked and removed when decrypting. If the pad parameter
is zero then no padding is performed, the total amount of data
encrypted or decrypted must then be a multiple of the block size or an
error will occur.
This function should be called after the context is set up for
encryption or decryption with EVP_EncryptInit_ex().
So your steps are:
Call EVP_CIPHER_CTX_new to create a context
Call EVP_EncryptInit_ex with the context
Call EVP_CIPHER_CTX_set_padding on the context
Call EVP_EncryptUpdate_ex to encrypt the data
Call EVP_EncryptFinal_ex to retrieve the cipher text
Also see EVP Symmetric Encryption and Decryption on the OpenSSL wiki.