0

I have used the encrypt and decrypt functions from this answer to implement message passing using Three-pass protocol with the Blowfish cipher.

And I tried using commutative ecryption/decryption. That is,

$tmp = encrypt($input, $key1);
$tmp = encrypt($tmp, $key2);
$tmp = decrypt($tmp, $key1);
$dec2 = decrypt($tmp, $key2);

But it does not work. I used a single key instead of 2 different keys and it works(has to!).

So there's no problem in the way I'm using these functions, but I simply cant get it working with two keys.

Am I doing something wrong? Is this not possible, or is there another way?

Or, is there a way I could do it in Java?

Edit: For those who don't understand the procedure, Three-pass protocol is a way to send encrypted messages without having to send the keys. So the procedure is

  1. Sender encrypts with key1 and sends

  2. Receiver encrypts with key2 and sends back

  3. Sender decrypts with key1 and sends back

  4. Receiver decrypts with key2 to get the original message

You can see that keys are not exchanged, but the message is sent only in encrypted form. That's the whole point.

Xpleria
  • 5,472
  • 5
  • 52
  • 66

2 Answers2

2

Using the XOR function provided by a user in this thread

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>';

You get this

$itemwewanttoshare: hello darling
$packet1: 1W6 TS>
$packet2: hNwRVtq|ing
$packet3: 1=&M"TS>
$packet4: hello darling

EDIT addition

I base64'd the key for simplicity. Use a key with more variation and the results will be more complicated.
use mcrypt_create_iv(40) to create your keys and you end up with something like this

$senderkey='<²#H[Ô\´(µÑ/KÀ®"熺¥ç|Ëvr%O›eu$nºbe';
$receiverkey='Øh\5PÀKO[ù¬òZH‰•ʬh/¥nëk¾ðéíPÄ"Uü';

which will change the output to

$itemwewanttoshare: hello darling
$packet1: T§ÞO'{§õ.®ÝF¥
$packet2: —?¶+¦6®½– þ
$packet3: «ý0Zpe¢ò"!<
$packet4: hello darling

Edit 2

Duskwuff brings up a good point. $itemwewanttoshare should be created by the system(program) and not be a user created item. This method could be used to establish a shared encryption key that both send and receiver could use to encrypt further communication. Sender would generate the key, and then that would be the itemwewanttoshare , thus allowing both sides to know the encryption key without passing it directly.

Community
  • 1
  • 1
greg_diesel
  • 2,955
  • 1
  • 15
  • 24
  • Does look promising. But the question is how safe is it? If encryption/decryption was so easy then why so complicated ciphering techniques? – Xpleria Feb 03 '15 at 22:50
  • Completely unsafe — it's trivial to recover the key for such a scheme using a known-plaintext attack. **Do not use this code.** –  Feb 03 '15 at 23:44
  • 1
    @duskwuff In theory the plaintext is the actual encryption key that you would end up using for the transaction. You just want a way to get both sides knowing the same encryption key without passing it directly. So the 'end user' would not be able to submit their own plaintext key to be able to do your attack. The questioner references the Wikipedia page that describes the possibility of a MITM attack so I assume he is aware of that vector. – greg_diesel Feb 04 '15 at 02:04
0

The WikiPedia article gives a hint at what can be used:

Sometimes the encryption function and decryption function are the same.

This is the case for stream ciphers like RC4 which create a long stream of pseudo-random data and simply XOR it with the data. XOR is commutative and it is easy to implement it in 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;

Block ciphers in CTR mode are also useable in the same way. This is an example of AES in CTR mode:

$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;
Artjom B.
  • 61,146
  • 24
  • 125
  • 222