Is multiple encryption a good idea?
By adding more algorithms, you do two things:
- Potentially increase the strength of the encryption.
- Increase the attack surface of your application.
AES128-CBC is strong. If you're implementing it properly, and using strong random keys and unique random IVs, you're very safe. The US government (NSA) certifies AES for use in securing top-secret documents. I somewhat doubt that your security requirements are anywhere near theirs, so you should consider AES more than strong enough alone. If you're really paranoid, move up to 256-bit AES.
Chaining algorithms only provides more provable security if you use independent keys for each. Using the same key for all ciphers means you still only have to bruteforce one key, though at 128 bits it's been predicted that we might never posess the equipment to do so.
Chaining multiple algorithms makes some sense in ridiculously high-security high-paranoia long term storage situations like TrueCrypt volumes, where the deployment environment is completely unknown. However, unless you're likely to be storing military secrets that'll be shipped into a hostile country, and happen to be a professional cryptographer, I'd stick with just using AES.
It is extremely rare that the algorithm itself is a vulnerability. Even weak algorithms such as RC4 are often the strongest part of the system in which they are used. Vulnerabilities usually hide in how you apply encryption (padding, IV randomness, integrity checks...) and in key management. These seemingly peripheral activities are quite hard to do right, and have repeatedly proven to be the number one source of weakness in any encryption system. By encrypting three times, you have tripled the opportunities for such nasty weaknesses.
So don't do it.
Personally, I would avoid multiple encryption protocols most of the time. It adds significant extra implementation complexity without making your data any more secure in the real world, unless the encryption protocol you are using is ultimately broken or becomes computationally feasible at a later date to break.
Granted, I will disagree with others who claim that by doing so you have a larger attack surface and increase your vulnerabilities. While the attack surface technically does increase (you can attack blowfish; you can attack AES), since you must successfully attack both your security has not decreased. (Assuming your message is multiply-encrypted in a nested fashion (anything else doesn't make sense) with independent keys/passphrases like multiply_encrypted_file = Blowfish(AES(file))
. If an attacker gets a hold of multiply_encrypted_file
it is not in any way weaker than getting hold of encrypted_file = AES(file)
though you should beware of exposing yourself to known-plaintext attacks which could weaken security if you used the same key/passphrase at all levels and have a guessable header/structure of the file after the first level of decryption). Even if they find a exploitable flaw in Blowfish
encryption, they still only can reverse that and then find an AES encrypted file.
However, I do use multiple layers of encryption on an almost daily basis when there is a legitimate reason for it and it provides extra security. For example, I often need to connect to work computers from my home, but for security the work computers are on a private intranet, firewalled off from the outside world.
To connect, I first create a VPN tunnel over the public internet to a public facing VPN-server that verifies my identity that acts as a gateway to the intranet. Then all my network traffic sent over the internet between my house and work encrypted using IPsec protocol by VPN to the VPN server which decrypts it and forwards it to the local machine as if it was on the local intranet. However, I may then want to connect to something at work using ssh
or https
. This provides a layer of encryption for the local intranet at work, so my coworkers could not say eavesdrop in on my network connections. However, to someone at my ISP capturing packets the data they see has been multiply encrypted: VPN_encryption(ssh_encryption(actual_data_to_be_transferred))
. Again, I'm not using the ssh protocol (on top of VPN) to make my data more secure against my ISP eavesdropping; but in no way does it make it easier for my ISP to eavesdrop).
EDIT: Some keeping arguing that implementation would be much tougher than standard encryption, but not necessarily. To demonstrate, I first implement Blowfish/AES in python using pycrypto:
from Crypto.Cipher import Blowfish, AES
from Crypto import Random
from hashlib import sha256, sha512
def encrypt(plaintext, key, crypto_class):
block_size = crypto_class.block_size
iv = Random.new().read(block_size)
cipher = crypto_class.new(key, crypto_class.MODE_CBC, iv)
pad_len = block_size - (len(plaintext) % block_size)
padding = ''.join([chr(pad_len)]*pad_len)
encrypted_msg = iv + cipher.encrypt(plaintext + padding)
return encrypted_msg
def decrypt(encrypted_msg, key, crypto_class):
block_size = crypto_class.block_size
iv = encrypted_msg[:block_size]
cipher = crypto_class.new(key, crypto_class.MODE_CBC, iv)
padded_msg = cipher.decrypt(encrypted_msg[block_size:])
pad_len = ord(padded_msg[-1])
msg = padded_msg[:len(padded_msg)-pad_len]
return msg
which an be used in python like:
>>> plaintext = """CONFIDENTIAL INFO: Wall Street does insider trading. Also, Israel has nuclear weapons."""
>>> passphrase = 'dinner artist mere trace metal thirty warp better'
>>> key1 = sha256(passphrase).digest()[0:16] # use 16-bytes=128bits for AES128
>>> key2 = sha512(passphrase).digest()[0:56] # 56 bytes max for Blowfish.
# ideally independent keys but based on same passphrase for simplicity
>>> aes_encrypted_msg = encrypt(plaintext, key1, AES) # '\r\xd0\x8e\x11\xbd\x9cN3\xd3\xa7a\xce\xd7\x15\xb4\xb2\xd7@\nBv\x95\xe0\xdb\xd0\xd2\xf2K\x9b\xcd\x80\xc0xr\xb7\x8d/\x16=\xfadV\xf0\xe2\xc8"x,\xa6\xf8\xed\x8b\xee#\xe1\xd1\xd4U4*0\x07\x11\x08\xc5\xe3\x98\r5\x018\xa5\xf1\x84\xb4\x90\xbc\x12\x80E\xbd\xe9\tN\xe1M\x92\xbb=\x06\r\xfe(\xe8\x12\xc7\x86=\n\x0f\x00\xa1R\xe6\x9c\xca\xaa\x15\xc1(\xaa\xe6'
>>> print decrypt(aes_encrypted_msg, key1, AES)
CONFIDENTIAL INFO: Wall Street does insider trading. Also, Israel has nuclear weapons.
>>> blowfish_encrypted_msg = encrypt(plaintext, key2, Blowfish) # "a\xd2\xe5mf\xac\x81f\xe9Q\xbd.\xd9SwA\x8a)\xcc\x84S\x08\x00\x84\xc6Y\xf5\xa1\x16\x88JaUoF\t4\xa2\xf2b\x89s\xaa\xa6\xb3\xda\xe2\xdd\xff\x0f\xc2\xe2\x1dW\xf6\x840\xe9\x08Eje\xfa\x14\xb77\x99\x00a\xe0\xcd\xaf\xbe\x83\x08\xc0'\x81\x8b\x85\xf0\xdaxT\x94!o\xd0\x07\x0f#\xae$,\x91Q"
>>> print decrypt(blowfish_encrypted_msg, key2, Blowfish)
CONFIDENTIAL INFO: Wall Street does insider trading. Also, Israel has nuclear weapons.
Now, you with minimal details you can implement something like:
def double_encrypt_using_keys(plaintext, key1, key2):
tmp_encrypted_msg = encrypt(plaintext, key1, AES)
encrypted_msg = encrypt(tmp_encrypted_msg, key2, Blowfish)
return encrypted_msg
def double_decrypt_using_keys(encrypted_msg, key1, key2):
tmp_encrypted_msg = decrypt(encrypted_msg, key2, Blowfish)
plaintext = decrypt(tmp_encrypted_msg, key1, AES)
return plaintext
def passphrase_to_keys(passphrase):
return sha256(passphrase).digest()[0:16], sha512(passphrase).digest()[0:56]
def double_encrypt(plaintext, passphrase):
return double_encrypt_using_keys(plaintext, *passphrase_to_keys(passphrase))
def double_decrypt(encrypted_msg, passphrase):
return double_decrypt_using_keys(encrypted_msg, *passphrase_to_keys(passphrase))
Which can be used like:
>>> double_encrypted_msg = double_encrypt(plaintext, passphrase) # '\xe9\xcd\x89\xed\xb1f\xd4\xbel\xcb\x8b2!\x98\xf0\xe7\xcd.\xefE\x1b\x92>\x82(\x8dG\xdaUS\x8f!\xe2rgkJ\xfb\xed\xb0\x10~n\xae\xe1\xce\x10\xf0\xa4K\x9f\xe6\xff\x8b\x7f\xdex]\x9a<\x9d\xc7\xa9\xb8\x9a\xbbx\xa4\xcekoA\xbc=)\xcc\xe6R\xd7\xb7\xd0[\xc3\xfc\xbfOU\x86\x18\xec5\xa9N\xed\xaa=\x9f\x06.\xbd\x0cMy\xcch\r\xf8\x8cR\xc0\xc5\xdeO\xef\xb0\xe01\x162\xaf\xf2\x1f\xd5\xb5"\x8a\xea\x96'
>>> print double_decrypt(double_encrypted_msg, passphrase)
CONFIDENTIAL INFO: Wall Street does insider trading. Also, Israel has nuclear weapons.
I don't see how the multiply-encrypted implementation has more of an attack surface and is in anyway weaker than a singly-implemented one. The implementation to the outside world can still be enter a password to decrypt a stored file.