0

我正在尝试在没有 proc_open (或 exec 或任何此类)的情况下为 jCryption 实现服务器端 PHP 处理代码,以便我可以完全禁用这些功能,但我很难获得 AES 加密/解密以匹配什么jCryption 是在客户端做的,虽然我已经让 RSA 组件使用 OpenSSL 函数工作。

具体来说,我很难编写代码来替换这两个函数的 proc_open 部分:

$descriptorSpec = array(
    0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
    1 => array("pipe", "w")  // stdout is a pipe that the child will write to
);

function handshake($encryptedAESKey) {
    // Decrypt the AES key with the RSA key 
    $encryptedAESKey = base64_decode($encryptedAESKey);
    $privKey = unserialize($_SESSION['priv_key']);
    openssl_private_decrypt($encryptedAESKey, $key, $privKey);
    // Store the AES key in the session
    $_SESSION["AES_Key"] = $key;
    // Generate the challenge to be sent back to the client
    $challenge = NULL;
    $cmd = sprintf("openssl enc -aes-256-cbc -pass pass:" . escapeshellarg($key) . " -a -e");
    $process = proc_open($cmd, $descriptorSpec, $pipes);
    if (is_resource($process)) {
        fwrite($pipes[0], $key);
        fclose($pipes[0]);

        // we have to trim all newlines and whitespaces by ourself
        $challenge = trim(str_replace("\n", "", stream_get_contents($pipes[1])));
        fclose($pipes[1]);
        proc_close($process);
    }

    return $challenge;
}

// Once the handshake is done, we can receive encrypted data and decrypt it.
function decrypt($encryptedData) {
    $key = $_SESSION["AES_Key"];

    // Decrypt the client's request and send it to the clients(uncrypted)
    $cmd = sprintf("openssl enc -aes-256-cbc -pass pass:" . escapeshellarg($key) . " -d");
    $process = proc_open($cmd, $descriptorSpec, $pipes);
    $decryptedData = NULL;
    if (is_resource($process)) {
        fwrite($pipes[0], base64_decode($encryptedData));
        fclose($pipes[0]);

        $decryptedData = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        proc_close($process);
    }

    return $decryptedData;
}

我已经尝试过 PHP 的 MCrypt 和 OpenSSL 函数,但似乎都不匹配(我手头没有我尝试过的东西,但我可以再试一次并发布它)。任何有关如何匹配 openssl 命令的建议将不胜感激。

4

1 回答 1

1

参考: http: //php.net/manual/en/function.openssl-decrypt.php#107210

<?php 

class sqAES {

  /**
   * decrypt AES 256
   *
   * @param string $password
   * @param data $edata
   * @return dencrypted data
   */
  public static function decrypt($password, $edata) {
    $data = base64_decode($edata);
    $salt = substr($data, 8, 8);
    $ct = substr($data, 16);
    /**
     * From https://github.com/mdp/gibberish-aes
     *
     * Number of rounds depends on the size of the AES in use
     * 3 rounds for 256
     *        2 rounds for the key, 1 for the IV
     * 2 rounds for 128
     *        1 round for the key, 1 round for the IV
     * 3 rounds for 192 since it's not evenly divided by 128 bits
     */
    $rounds = 3;
    $data00 = $password.$salt;
    $md5_hash = array();
    $md5_hash[0] = md5($data00, true);
    $result = $md5_hash[0];
    for ($i = 1; $i < $rounds; $i++) {
      $md5_hash[$i] = md5($md5_hash[$i - 1].$data00, true);
        $result .= $md5_hash[$i];
    }
    $key = substr($result, 0, 32);
    $iv  = substr($result, 32,16);

      return openssl_decrypt($ct, 'aes-256-cbc', $key, true, $iv);
  }

  /**
   * crypt AES 256
   *
   * @param string $password
   * @param data $data
   * @return base64 encrypted data
   */
  public static function crypt($password, $data) {
    // Set a random salt
    $salt = openssl_random_pseudo_bytes(8);

    $salted = '';
    $dx = '';
    // Salt the key(32) and iv(16) = 48
    while (strlen($salted) < 48) {
      $dx = md5($dx.$password.$salt, true);
      $salted .= $dx;
    }

    $key = substr($salted, 0, 32);
    $iv  = substr($salted, 32,16);

    $encrypted_data = openssl_encrypt($data, 'aes-256-cbc', $key, true, $iv);
    return base64_encode('Salted__' . $salt . $encrypted_data);
  }

}

?>

您的新代码:

require './sqAES.php';

function handshake($encryptedAESKey) {
    // Decrypt the AES key with the RSA key 
    $encryptedAESKey = base64_decode($encryptedAESKey);
    $privKey = unserialize($_SESSION['priv_key']);
    openssl_private_decrypt($encryptedAESKey, $key, $privKey);
    // Store the AES key in the session
    $_SESSION["AES_Key"] = $key;
    // Generate the challenge to be sent back to the client
    $challenge = trim(str_replace("\n", "", sqAES::crypt($key, $key)));

    return $challenge;
}

// Once the handshake is done, we can receive encrypted data and decrypt it.
function decrypt($encryptedData) {
    $key = $_SESSION["AES_Key"];

    // Decrypt the client's request and send it to the clients(uncrypted)
    $decryptedData = sqAES::decrypt($key, $encryptedData);

    return $decryptedData;
}
于 2014-09-12T19:24:43.673 回答