Der Diffie-Hellmann Schlüsselaustausch ist mit wenigen Zeilen Programmcode nutzbar und ist dennoch ein vollwertiger Algorithmus.
Hier noch einmal in Kurzform die Vorgehensweise: beide Partner erzeugen ihre Schlüsselpaare (KeyPairs) und tauschen dann ihre öffentlichen Schlüssel (public keys) aus. Im Programm geschieht das einfach durch „Vertauschen“ in der Ansicht, in der Praxis werden die öffentlichen Schlüssel z.B. auf einer persönlichen Webseite veröffentlicht. Dann erzeugen beide Partner den gemeinsamen geheimen Schlüssel (shared secret key), der dann z.B. für eine symmetrische Verschlüsselung genutzt werden kann. In diesem Beispiel ist der gemeinsame geheime Schlüssel 64 Byte lang und damit „zu lang“ für eine AES-Verschlüsselung (Schlüssellänge maximal 32 Byte). Für eine „sichere“ Kürzung des Schlüssels sorgt hier der SHA-256-Hash-Algorithmus; alternativ wäre auch die Nutzung von HKDF (Kryptografische Erzeugung von abgeleiteten Schlüsseln) denkbar.
Schlüsselaustauschsteckbrief | |
Name des Verfahrens | DH |
Langname | Diffie-Hellmann Schlüsselaustausch |
Basis | Diskreter Logarithmus |
Blocklänge (Byte) | – |
Schlüssellänge (Byte/Bit) | 64/512, 128/1024, 256/2048, 512/4096, 1024/8192 |
Padding genutzt | Nein |
Sicherheit | nur ab 2048 Bit Schlüssellänge |
Besonderes | – |
Der nachfolgende Quellcode ist durch die Ausgaberoutinen deutlich länger als der „eigentliche“ Programmcode.
Bitte die nachfolgende Routine nicht für den Echteinsatz nutzen, da sie aus kryptographischer Sicht angreifbar ist !
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
package net.bplaced.javacrypto.keyexchange; /* * Herkunft/Origin: http://javacrypto.bplaced.net/ * Programmierer/Programmer: Michael Fehr * Copyright/Copyright: frei verwendbares Programm (Public Domain) * Copyright: This is free and unencumbered software released into the public domain. * Lizenttext/Licence: <http://unlicense.org> * getestet mit/tested with: Java Runtime Environment 8 Update 191 x64 * getestet mit/tested with: Java Runtime Environment 11.0.1 x64 * Datum/Date (dd.mm.jjjj): 14.01.2019 * Funktion: elektronischer Schlüsselaustausch mittels Diffie-Hellmann * Function: digital key exchange using Diffie-Hellmann * * Sicherheitshinweis/Security notice * Die Programmroutinen dienen nur der Darstellung und haben keinen Anspruch auf eine * korrekte Funktion, insbesondere mit Blick auf die Sicherheit ! * Prüfen Sie die Sicherheit bevor das Programm in der echten Welt eingesetzt wird. * The program routines just show the function but please be aware of the security part - * check yourself before using in the real world ! */ import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import javax.crypto.KeyAgreement; public class E01_DiffieHellmanKeyexchange { public static void main(String[] args) throws Exception { System.out.println("E01 Diffie Hellman Schlüsselaustausch Intern"); // hinweis: eine sichere schlüssellänge wird erst ab 2048 bit erreicht int dhKeyLengthInt = 512; // 512, 1024, 2048, 4096, 8192 bit // jeder der beiden benutzer erzeugt ein eigenes schluessel-paar // benutzer a // unsere variablen fuer den benutzer a KeyPair aKeyPair = generateDhKeyPair(dhKeyLengthInt); PrivateKey aPrivateKey = aKeyPair.getPrivate(); // der private schluessel von benutzer a PublicKey aPublicKey = aKeyPair.getPublic(); // der public schluessel von benutzer a byte[] aSharedSecretByte = null; // unsere variablen fuer den benutzer b KeyPair bKeyPair = generateDhKeyPair(dhKeyLengthInt); PrivateKey bPrivateKey = bKeyPair.getPrivate(); // der private schluessel von benutzer a PublicKey bPublicKey = bKeyPair.getPublic(); // der public schluessel von benutzer a byte[] bSharedSecretByte = null; // ausgabe der schluessel fuer jeden benutzer System.out.println("\n= = = Erzeugung der Schlüssel von Benutzer A = = ="); System.out.println("Benutzer A PrivateKey (Hex):" + printHexBinary(aPrivateKey.getEncoded())); System.out.println("Benutzer A PublicKey (Hex) :" + printHexBinary(aPublicKey.getEncoded())); System.out.println("\n= = = Erzeugung der Schlüssel von Benutzer B = = ="); System.out.println("Benutzer B PrivateKey (Hex):" + printHexBinary(bPrivateKey.getEncoded())); System.out.println("Benutzer B PublicKey (Hex) :" + printHexBinary(bPublicKey.getEncoded())); // nun werden die public keys untereinander getauscht // in der realen welt wird der public key zB per mail oder einer webseite // verteilt // hier werden die beiden public keys "nur" beim jeweils anderen benutzer // angezeigt System.out.println("\n= = = Schlüssel bei Benutzer A = = ="); System.out.println("Benutzer A PrivateKey (Hex):" + printHexBinary(aPrivateKey.getEncoded())); System.out.println("Benutzer B PublicKey (Hex) :" + printHexBinary(bPublicKey.getEncoded())); System.out.println("\n= = = Schlüssel bei Benutzer B = = ="); System.out.println("Benutzer B PrivateKey (Hex):" + printHexBinary(bPrivateKey.getEncoded())); System.out.println("Benutzer A PublicKey (Hex) :" + printHexBinary(aPublicKey.getEncoded())); // erzeugung des shared secret keys bei jedem benutzer // benutzer a aSharedSecretByte = createDhSharedSecret(aPrivateKey, bPublicKey); // benutzer b bSharedSecretByte = createDhSharedSecret(bPrivateKey, aPublicKey); // ausgabe der shared keys fuer jeden benutzer System.out.println("\n= = = Gemeinsame Schlüssel (SharedSecred) bei den Benutzern = = ="); System.out.println("Benutzer A SharedSecret (Hex):" + printHexBinary(aSharedSecretByte)); System.out.println("Benutzer B SharedSecret (Hex):" + printHexBinary(bSharedSecretByte)); // die laenge des schluessels duerfte zu gross fuer viele aes-verfahren sein, // daher kuerzen wir den schluessel mittels eines hashes System.out.println("\nSchlüssel-Länge des SharedSecretByte :" + aSharedSecretByte.length + " Byte/" + (aSharedSecretByte.length * 8) + " Bit"); // hashing der ausgabe um einen 32 byte = 256 bit schluessel zu erhalten MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] sharedSecret32Byte = digest.digest(aSharedSecretByte); System.out.println("= = = Der gemeinsame Schlüssel wird per SHA-256 Hash auf eine Länge von 32 Byte gebracht = = ="); System.out.println("SharedSecretByte nach SHA-256Hash (Hex) :" + printHexBinary(sharedSecret32Byte)); System.out.println("Schlüssel-Länge des SharedSecret32Byte :" + sharedSecret32Byte.length + " Byte/" + (sharedSecret32Byte.length * 8) + " Bit"); // ab hier folgt zb die verschluesselung einer datei mittels aes mit nutzung des // sharedSecret32Byte als key } public static KeyPair generateDhKeyPair(int keylengthInt) throws NoSuchAlgorithmException, NoSuchProviderException { KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("DH"); keyGenerator.initialize(keylengthInt); return keyGenerator.genKeyPair(); } public static byte[] createDhSharedSecret(PrivateKey privateKey, PublicKey publicKey) throws NoSuchAlgorithmException, InvalidKeyException { KeyAgreement keyAgree = KeyAgreement.getInstance("DH"); keyAgree.init(privateKey); // initialisierung mit dem private key des benutzers a keyAgree.doPhase(publicKey, true); // ergaenzung mit dem public key des benutzers b return keyAgree.generateSecret(); // erzeugung des shared keys bei benutzer a } public static String printHexBinary(byte[] bytes) { final char[] hexArray = "0123456789ABCDEF".toCharArray(); char[] hexChars = new char[bytes.length * 2]; for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } } |
Auf der Konsole seht Ihr die Ergebnisse:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
E01 Diffie Hellman Schlüsselaustausch Intern = = = Erzeugung der Schlüssel von Benutzer A = = = Benutzer A PrivateKey (Hex):3081D202010030819706092A864886F70D010301308189024100FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E170240678471B27A9CF44EE91A49C5147DB1A9AAF244F05A434D6486931D2D14271B9E35030B71FD73DA179069B32E2935630E1C2062354D0DA20A6C416E50BE794CA4020201800433023100A4C3B114545E32813460C9E89B38435FEA74BCFE9A05F9B743563C8928D9E3C30B658E5E6EE81C78EC56A125BD53C926 Benutzer A PublicKey (Hex) :3081E030819706092A864886F70D010301308189024100FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E170240678471B27A9CF44EE91A49C5147DB1A9AAF244F05A434D6486931D2D14271B9E35030B71FD73DA179069B32E2935630E1C2062354D0DA20A6C416E50BE794CA402020180034400024100A6ABE4BD530812A1BF607A13206C02EB413ABDC9FEFF06DC3AFF2B0E0D7704C3A7CD47C699BDE69EC140CE329BACB407B9DB7D38812C9219FB406C92D55EED29 = = = Erzeugung der Schlüssel von Benutzer B = = = Benutzer B PrivateKey (Hex):3081D202010030819706092A864886F70D010301308189024100FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E170240678471B27A9CF44EE91A49C5147DB1A9AAF244F05A434D6486931D2D14271B9E35030B71FD73DA179069B32E2935630E1C2062354D0DA20A6C416E50BE794CA40202018004330231009A9F38517B49E23734EFC1954E038CCFA22040E432212815CECFA70E477A4EB30A675B799CF16778AD853A73A905380E Benutzer B PublicKey (Hex) :3081E030819706092A864886F70D010301308189024100FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E170240678471B27A9CF44EE91A49C5147DB1A9AAF244F05A434D6486931D2D14271B9E35030B71FD73DA179069B32E2935630E1C2062354D0DA20A6C416E50BE794CA402020180034400024100DF4F8DD38BA99DF6C0F296C419064938A831320A2193503FB6D27560D2E06C50C1D745C918EC4B06FD9A9CD6BA04EB03BB4B4598FF4613EE69A17A24BF565283 = = = Schlüssel bei Benutzer A = = = Benutzer A PrivateKey (Hex):3081D202010030819706092A864886F70D010301308189024100FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E170240678471B27A9CF44EE91A49C5147DB1A9AAF244F05A434D6486931D2D14271B9E35030B71FD73DA179069B32E2935630E1C2062354D0DA20A6C416E50BE794CA4020201800433023100A4C3B114545E32813460C9E89B38435FEA74BCFE9A05F9B743563C8928D9E3C30B658E5E6EE81C78EC56A125BD53C926 Benutzer B PublicKey (Hex) :3081E030819706092A864886F70D010301308189024100FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E170240678471B27A9CF44EE91A49C5147DB1A9AAF244F05A434D6486931D2D14271B9E35030B71FD73DA179069B32E2935630E1C2062354D0DA20A6C416E50BE794CA402020180034400024100DF4F8DD38BA99DF6C0F296C419064938A831320A2193503FB6D27560D2E06C50C1D745C918EC4B06FD9A9CD6BA04EB03BB4B4598FF4613EE69A17A24BF565283 = = = Schlüssel bei Benutzer B = = = Benutzer B PrivateKey (Hex):3081D202010030819706092A864886F70D010301308189024100FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E170240678471B27A9CF44EE91A49C5147DB1A9AAF244F05A434D6486931D2D14271B9E35030B71FD73DA179069B32E2935630E1C2062354D0DA20A6C416E50BE794CA40202018004330231009A9F38517B49E23734EFC1954E038CCFA22040E432212815CECFA70E477A4EB30A675B799CF16778AD853A73A905380E Benutzer A PublicKey (Hex) :3081E030819706092A864886F70D010301308189024100FCA682CE8E12CABA26EFCCF7110E526DB078B05EDECBCD1EB4A208F3AE1617AE01F35B91A47E6DF63413C5E12ED0899BCD132ACD50D99151BDC43EE737592E170240678471B27A9CF44EE91A49C5147DB1A9AAF244F05A434D6486931D2D14271B9E35030B71FD73DA179069B32E2935630E1C2062354D0DA20A6C416E50BE794CA402020180034400024100A6ABE4BD530812A1BF607A13206C02EB413ABDC9FEFF06DC3AFF2B0E0D7704C3A7CD47C699BDE69EC140CE329BACB407B9DB7D38812C9219FB406C92D55EED29 = = = Gemeinsame Schlüssel (SharedSecred) bei den Benutzern = = = Benutzer A SharedSecret (Hex):D99A87150BFA52D6440A8815276BC66AA910F73A57CFA107898AF8D61583F2636FE816A550CCD78F1EC0815FAB3C1939EF6429F813C114A32575735DB30D8421 Benutzer B SharedSecret (Hex):D99A87150BFA52D6440A8815276BC66AA910F73A57CFA107898AF8D61583F2636FE816A550CCD78F1EC0815FAB3C1939EF6429F813C114A32575735DB30D8421 Schlüssel-Länge des SharedSecretByte :64 Byte/512 Bit = = = Der gemeinsame Schlüssel wird per SHA-256 Hash auf eine Länge von 32 Byte gebracht = = = SharedSecretByte nach SHA-256Hash (Hex) :403311D5ED1AF5632C795E47AF4FA1FA0FD666237ED8C243671CB3FFC2BEA720 Schlüssel-Länge des SharedSecret32Byte :32 Byte/256 Bit |
Die Lizenz zum obigen Beispiel findet Ihr auf der eigenen Lizenz-Seite.
Letzte Aktualisierung: 18.01.2019