web-dev-qa-db-fra.com

Pourquoi PGP utilise-t-il le chiffrement symétrique et RSA?

En examinant les détails de Pretty Good Privacy, je suis confus quant au raisonnement derrière le cryptage du message avec une clé de session et la clé avec la clé publique du destinataire via RSA. Je n'arrive pas à voir comment cela est plus sûr que le simple chiffrement RSA du message réel.

Il est très probable que je sois tout simplement trop naïf en termes de sécurité et de cryptage, mais si je peux obtenir votre clé privée RSA, pourquoi est-ce important que cela me donne accès au corps du message ou à l'autre clé qui déverrouillera le message corps?

23
Ken Bellows

RSA n'est pas vraiment conçu pour crypter de gros morceaux de texte en clair. Chaque "tour" RSA peut chiffrer 117 octets de données, et pour en chiffrer plus, vous devrez utiliser --- mode de chaînage . Actuellement, cela signifie des frais supplémentaires, une lenteur (rappelez-vous, RSA est assez lent) et une incertitude de sécurité (RSA-chaningMode n'a pas été examiné comme d'autres types de schémas de cryptage). <- MAUVAIS

En utilisant cryptage hybride (symétrique + asymétrique pour la clé symétrique), vous obtenez l'avantage de l'asymétrique, à savoir, ne pas avoir à vous soucier de l'échange de clés; et symétrique, très rapide et a été bien vérifié. <- BON

Pour plus d'informations, veuillez vérifier: Comment puis-je utiliser le chiffrement asymétrique, tel que RSA, pour chiffrer une longueur arbitraire de texte en clair?

34
Adi

RSA est un algorithme lent, en particulier pour le décryptage. Vous devez calculer m = c^d mod N Où d est à peu près la taille du module. Pour RSA-1024/2048/4096 (où 1024/2048/4096 est le nombre d'octets du module N), même avec une exponentiation modulaire rapide par quadrature répétée, il nécessite environ 1,5 lg N (~ 1500/~ 3000/~ 6000) multiplications d'entiers à N bits. La multiplication d'un entier à N bits n'est pas une opération primitive mais évolue comme O (N ^ 1,6) pour un entier à n bits (donc chaque multiplication est environ 84/256/776 fois plus lente qu'une primitive de multiplication à 64 bits).

Remarque: le cryptage RSA est beaucoup plus rapide que le décryptage car avec un remplissage correct, il n'y a aucune faiblesse dans le choix d'un petit exposant de clé publique comme e = 65537 où votre étape d'exponentiation ne nécessite que ~ 17 multiplications; en fait, e = 3 ne nécessitant que deux multiplications fonctionnerait parfaitement avec un rembourrage approprié.

De plus, une application de RSA b-bit signifiant que vous deviez générer deux nombres premiers ayant approximativement cette longueur chacun) ne peut décrypter qu'un message jusqu'à environ b-128 bits (en utilisant un pavé aléatoire de 128 bits) ou environ 112/240/496 octets car vous décodez uniquement un nombre compris entre 0 et N. Cette réponse avec un codage 8 bits ASCII aurait besoin de 7449 octets.

Par conséquent, ce qui se passe habituellement, c'est que vous chiffrez simplement une clé symétrique, car la clé symétrique sera beaucoup plus rapide et l'utilisation d'un mode de chiffrement (par exemple, CBC, CTR) peut chiffrer des messages de taille arbitraire.


Informations de synchronisation pour justifier l'analyse ci-dessus

J'ai créé au hasard une paire de clés RSA 4096 bits (N, e) et (N, d) (en utilisant import rsa; rsa.newkeys(nbits=4096)), puis j'ai effectué des synchronisations pour comparer le "manuel" (faible - sans octets aléatoires remplis) Cryptage RSA/décryptage en cryptage AES.

La configuration pour le chronométrage RSA est donnée ci-dessous cryptage/décryptage:

>>> encryption = "pow(m,e,N)"
>>> decryption = "pow(c,d,N)"
>>> setup =  """N = 650022002033202164791638561174816123258916492020045683486079596172818033518252144860009135975860423604411399274822133841546708494765449009472683563317182198759309684914356008659922538583279515419473227210977474088638850782595732910857797571156318425669817244314450827318145758475770172116229990603884173470104902799641093008914867436680133631971559712828465243806241512864086546090728020169682901285441149037545107765998640217114788723715575098893307499744794060936075307573516246976128444578474543743151813381476261995022381469996299316134038828450334308951123635607639233510908350391842701316709834010335732144351192249236953330927673972067894385163240378028762678952835544528074929660347162229394149982403274141710996800529609644247153732931740566379474447028470447165473543764460712691302632667942726305345440613110797535733482536487121364569032950159436896042439632454394173272272373593467791776848612054118558722637286863035388661691125609333937871344046274188817824229897604542696165894703693345718292207375417809743565484488696015562272970275127353631067240331072960179800283770558952793368549384848991363395614092594834723746484679602433778811932755737361396956451757817273043140309312219744371338360280947729616063853738641

e = 65537

d = 163256819101675505935126275492278764497028632049833711493978518287449606050176698725845711249563797130302144316394896364372168726426893063398086141449880510117616574052677112204439095245140620165777031598832556014144612720776443287192263118867708337069520909431555619232749121633751575949969416441703671137188560661642925231956585104715733090960096935672315454064890600755952584778878850298197667808388563912873529057301030226798746088352508752731797937742028323588321094384242144517250929974849184277771012531228150089843422784017258750683831715157735366668225506845014904307329056055723208632277201486994123654288753880392020556964543443597828229493325467616467308118864809565200248599428162198788308364968380312577988297310500286974136209331121821893719017982045957945241683426015912952303440579610553088057331105677592306795472995839704525934407019706992740653789223747419222232691256397983243926154436341276701812083801394467756814989897357722664273229362826815661611670740504736110949984419908621950792127278167263015929591331285519955311164883226113070661776218890597216617564529563317568347817244502395174702566462626236588608296425638109493962233171124725237010153412040065506840529586822535766472003407847003802265141256193

m= int("This is a secret message provided as a test for RSA-4096 and AES encryption.  To be fair it is 496 bytes long.  Keyboard mashing follows: asdbklajsdgl;sdjgl;kasjdgiowepgj opijg aslekgjase;lgk jasel; elask;gj lask;lgjl;ske gjasle;k asel;k gjl;asekgj asljsel;k jseal; gkjasel; kjsael;kjg aal;se asegkl;j asel;kjasegl;k jasegl;k jasel;gk jasegl;k jasel gkjsael;gkjasel;gkj sea;lekgjseal;kjasegl;asekgjasel;kgjsael;jkasel;gjkgasel;asfasfl;kjasf;lkjsadfkljdl;kfaskl;jfasldk;fkfkjl;akasdfasdfasdfkjkjga".encode('hex'),16)
c = pow(m, e, N)
"""
>>> import timeit
>>> timeit.repeat(encryption, setup=setup, repeat=3, number=1)
[0.0044488906860351562, 0.0045480728149414062, 0.0044538974761962891]

>>> timeit.timeit(decryption, setup=setup, repeat=3, number=1)  
[1.9231810569763184, 1.9048171043395996, 1.9280149936676025]

Le chiffrement RSA 4096 bits prend environ 4,5 ms par exécution et le déchiffrement prend 1,9 seconde (environ 500 fois plus lent que le chiffrement car d est beaucoup plus grand que e). Le chiffrement de ce message avec RSA nécessiterait 16 blocs et prendrait environ 30 secondes à déchiffrer. En répétant pour d'autres tailles RSA, j'ai trouvé que le RSA 1024 bits prend ~ 0,5 ms pour le cryptage et 40 ms pour le décryptage. Le RSA 2048 bits prend ~ 1,6 ms pour le chiffrement et ~ 270 ms pour le déchiffrement.

Examinons maintenant AES-128, en utilisant la bibliothèque pycrypto.

setup = """
from Crypto.Cipher import AES 
from Crypto import Random
from hashlib import sha256

def aes_encrypt(plaintext, key):
    block_size = AES.block_size
    iv = Random.new().read(block_size)
    cipher = AES.new(key, AES.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 aes_decrypt(encrypted_msg, key):
    block_size = AES.block_size
    iv = encrypted_msg[:block_size]
    cipher = AES.new(key, AES.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

key = sha256("secret passphrase").digest()[0:16]
message = "This is a secret message provided as a test for RSA-4096 and AES encryption.  To be fair it is 496 bytes long.  Keyboard mashing follows: asdbklajsdgl;sdjgl;kasjdgiowepgj opijg aslekgjase;lgk jasel; elask;gj lask;lgjl;ske gjasle;k asel;k gjl;asekgj asljsel;k jseal; gkjasel; kjsael;kjg aal;se asegkl;j asel;kjasegl;k jasegl;k jasel;gk jasegl;k jasel gkjsael;gkjasel;gkj sea;lekgjseal;kjasegl;asekgjasel;kgjsael;jkasel;gjkgasel;asfasfl;kjasf;lkjsadfkljdl;kfaskl;jfasldk;fkfkjl;akasdfasdfasdfkjkjga"
cipher = aes_encrypt(message,key)
"""

>>> timeit.repeat("aes_encrypt(message,key)", setup=setup, repeat=3, number=1)
[6.198883056640625e-05, 6.198883056640625e-05, 6.008148193359375e-05]

>>> timeit.repeat("aes_decrypt(cipher,key)", setup=setup, repeat=3, number=1)
[1.0967254638671875e-05, 9.059906005859375e-06, 9.059906005859375e-06]

Bottomline, le cryptage AES est à peu près 8/25/5 fois plus rapide que RSA et le décryptage AES est environ 4000/25000/2000 fois plus rapide que RSA (au cryptage 1024/2048/4096 bits respectivement). Par conséquent, le chiffrement hybride a toujours un sens chaque fois que vous avez besoin de plusieurs blocs.

10
dr jimbob

D'après quelque chose que j'ai écrit il y a 3 ans: "Il existe 2 types de base de cryptage que nous utilisons tous les jours de notre vie. Tout le monde les utilise. Même ma grand-mère.

Le type 1 est symétrique, alias Single Key, alias Secret key, alias ultra-rapide ... Notez comment tous les mots S vont ensemble :)

Le type 2 est asymétrique, alias clé publique/clé privée (ou simplement clé publique pour faire court), alias Two Key, alias vraiment-fricking-slow encryption. C'est ce que les gens pensent généralement qu'ils utilisent lorsqu'ils utilisent PGP. (ils le sont, mais ils utilisent également le cryptage symétrique pour effectuer la majeure partie du travail) " http://www.infosecisland.com/blogview/4497-Public-Key-Private-Key-Secret-Key- Everyday-Encryption-.html

Fondamentalement, comme dr jimbob l'a montré ci-dessus, la clé publique est trop lente à utiliser pour le chiffrement en masse. Le mélanger avec Symmetric corrige cela, et la raison pour laquelle nous n'utilisons pas symétrique seul est qu'il y a un problème d'échange de clés. Sinon, comment pouvons-nous nous assurer que le destinataire prévu obtient la clé et qu'il est le seul à l'obtenir?

2
Rod MacPherson

Une autre raison pour laquelle cela est utile est qu'il augmente la flexibilité. Par exemple, le chiffrement uniquement de la clé de session vous permet d'utiliser plusieurs paires de clés avec un temps système relativement faible. Vous ajoutez simplement une clé de session chiffrée par paire de clés.

1
Tim Lamballais