Diffie-Hellmann Keyechange

Diffie und Hellmann haben das erste echte Schlüsselaustausch Protokoll entwickelt, welches die Idee von privaten und öffentlichen Schlüssen beinhaltet. Allerdings ist es kein Verschlüsselungsalgorithmus, sondern lediglich das Handshakeprotokoll. Außerdem ist wichtig zu erwähnen, dass, obwohl es private Schlüssel nutzt, der Anwendungszweck der Schlüsselaustausch für symetrische Verschlüsselung ist. Daher wird er teilweise auch heute noch genutzt, denn symetrische Verschlüsselung ist meist sicherer, als die asymetrische mit einem mathematisch voneinander abhängigem Schlüsselpaar.

Implementierung

Ablauf

Bei der Gesamtheit des Schlüsselaustausches wird davon ausgegangen, dass jede Kommunikation zwischen A und B von C mitgelesen werden kann, da der sichere Kanal, der mit dem Hanshake hergestellt werden soll ja noch nicht besteht.

Beide Partner, hier A und B, einigen sich auf eine Gemeinsame Basis B und eine Primzahl p. Außerdem generiert jeder der beiden den geheimen Schlüssel (a oder b), den er mit niemandem teilt. Dann rechnet jeder $$mod(B^{geheim}, p)$$ und teilt das dann mit seinem Partner. Auch diese Zahlen kann der Angreifer abhören. Um dann den gemeinsamen (geheimen) Schlüssel zu bekommen, der für die symetrische Verschlüsselung benötigt wird, rechnet jeder $$mod(ZahlDesAnderen^{geheim}, p)$$ Die Magie dabei ist, dass dabei für beide die gleiche Zahl raus kommt. Dieser Schlüsselaustausch ist sicher, da wenn der Angreifer die letzte Operation ausführt, was er kann, denn er hat alle Parameter (außer die Geheime Zahl, aber die kann er sich ja auch generieren) die dafür notwendig sind. Den Schlüssel, den C dann generieren kann wäre valide, wenn einer der beiden anderen die Zahl des Angreifers aus der ersten Rechenoperation genommen hätte. Aber wenn das nicht der Fall ist, dann kann der Angreifer den gemeinsamen Schlüssel nicht bekommen, obwohl er alle öffentlichen Parameter hat und die beiden Partner den geheimen Schlüssel des anderen nicht kennen.

Schaubild

ein Schaubild, welches ich selbst gemacht habe

das Schaubild von Wikipedia

Beispielcode

main.rs

// Abfrage, ob ein String nur numerisch ist
use keyexchange::IsNumeric;
// Implementation großer Zahlen, die das normale i128-Maß übersteigen
use num_bigint::BigInt;
// Zufällige Zahlen
use rand::prelude::*;
// sha256 Hashing algorithmus
// ist für den Schlüsselaustausch nicht notwendig
use sha2::Sha256;
use sha2::Digest;
// kann eine beliebige Zahl sein, so lange
// sie für beide PArtner gleich ist
const EINS: i64 = 3125;
// kann eine beliebige Primzahl sein, so lange
// sie für beide PArtner gleich ist
const PRIME: i64 = 1000000007;
fn main() {
   // zufällige Zahl
   let rng = rand::thread_rng().gen_range(1000..9000);
   let prime = PRIME;
   // "übersetze" die i64 Zahl in eine Zahl, die groß werden kann
   let base = BigInt::from(EINS);
   // exponiere die Basis
   let power = base.pow(rng);
   // bestimme den öffentlichen Schlüssel
   let y = power % prime as i128;
   // gebe ihn aus
   println!("Your public key is: \n{y}");
   println!("Please enter the public key of your partner");
   loop {
      // lese die Nutzereingabe des öffentlichen Schlüssels des Partners
      let i = keyexchange::geti();
      // überprüfe, ob die Eingabe numerisch ist
      if i.is_numeric() {
         // mache die eingabe zu einer Zahl
         let x: i64 = i.parse().unwrap();
         // Übersetze die Eingabe
         let secretbase = BigInt::from(x);
         // potenziere die Eingabe
         let secretpower = secretbase.pow(rng);
         // nimm den Modulus davon
         let secret = secretpower % prime;
         // übersetze es zurück in ein Format, welches weiter genutzt werden kann
         // (die Zahl ist dank des Modulo nicht mehr so groß)
         let num = secret.to_signed_bytes_be();
         // hashe sie, um sie zu verlängern und weitere Zeichen eintzufügen
         // (um den Wert als Passwort geeigneter zu machen, für den Schlüsselaustausch nicht notwendig)
         let mut hasher = Sha256::new();
         hasher.update(num);
         let result = hasher.finalize();
         // gebe den gemeinsamen Schlüssel aus
         println!("The shared secret key is:\n{:x}", result);
         break;
      } else {
         println!("can only be numeric");
      }
   }
}

Mathe

$$ (B^a \space mod \space p)^b \space mod \space p = (B^b \space mod \space p)^a \space mod \space p $$


52posts

Dieser Beitrag ist Teil meines Plans, in 2023 jede Woche einen Post zu erstellen, mit Dingen, die ich gelernt habe. (Das sind dann 52 Posts).

#52posts