Hızlı bir düşünce deneyiyle başlayalım.
Alice, Bob ve Charlie tarafından kullanılan 3 bilgisayardan oluşan bir ağınız var. 3 katılımcının tümü mesaj gönderebilir, ancak ağa bağlı tüm diğer istemcilerin okuyabileceği şekilde. Katılımcılar arasındaki tek olası iletişim formu budur.
Alice teller aracılığıyla bir mesaj gönderirse, hem Bob hem de Charlie onu alır. Başka bir deyişle, Alice, Charlie de almadan Bob'a doğrudan mesaj gönderemez.
Ancak Alice, Bob'a gizli bir mesaj göndermek ister ve Charlie'nin bunu okuyabilmesini istemez.
Bu katı kurallarla imkansız görünüyor, değil mi? Bu sorunun 1976'da Whitfield Diffie ve Martin Hellman tarafından çözülmesinin güzel yanı.
Bu, gerçek dünyanın basitleştirilmiş bir sürümüdür, ancak şimdiye kadar var olan en büyük ağ üzerinden iletişim kurarken aynı sorunla karşılaşıyoruz.
Genellikle internete doğrudan bağlı değilsiniz, ancak Ethernet adı verilen yerel daha küçük bir ağın parçasısınız.
Bu daha küçük ağ kablolu veya kablosuz (Wi-Fi) olabilir, ancak temel konsept kalır. Ağ üzerinden bir sinyal gönderirseniz, bu sinyal aynı ağa bağlı diğer tüm istemciler tarafından okunabilir.
Kredi kartı bilgilerinizle bankanızın sunucusuna bir mesaj gönderdiğinizde, yerel ağdaki diğer tüm müşteriler, yönlendirici dahil mesajı alır. Daha sonra bunu bankanın gerçek sunucusuna iletecektir. Diğer tüm istemciler mesajı görmezden gelecektir.
Peki ya ağda gizli mesajlarınızı görmezden gelmeyen, bunun yerine okuyan kötü niyetli bir istemci varsa? Banka hesabınızda hala paranız olması nasıl mümkün olabilir?
Şifreleme
Bu noktada, mesajın Alice ve Bob için okunabilir olduğundan emin olmak için bir tür şifreleme kullanmamız gerektiği, ancak Charlie için tamamen anlamsız olduğu açıktır.
Bilgilerin şifrelenmesi, bir anahtar (örneğin bir dizge) alan ve şifreli metin adı verilen şifreli bir değeri geri veren bir şifreleme algoritması tarafından yapılır. Şifreli metin tamamen rastgele görünen bir dizedir.
Şifrelenmiş değerin (şifreli metin) şifresinin yalnızca orijinal anahtarla çözülebilmesi önemlidir. Buna simetrik anahtar algoritması denir, çünkü mesajın şifresini çözmek için şifreli olduğu gibi aynı anahtara ihtiyacınız vardır. Asimetrik anahtar algoritmaları da var, ancak şu anda onlara ihtiyacımız yok.
Bunu anlamayı kolaylaştırmak için, işte JavaScript'te uygulanan sahte bir şifreleme algoritması:
function encrypt(message, key) { return message.split("").map(character => { const characterAsciiCode = character.charCodeAt(0) return String.fromCharCode(characterAsciiCode+key.length) }).join(""); }
Bu işlevde, her bir karakteri, verilen anahtarın uzunluğuna göre başka bir karakterle eşledim.
Her karakterin ASCII kodu adı verilen bir tamsayı temsili vardır. ASCII tablosu adı verilen, koduyla birlikte tüm karakterleri içeren bir sözlük vardır. Bu tamsayıyı anahtarın uzunluğu kadar artırdık:
Şifreli metnin şifresini çözmek oldukça benzer. Ancak toplama yapmak yerine, şifreli metindeki her karakterden anahtar uzunluğunu çıkarırız, böylece orijinal mesajı geri alırız.
function decrypt(cipher, key) { return cipher.split("").map(character => { const characterAsciiCode = character.charCodeAt(0) return String.fromCharCode(characterAsciiCode-key.length) }).join(""); }
Son olarak işte kukla şifreleme iş başında:
const message = "Hi Bob, here is a confidential message!"; const key = "password"; const cipher = encrypt(message, key); console.log("Encrypted message:", cipher); // Encrypted message: Pq(Jwj4(pmzm(q{(i(kwvnqlmv|qit(um{{iom) const decryptedMessage = decrypt(cipher, key); console.log("Decrypted message:", decryptedMessage); // Decrypted message: Hi Bob, here is a confidential message!
Mesaja bir dereceye kadar şifreleme uyguladık, ancak bu algoritma simetrik anahtar şifreleme algoritmalarının nasıl davrandığına dair bir fikir edinmek için yalnızca gösterim amacıyla yararlıydı.
Bu uygulamada, köşe durumlarını ve parametre türlerini zayıf bir şekilde ele almanın yanı sıra birkaç sorun vardır.
Öncelikle her 8 karakter uzunluğundaki bir anahtar, "şifre" anahtarı ile şifrelenmiş mesajın şifresini çözebilir. Bir şifreleme algoritmasının, bir mesajın şifresini ancak mesajın şifrelendiği anahtarın aynısını verirsek çözebilmesini istiyoruz. Her anahtarla açılabilen bir kapı kilidi o kadar kullanışlı değildir.
İkincisi, mantık çok basittir - ASCII tablosundaki her karakter aynı miktarda kaydırılır, bu çok tahmin edilebilir. Anahtarsız mesajı bulmayı zorlaştırmak için daha karmaşık bir şeye ihtiyacımız var.
Üçüncüsü, minimum anahtar uzunluğu yoktur. Modern algoritmalar en az 128 bit uzunluğunda anahtarlarla (~ 16 karakter) çalışır. Bu, olası anahtarların sayısını ve bununla birlikte şifrelemenin güvenliğini önemli ölçüde artırır.
Son olarak, mesajı şifrelemek veya şifresini çözmek çok az zaman alır. Bu bir sorundur çünkü olası tüm anahtarları denemek ve şifrelenmiş mesajı kırmak çok fazla zaman almaz.
Bu anahtar uzunluğu ile el ele veriliyor: Bir saldırgan olarak anahtarı bulmak istersem algoritma güvenlidir, o zaman çok sayıda tuş kombinasyonunu denemem gerekir ve tek bir kombinasyonu denemek nispeten uzun zaman alır.
Tüm bu iddiaları ele alan, genellikle her durumda iyi bir hız ve güvenlik oranı bulmak için birlikte kullanılan çok çeşitli simetrik şifreleme algoritmaları vardır.
Daha popüler simetrik anahtar algoritmaları Twofish, Serpent, AES (Rijndael), Blowfish, CAST5, RC4, TDES ve IDEA'dır.
Genel olarak kriptografi hakkında daha fazla bilgi edinmek istiyorsanız bu konuşmaya göz atın.
Anahtar değişimi
Görünüşe göre orijinal sorun alanını küçültmüşüz. Şifreleme ile, bilgileri okumaya uygun olan ancak diğerleri tarafından okunamayan taraflar için anlamlı bir mesaj oluşturabiliriz.
Alice gizli bir mesaj yazmak istediğinde, bir anahtar seçer ve mesajını onunla şifreler ve şifreli metni kablolar aracılığıyla gönderir. Bob ve Charlie şifrelenmiş mesajı alacaktı, ancak hiçbiri Alice'in anahtarı olmadan bunu yorumlayamazdı.
Şimdi cevaplanması gereken tek soru, Alice ve Bob'un sadece ağ üzerinden iletişim kurarak ortak bir anahtarı nasıl bulabilecekleri ve Charlie'nin aynı anahtarı bulmasını nasıl engelleyebilecekleridir.
Alice anahtarını doğrudan kablolar yoluyla gönderirse, Charlie onu keser ve Alice'in tüm mesajlarının şifresini çözebilir. Yani bu bir çözüm değil. Bu, bilgisayar biliminde anahtar değişim problemi olarak adlandırılır.
Diffie – Hellman anahtar değişimi
Bu havalı algoritma, iki kişi arasında, iletişimi gözlemleyerek anahtarın görülemeyeceği bir şekilde paylaşılan bir anahtar oluşturmanın bir yolunu sağlar.
İlk adım olarak, tüm katılımcıların bildiği çok büyük bir asal sayı olduğunu söyleyeceğiz, bu halka açık bilgidir. Biz buna "p" veya modül diyoruz .
There is also another public number called "g" or base,which is less than p.
Don't worry about how these numbers are generated. For the sake of simplicity let's just say Alice picks a very big prime number (p) and a number which is considerably less than p. She then sends them through the wires without any encryption, so all participants will know these numbers.
Example: To understand this through an example, we'll use small numbers. Let's say p=23 and g=5.
As a second step both Alice (a) and Bob (b) will pick a secret number, which they won't tell anybody, it's just locally living in their computers.
Example:Let's say Alice picked 4 (a=4), and Bob picked 3 (b=3).
As a next step, they will do some math on their secret numbers, they will calculate:
- the base (g) in the power of their secret number,
- and take the calculated number's modulo to p.
- Call the result A (for Alice) and B (for Bob).
Modulo is a simple mathematical statement, and we use it to find the remainder after dividing one number by another. Here is an example: 23 mod 4 = 3, because 23/4 is 5 and 3 remains.
Maybe it's easier to see all of this in code:
// base const g = 5; // modulus const p = 23; // Alice's randomly picked number const a = 4; // Alice's calculated value const A = Math.pow(g, a)%p; // Do the same for Bob const b = 3; const B = Math.pow(g, b)%p; console.log("Alice's calculated value (A):", A); // Alice's calculated value (A): 4 console.log("Bob's calculated value (B):", B); // Bob's calculated value (B): 10
Now both Alice and Bob will send their calculated values (A, B) through the network, so all participants will know them.
As a last step Alice and Bob will take each other's calculated values and do the following:
- Alice will take Bob's calculated value (B) in the power of his secret number (a),
- and calculate this number's modulo to p and will call the result s (secret).
- Bob will do the same but with Alice's calculated value (A), and his secret number (b).
At this point, they successfully generated a common secret (s), even if it's hard to see right now. We will explore this in more detail in a second.
In code:
// Alice calculate the common secret const secretOfAlice = Math.pow(B, a)%p; console.log("Alice's calculated secret:", secretOfAlice); // Alice's calculated secret: 18 // Bob will calculate const secretOfBob = Math.pow(A, b)%p; console.log("Bob's calculated secret:", secretOfBob); // Bob's calculated secret: 18
As you can see both Alice and Bob got the number 18, which they can use as a key to encrypt messages. It seems magic at this point, but it's just some math.
Let's see why they got the same number by splitting up the calculations into elementary pieces:
In the last step, we used a modulo arithmetic identity and its distributive properties to simplify nested modulo statements.
So Alice and Bob have the same key, but let's see what Charlie saw from all of this. We know that p and g are public numbers, available for everyone.
We also know that Alice and Bob sent their calculated values (A, B) through the network, so that can be also caught by Charlie.
Charlie knows almost all parameters of this equation, just a and b remain hidden. To stay with the example, if he knows that A is 4 and p is 23, g to the power of a can be 4, 27, 50, 73, ... and infinite other numbers which result in 4 in the modulo space.
He also knows that only the subset of these numbers are possible options because not all numbers are an exponent of 5 (g), but this is still an infinite number of options to try.
This doesn't seem too secure with small numbers. But at the beginning I said that p is a really large number, often 2000 or 4000 bits long. This makes it almost impossible to guess the value of a or b in the real world.
The common key Alice and Bob both possess only can be generated by knowing a or b, besides the information that traveled through the network.
If you're more visual, here is a great diagram shows this whole process by mixing buckets of paint instead of numbers.
Here p and g shared constants represented by the yellow "Common paint". Secret numbers of Alice and Bob (a, b) is "Secret colours", and "Common secret" is what we called s.
This is a great analogy because it's representing the irreversibility of the modulo operation. As mixed paints can't be unmixed to their original components, the result of a modulo operation can't be reversed.
Summary
Now the original problem can be solved by encrypting messages using a shared key, which was exchanged with the Diffie-Hellman algorithm.
With this Alice and Bob can communicate securely, and Charlie cannot read their messages even if he is part of the same network.
Thanks for reading this far! I hope you got some value from this post and understood some parts of this interesting communication flow.
If it was hard to follow the math of this explanation, here is a great video to help you understand the algorithm without math, from a higher level.
If you liked this post, you may want to follow me on Twitter to find some more exciting resources about programming and software development.