3层Diffie Hellman





5.00/5 (2投票s)
在不安全的网络连接上传输三个用户的共享密钥。
引言
本文的目标是为使用 Diffie-Hellman 算法在非安全网络连接上进行三方(或更多方)会议提供一个框架,以保证其安全性。
注意:要运行该项目,您必须先启动服务器,然后启动三个客户端。
背景
Diffie-Hellman 算法使用模算术和素数。
它使用以下组件
- 素数 - 只能被自身和数字 1 除且没有余数的整数。(通常是一个非常大的整数,但我使用了一个较小的整数,以便更容易调试。)
- 本原根 - 小于素数的整数。它是素数生成的域的创建者。
示例:对于素数 7,本原根可以是 3,但不能是 2,因为
3^0 = 1 => 1 mod 7 = 1 2^0 = 1 => 1 mod 7 = 1 3^1 = 3 => 3 mod 7 = 3 2^1 = 2 => 2 mod 7 = 2 3^2 = 9 => 9 mod 7 = 2 2^2 = 4 => 4 mod 7 = 4 3^3 = 27 => 27 mod 7 = 6 2^3 = 8 => 8 mod 7 = 1 3^4 = 81 => 81 mod 7 = 4 2^4 = 16 => 16 mod 7 = 2 3^5 = 243 => 243 mod 7 = 5 2^5 = 32 => 32 mod 7 = 4
- 幂数 - 本原根的随机乘积(我们每次交互都进行模运算,因此数字永远不会大于 uint64,否则计算机将很快崩溃)。
工作原理
三个用户就一个素数和一个本原根达成一致(在我的实现中,服务器选择),并且每个用户选择自己的幂数(他不会共享此数字)。然后每个用户将本原根乘以幂数,并将余数发送给其他两个用户。
服务器发送素数及其本原根。
每个用户发送本原根与其秘密幂数模素数的结果。
然后用户将其他用户的结果乘以他们的秘密幂数,并获得共享密钥。
注意:不需要服务器,它的目的是将 IP 发送给客户端,因为它们都在同一台机器上运行。在不同的机器上,他们可以直接通过彼此的 IP 地址连接。
现在所有用户都有了共享密钥,他们可以加密他们的消息。只有这三个人才能拥有解密它的密钥。共享密钥有很多可能的结果,以至于无法猜测。恶意方不能仅仅通过监听所有连接来获得密钥。他必须知道其中一个用户的能力才能知道共享密钥,但这个数字永远不会发送给其他用户,所以他无法知道。
例如

我们获得了共享密钥 4758,用户 A 想要将其银行 PIN 码发送给用户 B 和 C。假设 A 的 PIN 码是 1234(或二进制 10011010010),A 使用共享密钥 4758(二进制 1001010010110)进行异或运算并发送结果。拥有共享密钥的 B 和 C 各自对 A 发送的数字 5700(二进制 1011001000100)进行异或运算,现在 B 和 C 拥有 A 的 PIN 码。
超过 3 个用户?
对于想要共享秘密的两个用户,您可以使用原始算法。但是,如果 4 个或 5 个或 100 万个用户想要共享一个秘密,则要求每个用户都与其他每个用户连接。这将创建一个完整的图。如果其中一个节点不安全,则其余节点也不安全(链条的强度取决于其最薄弱的环节)。

Using the Code
计算要发送给其他用户的数字
private void calaulate() //calculate the number this user
//sends A = [(primitive-root)^power (mod prime)]
{
A = (UInt64)((primitiveRoot * primitiveRoot) % prime);
for (int i = 0; i < power - 2; i++)
A = (UInt64)((A * primitiveRoot) % prime);
}
在以下第一个代码块中,如果您希望与第一个用户通信,则需要确保在第二个代码块中建立共享密钥后才能使用共享密钥加密消息。因此,您必须等到第二个块完成计算后才能安全地进行通信。
public void next(object rw)
{
try
{
readWrite RW = rw as readWrite;
BinaryReader reader = RW.Reader;
BinaryWriter writer = RW.Writer;
writer.Write(A);//write to left user my result
C = reader.ReadUInt16();
//read left users result
/*
* make sure that the shared secret is not 0 and
* you can communicate with left side here
* choose whatever protocol of encryption uses a shared key
*/
} catch (Exception)
{
MessageBox.Show("an error occurred and needs to exit");
this.Close();
}
}
public void prev(object rw)
{
try
{
readWrite RW = rw as readWrite;
BinaryReader reader = RW.Reader;
BinaryWriter writer = RW.Writer;
B = reader.ReadUInt16();//read right user result
writer.Write(A);//write to right user my result
Thread.Sleep(3500);//wait the other side read (gets C)
#region calculate sherd secret
sherdSecret = (UInt64)(B * C);
insertToTextBox("B: " + B.ToString() +
" C: " + C.ToString()); //display left and right calculation
//(you should remove that)
sherdSecret = (UInt64)(sherdSecret % prime);
insertToTextBox("1: " + ((B * C) % prime).ToString()); //prints
//interaction
for (int i = 0; i < power - 1; i++)
{
sherdSecret = (UInt64)((sherdSecret * primitiveRoot) % prime);
insertToTextBox((i + 2).ToString() + ": " +
sherdSecret.ToString());//prints interaction
}
#endregion calculate sherd secret
insertToTextBox("sherad secret key: " +
sherdSecret.ToString());//shows the sherd key(remove this line)
/*
* your code to communicate with right side here
* no need to wait
* choose whatever protocol of encryption uses a shared key
*/
}
catch (Exception)
{
MessageBox.Show("an error occurred and needs to exit");
this.Close();
}
}
关注点
请注意,所有用户都在同一台机器上进行通信,因此每个用户都有自己的 IP 和端口,服务器按照他们的连接顺序分配给他们。最好在您开始与他人通信时根本不使用服务器,以最大限度地降低失去网络可信度的风险。