$configargs)); openssl_pkey_export_to_file($private_key,'privateclient.pem',$passphrase); } $details = openssl_pkey_get_details($private_key); $public_key = $details['dh']['pub_key']; file_put_contents("publicclient.pem", $details['key']); return array("private" => $private_key, "public" => $public_key); } // Returns: // ciphertext - The encrypted payload // iv - for randomness in ciphertext // tag - for verification function encrypt($plaintext, $aes_key) { // Encrypt payloads $cipher = "aes-256-gcm"; $ivlen = openssl_cipher_iv_length($cipher); $iv = openssl_random_pseudo_bytes($ivlen); $options = 0; $ciphertext = openssl_encrypt($plaintext, $cipher, $aes_key, $options=0, $iv, $tag); return array("ciphertext" => $ciphertext, "iv" => $iv, "tag" => $tag); } // Returns: function decrypt_server_output($server_output, $aes_key) { // Decrypt server output $cipher = "aes-256-gcm"; $parts = explode("\n", $server_output); $tag = hex2bin($parts[0]); $iv = hex2bin($parts[1]); $ciphertext = $parts[2]; return openssl_decrypt($ciphertext, $cipher, $aes_key, $options=0, $iv, $tag); } function send_to_server($url, $iv, $tag, $ciphertext, $public_key) { // Send to server $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_POST, 1); $query = array("hex_tag" => bin2hex($tag), "hex_iv" => bin2hex($iv), "ciphertext" => $ciphertext, "public_client" => bin2hex($public_key)); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($query)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $server_output = curl_exec($ch); curl_close ($ch); return $server_output; } if(isset($_POST['public_server']) && isset($_POST['url']) && isset($_POST['payload'])) { $keys = generate_keys(); $private_key = $keys['private']; $public_key = $keys['public']; // Calculate shared secret $remote_public_key = hex2bin(trim($_POST['public_server'])); $shared_secret = openssl_dh_compute_key($remote_public_key, $private_key); // XXX Not sure if it's safe to use the shared secret as the // AES key. Maybe a KDF is needed? $encrypted = encrypt($_POST['payload'], $shared_secret); // Send the encrypted payload to the server $server_output = send_to_server($_POST['url'], $encrypted['iv'], $encrypted['tag'], $encrypted['ciphertext'], $public_key); echo "
$server_output
"; // Decrypt the output from the server $new_plaintext = decrypt_server_output($server_output, $shared_secret); } ?>
Server url:

Payload/Command:

Server's public key (in hex):


OUTPUT: