web-dev-qa-db-fra.com

Le chiffrement multiple est-il une bonne idée?

Je sais que de nombreux algorithmes de chiffrement, bien que sécurisés, présentent des vulnérabilités. Pour réduire les risques, un chiffrement multiple comme celui-ci

Blowfish_CbC ( Rc2_OFB ( AES128_CBC (myfilecontent)))

être une bonne idée?

Je sais que le temps d'exécution augmente sérieusement, mais ce n'est pas un problème pour moi. Des suggestions ou des idées?

20
Surfer on the fall

Personnellement, j'éviterais la plupart du temps plusieurs protocoles de cryptage. Il ajoute une complexité d'implémentation supplémentaire importante sans rendre vos données plus sécurisées dans le monde réel, à moins que le protocole de chiffrement que vous utilisez soit finalement rompu ou devienne réalisable par ordinateur à une date ultérieure.

Certes, je ne serai pas d'accord avec ceux qui prétendent que ce faisant, vous disposez d'une surface d'attaque plus grande et augmentez vos vulnérabilités. Bien que la surface d'attaque augmente techniquement (vous pouvez attaquer des Blowfish; vous pouvez attaquer AES), puisque vous devez réussir à attaquer à la fois, votre sécurité n'a pas diminué. (En supposant que votre message est crypté en plusieurs fois de manière imbriquée (tout le reste n'a pas de sens) avec des clés/phrases de passe indépendantes comme multiply_encrypted_file = Blowfish(AES(file)). Si un attaquant obtient multiply_encrypted_file, Il est pas du tout plus faible que de mettre la main sur encrypted_file = AES(file) bien que vous devez vous méfier de vous exposer à des attaques connues en clair ce qui pourrait affaiblir la sécurité si vous utilisez la même clé/phrase de passe à tous les niveaux et avoir un en-tête/une structure du fichier devinable après le premier niveau de décryptage). Même s'ils découvrent une faille exploitable dans le cryptage Blowfish, ils ne peuvent que l'inverser et trouver un fichier crypté AES.

Cependant, j'utilise plusieurs couches de cryptage presque quotidiennement lorsqu'il y a une raison légitime à cela et qu'il offre une sécurité supplémentaire. Par exemple, j'ai souvent besoin de me connecter à des ordinateurs professionnels depuis mon domicile, mais pour des raisons de sécurité, les ordinateurs professionnels sont sur un intranet privé, protégé par un pare-feu du monde extérieur.

Pour me connecter, je crée d'abord un tunnel VPN sur Internet public vers un serveur VPN public qui vérifie mon identité qui agit comme une passerelle vers l'intranet. Ensuite, tout mon trafic réseau envoyé sur Internet entre ma maison et mon travail est chiffré à l'aide du protocole IPsec par VPN au serveur VPN qui le déchiffre et le transmet à la machine locale comme s'il se trouvait sur l'intranet local. Cependant, je peux alors vouloir me connecter à quelque chose au travail en utilisant ssh ou https. Cela fournit une couche de cryptage pour l'intranet local au travail, de sorte que mes collègues ne pouvaient pas dire écoute sur mes connexions réseau. Cependant, pour quelqu'un de mon FAI qui capture des paquets, les données qu'il voit ont été cryptées à plusieurs reprises: VPN_encryption(ssh_encryption(actual_data_to_be_transferred)). Encore une fois, je n'utilise pas le protocole ssh (en plus du VPN) pour sécuriser mes données contre l'écoute de mon FAI; mais en aucun cas cela ne facilite l’écoute de mon FAI).


EDIT: Certains continuent de faire valoir que la mise en œuvre serait beaucoup plus difficile que le cryptage standard, mais pas nécessairement. Pour démontrer, j'implémente d'abord Blowfish/AES dans python en utilisant 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

qui peut être utilisé dans python comme:

>>> 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.

Maintenant, avec un minimum de détails, vous pouvez implémenter quelque chose comme:

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))

Qui peut être utilisé comme:

>>> 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.

Je ne vois pas comment l'implémentation à chiffrement multiple a plus d'une surface d'attaque et est en tout cas plus faible qu'une implémentation unique. L'implémentation au monde extérieur peut encore être saisir un mot de passe pour décrypter un fichier stocké.

11
dr jimbob

En ajoutant plus d'algorithmes, vous faites deux choses:

  1. Potentiellement augmente la force du cryptage.
  2. Augmentez la surface d'attaque de votre application.

AES128-CBC est solide. Si vous l'implémentez correctement et utilisez des clés aléatoires solides et des IV aléatoires uniques, vous êtes très en sécurité. Le gouvernement américain (NSA) certifie AES pour une utilisation dans la sécurisation de documents top secrets. Je doute un peu que vos exigences de sécurité soient proches des leurs, vous devriez donc considérer AES plus que suffisamment fort seul. Si vous êtes vraiment paranoïaque, passez à AES 256 bits.

Les algorithmes de chaînage n'offrent une sécurité plus prouvée que si vous utilisez des clés indépendantes pour chacun. L'utilisation de la même clé pour tous les chiffrements signifie que vous n'avez toujours qu'à forcer une seule clé, bien qu'à 128 bits, il ait été prédit que nous pourrions ne jamais posséder l'équipement pour le faire.

Le chaînage de plusieurs algorithmes est logique dans des situations de stockage à long terme ridiculement haute sécurité et paranoïa comme les volumes TrueCrypt, où l'environnement de déploiement est complètement inconnu. Cependant, à moins que vous ne stockiez probablement des secrets militaires qui seront expédiés dans un pays hostile et que vous soyez un cryptographe professionnel, je m'en tiendrai à l'utilisation d'AES.

16
Polynomial

Il est extrêmement rare que l'algorithme lui-même soit une vulnérabilité. Même les algorithmes faibles tels que RC4 sont souvent la partie la plus solide du système dans lequel ils sont utilisés. Les vulnérabilités se cachent généralement dans comment vous appliquez le chiffrement (remplissage, aléatoire IV, vérifications d'intégrité ...) et dans la gestion des clés. Ces activités apparemment périphériques sont assez difficiles à faire correctement et se sont révélées à plusieurs reprises être la principale source de faiblesse de tout système de cryptage. En chiffrant trois fois, vous avez triplé les opportunités de telles faiblesses désagréables.

Alors ne le fais pas.

13
Thomas Pornin