Can you 'convert' ciphertext encrypted in CBC mode to ECB mode with known IV? - security

In CBC mode, C2 = Ek(C1 ⊕ P2)
C2 = 2nd block of ciphertext
P2 = 2nd block of plaintext
Ek = encryption function
If IV is known (let's say it's set to 0), is there anyway to find the ciphertext block such that C2 = Ek(P2) ?

If the message is only 1 block in size and the IV is null, then both ECB and CBC modes will produce an equivalent cipher text. However, the short answer to your question is NO. In most cases (like WEP and WPA) the IV is known to the attacker and this does not compromise the system. However, make sure that the IV is random when using CBC mode.
In Cipher Block Chaining mode (CBC), each plain text block is xor'ed with the previous cipher text block in the sequence. Thus you cannot decrypt the message in its entirety without following the "chain" or series of decryption routines. Its kind of like a one-time-pad meets a block cipher. The algorithm isn't that complex and here is a graphical representation of the two. Notice that they are nearly identical except CBC mode adds XOR operation for each block.

The simple answer is that if what you ask for was possible in general then CBC would then be equivalent to ECB anyway - there would be no security gained by CBC over ECB.
There is, however, an information leak in CBC. If you happen to observe two identical ciphertexts in CBC messages that were encrypted with the same key, Cn = Cm, then you can calculate Pn ⊕ Pm (it is equal to Cn-1 ⊕ Cm-1). Two identical ciphertexts are only likely in two cases: the first is that the sender re-used an IV, and the second is that you have observed a very large amount of traffic encrypted with the same key (for a 128 bit block cipher, on the order of 16 million TB; for a 64 bit block cipher, on the order of 4 GB).

Related

AES encryption constant input and output size

I have a key for AES encryption and I'm trying to encrypt strings with constant length as well, does the resultant encrypted string will always have the same length?
That depends on what you mean by 'the same length'.
The same length as the original string: generally no; the original string will be padded to a multiple of the cipher block-length. Check padding modes for details.
The same length every time you encrypt: yes; as long as you stick to the same mode and padding the encrypted output will have the same length.
First of all, a block cipher requires a full block to encrypt, therefore AES requires 16-byte ( or 128-bit ) input to encrypt will output 16-byte ciphertext. This is always the case for block ciphers since they are Pseudo-Random Permutations (PRP) - they are always permutations we expect them to be PRP.
Block ciphers, like AES, are primitives and must be used with a proper mode of operation. Here we will talk only about some of them.
ECB mode is the default and insecure.
Padding: In the case of the message size is not a multiple of the 128, we apply padding. There are various paddings, however, the most common one is the PCKS#7 ( update of PCKS#5 that was for 64-bit block ciphers like DES). This padding append characters to the end so that the size is multiple of 128.
Therefore; the appended number of characters for ECB mode can be from 1 to 16 ( if the block size is already a multiple of 128) then a new block is added with 16 10 bytes.
CBC mode requires a random and unpredictable IV so that we can achieve probabilistic encryption. As in ECB, it requires padding.
Therefore; the appended number of characters for CBC mode can be from 1+16 to 32 since we need to add the IV to the ciphertext.
CTR mode requires Initial Value (IV) that can be random or deterministic. CTR mode converts a block cipher (PRP) into a stream cipher. The plaintext is x-ored with the ciphertext where the input was the IV and incremented for each encryption. There is no need for padding in CTR mode.
Therefore; the appended number of characters for CTR mode is (at most)16.
AAED: The above are archaic mode of operations and today we use Authenticated Encryption (with Associated Data) (AE/AEAD). Unlike the archaic modes, these modes can provide us not only confidentiality but also integrity and authentication.
The authentication part requires a tag (MAC tag) and this really depends on the scheme.
AES-GCM is the NIST-approved mode. AES-GCM's recommended IV size 12 since different size requires an additional process. It always produces a 16-byte tag, however, one can reduce the size of the tag if they want to, although not recommended.
At first one might consider that the size is incremented by 12-16, however, it is not. The GCM always used Associated Data (AD) and allows zeroAD and the size of the AD is always added. For details, see NIST GCM specification
This was the short story of the long list of how the mode of operations behaves in terms of input vs output length.
If you omit the IV size, it is possible with CTR mode.

How does an IV work and what would be the best way to store it?

I want to encrypt and decrypt strings. I'm using Nodejs crypto for this. I've read that when encrypting and decrypting it's highly recommended to use an IV. I want to store the encrypted data inside a MySQL database and decrypt it later when needed. I understand that I need the IV also for the decryption process. But what exactly is an IV and how should I store it? I read something about that an IV does not to be kept secret. Does this mean I can store it right next to the encrypted data it belongs to?
it's highly recommended to use an IV
No, it's required or you'll not get a fully secure ciphertext in most circumstances. At the very minimum, not supplying an IV for the same key and plaintext message will result in identical ciphertext, which will leak information to an adversary. In other words: encryption would be deterministic, and that's not a property that you want from a cipher. For CTR and GCM mode you may well leak all of the plaintext message though...
But what exactly is an IV ... ?
An IV just consists of binary bits. It's size and contents depend on the mode of operation (CBC/CTR/GCM). Generally it needs either to be a nonce or randomized.
CBC mode requires a randomized IV of 16 bytes; generally a cryptographically secure random number generator is used for that.
CTR mode commonly specifies both a nonce and the initial counter value within the IV of 16 bytes. So you already need to put the nonce in the left hand bytes (lowest index). This nonce may be randomized, but then it should be large enough (e.g. 12 bytes) to avoid the birthday problem.
GCM mode requires just a nonce of 12 bytes.
and how should I store it
Anyway you can store the bytes, as long as they can be retrieved or regenerated during decryption. If you need text you may need to encode it using base 64 or hexadecimals (this goes for the ciphertext as well, of course).
I read something about that an IV does not to be kept secret.
That's correct.
Does this mean I can store it right next to the encrypted data it belongs to?
Correct, quite often the IV is simply prefixed to the ciphertext; if you know the block cipher and mode of operation then the size is predetermined after all.

What is the equivalent cipher to bouncycastle's PaddedBufferedBlockCipher with AESEngine and PKCS7 padding?

I want to decrypt AES-256 encrypted string using nodejs. I am using crypto module for that.
The string is encrypted using Bouncy castle java library. In Java the cipher is intialsed using:
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new AESEngine(), new PKCS7Padding());
crypto module of nodejs uses openssl's list of ciphers for intialising it, like:
var decipher = crypto.createDecipher('aes-256-cbc',key);
Which algorithm should I use?
Here is the list of algorithms to choose from:
-bash-4.1$ openssl list-cipher-algorithms|grep AES-256
AES-256-CBC
AES-256-CFB
AES-256-CFB1
AES-256-CFB8
AES-256-CTR
AES-256-ECB
AES-256-OFB
AES-256-XTS
AES256 => AES-256-CBC
aes256 => AES-256-CBC
If you encrypt something with a block cipher, you need
the block cipher which can take a single block of input and mangle it into a single block of output (for AES the block size is 16 bytes),
the mode of operation which enables you to encrypt more than one block in a structured fashion
the padding which enables you to encrypt something that is not exactly as long as a multiple of the block size.
The PaddedBufferedBlockCipher that you've shown only has two of them. The mode of operation is implied to be ECB mode, because it simply consists of applying the block cipher to each block separately.
You'll get the same behavior in node.js with:
var decipher = crypto.createDecipheriv('aes-xxx-ecb', key, '');
Exchange the xxx for the size of your key in bits. Valid sizes are 128 bit, 192 bit and 256 bit. Everything else will not work. Also, make sure that you get the encoding of your key right.
In case you're wondering why createDecipheriv is used here instead of createDecipher, I suggest that you carefully compare the documentation to both of those functions. createDecipher expects a password and not a key.
Other considerations:
Never use ECB mode. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like CBC or CTR. It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC scheme.
Decrypt the data with AES-256-ECB (I don't see any CBC or other modes.).
Call decipher.setAutoPadding(true) for using PKCS padding.

Can One-Time-Pad key be reused if encrypted plaintext is random?

I want to encrypt purely random data with one single key that is shorter than the plaintext.
Should I use AES or another robust encryption algorithm, or can I use OTP, i.e. only xoring (purely random) plaintext with the unique key, block by block?
E.g. data is 1024 bits long and is random. Key is 128-bit long (random too). Is it safe to encrypt data by xoring 8 successive 128-bit blocks with the same key?
Your question asks " Is it safe to encrypt data by xoring 8 successive 128-bit blocks with the same key?"
This is not a One-Time-Pad. A One-Time-Pad is used once and once only. Any compromise of part of the unencrypted data would allow recovery of all or part of the key, and hence recovery of more of the unencrypted data.
A safe encryption scheme is secure against an attacker knowing part or all of the plaintext: a "known plaintext attack". Your scheme is not safe; it is vulnerable to a known plaintext attack.
E.g. data is 1024 bits long and is random. Key is 128-bit long (random
too). Is it safe to encrypt data by xoring 8 successive 128-bit blocks
with the same key?
If your data is random, then the answer is yes.
You can consider your actual data as OTP key here. It's purely random and is used only once, so there's no way to recover either key or data.
If the data itself is random then it is an equally likely to the text space, so any transformation will lead safety. XOR or stream cipher maintains the relation that the blocks have in cipher-text as below..
from Crypto.Cipher import ARC4
key = '1234567812345678'
obj1 = ARC4.new(key)
obj2 = ARC4.new(key)
d1= obj1.encrypt('\x01\x82\x83\x04\x05\x06\x10\x81\x23\x32\x33\x34')
d2= obj2.encrypt('\x81\x02\x83\x84\x85\x86\x90\x01\xa3\xb2\x33\xb4')
print repr(d1)
print repr(d2)
p1='';p2=''
for i in d1:
if ord(i)>=128: p1+=chr(ord(i)-128)
else: p1+=chr(ord(i))
print; print
for i in d2:
if ord(i)>=128: p2+= chr(ord(i)-128)
else: p2+=chr(ord(i))
print p1==p2`
output:
'\xbaq\xba\xd0\x0c\xb7\xce&\xd3\x019\xfb'
':\xf1\xbaP\x8c7N\xa6S\x819{'
True

DES and ICryptoTransform

This method works fine in a program I've made. However I cannot really understand what is happening and where the encryption is actually performed. I read the related description from MSDN but not much information is given.
Can someone explain what is happening in general especially in line 8 and 9 please.
public byte[] Decrypt(byte[] input, byte[] key, byte[] iv)
{
DES des = new DESCryptoServiceProvider();
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.None;
des.Key = key;
ICryptoTransform ct = des.CreateDecryptor(key, iv);
byte[] result = ct.TransformFinalBlock(input, 0, input.Length);
return result;
}
If you want to understand what is going on, you should read about block cipher operations here:
http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29
In a nutshell, block ciphers chaining causes the input of one block operation to be fed into the next block operation. This obscures any block-level patterns in the ciphertext. Since there is a chaining structure, the last block gets an input from the second last block, and so on... until the second block gets an input from the first block. Now the first block needs to get an input from something, but there are no preceding blocks. So we use something called an Initialization Vector (iv) to start it off. This IV does not need to be secret like the key, but it does need to have a low probability of re-use (otherwise the attacker can use it to correlate the first blocks of all your ciphertexts). Typically random numbers are used, or sometimes increasing sequence numbers.
In regard to the specific call:
Your method works to decrypt a single block using DES. (Which is nowadays considered out of date and insecure, by the way, please consider using AES instead - the block cipher structures remain the same so all you need to do is swap the library). Anyway,
Since you're using a cipher in ECB mode, each block is decrypted independently with the same initialization vector, which is provided to your Decrypt method call. The call to CreateDecryptor initializes a decryption object using the provided secret key and initialization vector.
The actual decryption is performed using the call to TransformFinalBlock. The arguments are the input byte array, and then an offset and a length parameter (used for when you don't want to decrypt the entire byte array). In this case you do want to use the entire byte array so the starting offset is 0 and the size is the length of the whole byte array.
One thing you should probably add is to check that the input byte array is the correct block size for your cipher, otherwise it will throw an exception. In the case of DES, this is 64 bits. If you switch to AES as I recommended it will be 128 bits.

Resources