Szeretné megérteni a Pretty Good Privacy-t? Szimulálja.

Ahogy a neve is sugallja, a Pretty Good Privacy (vagy PGP) egy olyan titkosító program, amely valójában nagyon jó adatvédelmet biztosít. A „nagyon jó” bit kissé ironikus lebecsülést jelent. Phil Zimmermann 1991-ben történt fejlesztése után az e-mail kommunikáció végpontok közötti titkosításának egyik domináns formája volt. Egyre népszerűbb lett, miután a visszaélést bejelentő Edward Snowden használta.

A PGP két dolgot biztosít a biztonságos kommunikációhoz:

  1. Titoktartás: Szimmetrikus blokkos titkosítás, tömörítés a ZIP algoritmus használatával és az e-mail kompatibilitás a radix64 kódolási séma segítségével
  2. Hitelesítés: digitális aláírások használatával biztosított

Minden további kérdés nélkül térjünk rá a PGP működésére.

Hogyan működik

Elmagyarázom a PGP fogalmát a megvalósítás szempontjából Alice (a feladó) és Bob (a vevő) összefüggésében. A következő algoritmusokat fogjuk használni:

  1. RSA mint aszimmetrikus titkosítási algoritmus
  2. Az SHA-512 mint hash algoritmus
  3. DES mint szimmetrikus titkosítási algoritmus és
  4. ZIP tömörítéshez

Használhat más algoritmusokat is. (Tudom, hogy a DES túl régi ahhoz, hogy használni lehessen, de itt a cél a PGP fogalmának megértése.)

Alice és Bob egyaránt létrehozza a kulcspárját (Nyilvános és Saját Kulcs) az RSA algoritmus segítségével. Alice és Bob nyilvános kulcsait ismerniük kell egymásnak.

Alice / Feladó oldala:

  1. Alice M üzenetet ír, amelyet el akar küldeni Bobnak.
  2. Az M bemenetként szolgál az SHA-512 algoritmushoz, hogy megkapja annak 512 bites bináris hashját (128 bites hexadecimális karakterláncként ábrázolva).
  3. Ezt a kivonatot digitálisan aláírja az RSA algoritmus, vagyis a kivonatot Alice titkos kulcsai titkosítják. Az RSA bemenetei Alice Private Keys és a hash. Az RSA kimenete a digitálisan aláírt hash vagy a titkosított hash EH.
  4. Most M és EH együtt vannak csatolva. (Olyan értelemben csatolva, hogy egy sor karakterláncba kerülnek).
  5. M és EH (amelyek stringek tömbjében vannak) a ZIP tömörítési algoritmus bemeneteként működnek, hogy a tömörített M és a tömörített EH-t megkapják, ismét egy húr tömbben.
  6. A fenti lépés kimenetét a DES szimmetrikus titkosítási algoritmus segítségével titkosítjuk. Ehhez először a SecretKey-t generáljuk a DES-hez. Ez a kulcs és az 5. lépés kimenete bemenetként fog működni a DES titkosítási algoritmusban, amely titkosított kimenetet biztosít számunkra (ismét egy sor karakterláncban).
  7. Végül, de nem utolsósorban, mivel az M titkosítás a SecretKey használatával történik, Bobnak is el kell küldeni. Titkosítani fogjuk a SecretKey of DES algoritmust Bob nyilvános kulcsával. Ehhez az RSA-t fogjuk használni, és ennek bemenete Bob és SecretKey nyilvános kulcsa lesz.
  8. A 6. és 7. lépés kimeneteit most csatolják és elküldik utolsó üzenetként Bobnak.

Az egész üzenetet stringek tömbjeként ( String finalmessage[]) küldjük, amelyek a következőket tartalmazzák az indexekben:

0: Tömörített M üzenet, amelyet a SecretKey kódol

1: Digitálisan aláírt hash EH, amelyet azután a SecretKey-vel tömörítenek és titkosítanak

2: A 7. lépés kimenete

Bob / vevő oldala:

  1. Bob először a Privát kulcsaival dekódolja a DES SecretKey-t. Az RSA algoritmus bemenete ehhez Bob és finalmessage[2]. Az RSA kimenete megadja Bobnak a SecretKey-t.
  2. Ez a SecretKey mostantól a DES visszafejtési algoritmusának egyik bemeneteként fog működni a finalmessage[0]és visszafejtésére finalmessage[1]. Ez a kettő a DES visszafejtési algoritmus bemeneteként is működik. Ennek a lépésnek a kimenete decrypted versiona finalmessage[0]és finalmessage[1].
  3. A fenti lépés kimeneteit a dekompressziós ZIP algoritmus bemeneteként kell megadni.
  4. A fenti lépés kimenetéből megkapjuk a digitálisan aláírt kivonatot és az eredeti M üzenetet. Ellenőrizzük, hogy a kivonatot Alice írta-e alá. Ehhez kiszámoljuk az eredeti M üzenet kivonatát az SHA-512 ( calculated_hash) használatával. A digitálisan aláírt kivonatot az Alice nyilvános kulcsaival is visszafejtjük az RSA használatával. (Bemenetek az RSA-hoz: digitálisan aláírt hash és Alice nyilvános kulcsai és az RSA kimenete decrypted_hash:).
  5. Hasonlítsa össze a decrypted_hashés calculated_hash. Ha kiderül, hogy azonosak, akkor a hitelesítést elérjük, ami azt jelenti, hogy az üzenetet valóban Alice küldte.

Az alábbiakban bemutatjuk a PGP szimulációját a Java segítségével a legegyszerűbben.

import java.util.*; import java.math.*; import javax.crypto.Cipher; import java.security.*; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import javax.crypto.spec.*; public class PGP{ static Cipher ecipher, dcipher;//Required for DES public static void main(String args[]) throws Exception{ //Generating sender keys KeyPair senderkeyPair = buildKeyPair(); PublicKey senderpubKey = senderkeyPair.getPublic(); PrivateKey senderprivateKey = senderkeyPair.getPrivate(); //Generating receiver keys KeyPair receiverkeyPair = buildKeyPair(); PublicKey receiverpubKey = receiverkeyPair.getPublic(); PrivateKey receiverprivateKey = receiverkeyPair.getPrivate(); //Sending both public keys and private keys for choice of digital signature or normal assymetric encryption String messagetoreceiver[] = senderside(senderpubKey, senderprivateKey, receiverpubKey, receiverprivateKey); receiverside(messagetoreceiver, senderpubKey, senderprivateKey, receiverpubKey, receiverprivateKey); } public static void receiverside(String messagetoreceiver[], PublicKey senderpubKey, PrivateKey senderprivateKey, PublicKey receiverpubKey, PrivateKey receiverprivateKey) throws Exception { //Receiver receives the message messagetoreceiver[] with messagetoreceiver[2] as secret key encrypted with receiver pub key //Receiver decrypts the messagetoreceiver[2] with his/her privatekey String receiverencodedsecretkey = decrypt(receiverpubKey, receiverprivateKey, messagetoreceiver[2], 1); //Key after decryption is in base64 encoded form byte[] decodedKey = Base64.getDecoder().decode(receiverencodedsecretkey); SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "DES"); System.out.println("\nReceiver Side: Receiver SecretKey DES after Decryption with his/her Private Key=\n"+originalKey.toString()); //Decrypt the rest of the message in messagetoreceiver with SecretKey originalKey String receiverdecryptedmessage[] = new String[messagetoreceiver.length-1]; System.out.println("\nReceiver Side: Message After Decryption with SecretKey="); for (int i=0;iencryptwithprivatekey 1->encryptwithpublickey public static String encrypt(PublicKey publicKey, PrivateKey privateKey, String message, int ch) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); if (ch == 0) { cipher.init(Cipher.ENCRYPT_MODE, privateKey); byte[] utf8 = cipher.doFinal(message.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(utf8); } else { cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] utf8 = cipher.doFinal(message.getBytes("UTF-8")); return new sun.misc.BASE64Encoder().encode(utf8); } } //n: 0->decryptwithpublickey 1->decryptwithprivatekey public static String decrypt(PublicKey publicKey,PrivateKey privateKey, String st, int ch) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); byte[] encrypted = new sun.misc.BASE64Decoder().decodeBuffer(st); if (ch == 0) { cipher.init(Cipher.DECRYPT_MODE, publicKey); byte[] utf8 = cipher.doFinal(encrypted); return new String(utf8, "UTF8"); } else { cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] utf8 = cipher.doFinal(encrypted); return new String(utf8, "UTF8"); } } }

Használtuk az base64 kódolási sémát, amely hasonló a PGP-ben használt radix64-hez.

Jegyzet:

  1. A64-et kódoljuk a karakterláncokat titkosítás és tömörítés után, hogy olvasható szöveges formát kapjunk.
  2. A visszafejtéshez és a dekompresszióhoz a base64 dekódolt bemeneteket küldjük tényleges bemenetként a visszafejtési és dekompressziós algoritmusokba.
  3. A kulcsot base64 kódolással és dekódolással láttam el, mióta a Java-t használtam a PGP szimulációjához, amihez kódolt formára van szükség a vevő oldalán, így a dekódolási folyamathoz SecretKey adattípussá alakítható.

Kérjük, kövesse, tapsolja és ossza meg. Kommentáljon bármilyen hibát, fejlesztést vagy javaslatot. Még a Twitteren is követhetsz.