有没有办法在 php 中使用交换加密?
Is there a way to use commutative encryption in php?
我已经将此 answer to implement message passing using Three-pass protocol 中的 encrypt
和 decrypt
函数与 Blowfish 密码一起使用。
我尝试使用交换 ecryption/decryption。也就是说,
$tmp = encrypt($input, $key1);
$tmp = encrypt($tmp, $key2);
$tmp = decrypt($tmp, $key1);
$dec2 = decrypt($tmp, $key2);
但是没有用。我使用了一个键而不是 2 个不同的键并且它有效(必须!)。
所以我使用这些功能的方式没有问题,但我就是不能用两个键来工作。
我是不是做错了什么?这不可以,还是有别的办法?
或者,我可以在 Java 中做到吗?
编辑: 对于那些不了解该过程的人,三通协议是一种无需发送密钥即可发送加密消息的方法。所以程序是
发件人用key1加密后发送
接收端用key2加密后发回
发件人用key1解密并发回
接收方用key2解密得到消息原件
您可以看到没有交换密钥,但消息仅以加密形式发送。这就是重点。
使用本帖用户提供的异或函数
Encrypt/decrypt with XOR in PHP
function xor_this($string,$key) {
// Our plaintext/ciphertext
$text =$string;
// Our output text
$outText = '';
// Iterate through each character
for($i=0;$i<strlen($text);)
{
for($j=0;($j<strlen($key) && $i<strlen($text));$j++,$i++)
{
$outText .= $text{$i} ^ $key{$j};
//echo 'i='.$i.', '.'j='.$j.', '.$outText{$i}.'<br />'; //for debugging
}
}
return $outText;
}
//The sender chooses a private encryption key s and a corresponding decryption key t. The sender encrypts the message m with the key s and sends the encrypted message E(s,m) to the receiver.
//The receiver chooses a private encryption key r and a corresponding decryption key q and super-encrypts the first message E(s,m) with the key r and sends the doubly encrypted message E(r,E(s,m)) back to the sender.
//The sender decrypts the second message with the key t. Because of the commutativity property described above D(t,E(r,E(s,m)))=E(r,m) which is the message encrypted with only the receiver's private key. The sender sends this to the receiver.
$senderkey=base64_encode('chicken');
$receiverkey=base64_encode('ardvark');
$itemwewanttoshare='hello darling';
echo'$itemwewanttoshare: '.$itemwewanttoshare.'<BR>';
$packet1=xor_this($itemwewanttoshare,$senderkey);
echo'$packet1: '.$packet1.'<BR>';
$packet2=xor_this($packet1,$receiverkey);
echo'$packet2: '.$packet2.'<BR>';
$packet3=xor_this($packet2,$senderkey);
echo'$packet3: '.$packet3.'<BR>';
$packet4=xor_this($packet3,$receiverkey);
echo'$packet4: '.$packet4.'<BR>';
你明白了
$itemwewanttoshare: hello darling
$packet1: 1W6 TS>
$packet2: hNwRVtq|ing
$packet3: 1=&M"TS>
$packet4: hello darling
编辑添加
为了简单起见,我对密钥进行了 base64 编码。使用变化更多的密钥,结果会更复杂。
使用 mcrypt_create_iv(40)
来创建你的密钥,你最终会得到这样的东西
$senderkey='<²#H[Ô\´(µÑ/KÀ®"熺¥ç|Ëvr%O›eu$nºbe';
$receiverkey='ØhPÀKO[ù¬òZH‰•Ê¬h/¥nëk¾ðéíPÄ"Uü';
这会将输出更改为
$itemwewanttoshare: hello darling
$packet1: T§ÞO'{§õ.®ÝF¥
$packet2: —?¶+¦6®½– þ
$packet3: «ý0Zpe¢ò"!<
$packet4: hello darling
编辑 2
Duskwuff 提出了一个很好的观点。 $itemwewanttoshare
应该由系统(程序)创建,而不是用户创建的项目。此方法可用于建立共享加密密钥,发送方和接收方都可以使用该密钥来加密进一步的通信。发件人将生成密钥,然后这将是 itemwewanttoshare ,从而允许双方知道加密密钥而无需直接传递它。
WikiPedia article给出了可以使用的提示:
Sometimes the encryption function and decryption function are the same.
像 RC4 这样的流密码就是这种情况,它创建一长串伪随机数据并简单地将其与数据进行异或运算。 XOR 是可交换的,很容易在 PHP:
中实现
$cipher = "arcfour";
$k1 = mcrypt_create_iv(256); // random
$k2 = mcrypt_create_iv(256); // random
$data = "some string";
$mode = "stream";
echo "key size: ".mcrypt_get_key_size($cipher, $mode)."\n"; // 256
echo "iv size: ".mcrypt_get_iv_size($cipher, $mode)."\n"; // 0
// Three-pass protocol property: D(d,E(k,E(e,m))) = E(k,m)
$c1 = mcrypt_encrypt($cipher, $k1, $data , $mode, "");
$c2 = mcrypt_encrypt($cipher, $k2, $data , $mode, "");
$c2 = mcrypt_encrypt($cipher, $k1, $c2 , $mode, "");
$c2 = mcrypt_decrypt($cipher, $k2, $c2 , $mode, "");
echo $c1 == $c2;
CTR mode 中的块密码也可以以相同的方式使用。这是 CTR 模式下的 AES 示例:
$cipher = "rijndael-128";
$k1 = mcrypt_create_iv(16); // random
$k2 = mcrypt_create_iv(16); // random
$iv1 = mcrypt_create_iv(16); // random
$iv2 = mcrypt_create_iv(16); // random
$data = "some string";
$mode = "ctr";
echo "key size: ".mcrypt_get_key_size($cipher, $mode)."\n";
echo "iv size: ".mcrypt_get_iv_size($cipher, $mode)."\n";
$c1 = mcrypt_encrypt($cipher, $k1, $data , $mode, $iv1);
$c2 = mcrypt_encrypt($cipher, $k2, $data , $mode, $iv2);
$c2 = mcrypt_encrypt($cipher, $k1, $c2 , $mode, $iv1);
$c2 = mcrypt_decrypt($cipher, $k2, $c2 , $mode, $iv2);
echo $c1 == $c2;
我已经将此 answer to implement message passing using Three-pass protocol 中的 encrypt
和 decrypt
函数与 Blowfish 密码一起使用。
我尝试使用交换 ecryption/decryption。也就是说,
$tmp = encrypt($input, $key1);
$tmp = encrypt($tmp, $key2);
$tmp = decrypt($tmp, $key1);
$dec2 = decrypt($tmp, $key2);
但是没有用。我使用了一个键而不是 2 个不同的键并且它有效(必须!)。
所以我使用这些功能的方式没有问题,但我就是不能用两个键来工作。
我是不是做错了什么?这不可以,还是有别的办法?
或者,我可以在 Java 中做到吗?
编辑: 对于那些不了解该过程的人,三通协议是一种无需发送密钥即可发送加密消息的方法。所以程序是
发件人用key1加密后发送
接收端用key2加密后发回
发件人用key1解密并发回
接收方用key2解密得到消息原件
您可以看到没有交换密钥,但消息仅以加密形式发送。这就是重点。
使用本帖用户提供的异或函数
Encrypt/decrypt with XOR in PHP
function xor_this($string,$key) {
// Our plaintext/ciphertext
$text =$string;
// Our output text
$outText = '';
// Iterate through each character
for($i=0;$i<strlen($text);)
{
for($j=0;($j<strlen($key) && $i<strlen($text));$j++,$i++)
{
$outText .= $text{$i} ^ $key{$j};
//echo 'i='.$i.', '.'j='.$j.', '.$outText{$i}.'<br />'; //for debugging
}
}
return $outText;
}
//The sender chooses a private encryption key s and a corresponding decryption key t. The sender encrypts the message m with the key s and sends the encrypted message E(s,m) to the receiver.
//The receiver chooses a private encryption key r and a corresponding decryption key q and super-encrypts the first message E(s,m) with the key r and sends the doubly encrypted message E(r,E(s,m)) back to the sender.
//The sender decrypts the second message with the key t. Because of the commutativity property described above D(t,E(r,E(s,m)))=E(r,m) which is the message encrypted with only the receiver's private key. The sender sends this to the receiver.
$senderkey=base64_encode('chicken');
$receiverkey=base64_encode('ardvark');
$itemwewanttoshare='hello darling';
echo'$itemwewanttoshare: '.$itemwewanttoshare.'<BR>';
$packet1=xor_this($itemwewanttoshare,$senderkey);
echo'$packet1: '.$packet1.'<BR>';
$packet2=xor_this($packet1,$receiverkey);
echo'$packet2: '.$packet2.'<BR>';
$packet3=xor_this($packet2,$senderkey);
echo'$packet3: '.$packet3.'<BR>';
$packet4=xor_this($packet3,$receiverkey);
echo'$packet4: '.$packet4.'<BR>';
你明白了
$itemwewanttoshare: hello darling
$packet1: 1W6 TS>
$packet2: hNwRVtq|ing
$packet3: 1=&M"TS>
$packet4: hello darling
编辑添加
为了简单起见,我对密钥进行了 base64 编码。使用变化更多的密钥,结果会更复杂。
使用 mcrypt_create_iv(40)
来创建你的密钥,你最终会得到这样的东西
$senderkey='<²#H[Ô\´(µÑ/KÀ®"熺¥ç|Ëvr%O›eu$nºbe';
$receiverkey='ØhPÀKO[ù¬òZH‰•Ê¬h/¥nëk¾ðéíPÄ"Uü';
这会将输出更改为
$itemwewanttoshare: hello darling
$packet1: T§ÞO'{§õ.®ÝF¥
$packet2: —?¶+¦6®½– þ
$packet3: «ý0Zpe¢ò"!<
$packet4: hello darling
编辑 2
Duskwuff 提出了一个很好的观点。 $itemwewanttoshare
应该由系统(程序)创建,而不是用户创建的项目。此方法可用于建立共享加密密钥,发送方和接收方都可以使用该密钥来加密进一步的通信。发件人将生成密钥,然后这将是 itemwewanttoshare ,从而允许双方知道加密密钥而无需直接传递它。
WikiPedia article给出了可以使用的提示:
Sometimes the encryption function and decryption function are the same.
像 RC4 这样的流密码就是这种情况,它创建一长串伪随机数据并简单地将其与数据进行异或运算。 XOR 是可交换的,很容易在 PHP:
中实现$cipher = "arcfour";
$k1 = mcrypt_create_iv(256); // random
$k2 = mcrypt_create_iv(256); // random
$data = "some string";
$mode = "stream";
echo "key size: ".mcrypt_get_key_size($cipher, $mode)."\n"; // 256
echo "iv size: ".mcrypt_get_iv_size($cipher, $mode)."\n"; // 0
// Three-pass protocol property: D(d,E(k,E(e,m))) = E(k,m)
$c1 = mcrypt_encrypt($cipher, $k1, $data , $mode, "");
$c2 = mcrypt_encrypt($cipher, $k2, $data , $mode, "");
$c2 = mcrypt_encrypt($cipher, $k1, $c2 , $mode, "");
$c2 = mcrypt_decrypt($cipher, $k2, $c2 , $mode, "");
echo $c1 == $c2;
CTR mode 中的块密码也可以以相同的方式使用。这是 CTR 模式下的 AES 示例:
$cipher = "rijndael-128";
$k1 = mcrypt_create_iv(16); // random
$k2 = mcrypt_create_iv(16); // random
$iv1 = mcrypt_create_iv(16); // random
$iv2 = mcrypt_create_iv(16); // random
$data = "some string";
$mode = "ctr";
echo "key size: ".mcrypt_get_key_size($cipher, $mode)."\n";
echo "iv size: ".mcrypt_get_iv_size($cipher, $mode)."\n";
$c1 = mcrypt_encrypt($cipher, $k1, $data , $mode, $iv1);
$c2 = mcrypt_encrypt($cipher, $k2, $data , $mode, $iv2);
$c2 = mcrypt_encrypt($cipher, $k1, $c2 , $mode, $iv1);
$c2 = mcrypt_decrypt($cipher, $k2, $c2 , $mode, $iv2);
echo $c1 == $c2;