2014-07-20 2 views
0

proc_open (또는 exec 또는 그 종류의 것)없이 jCryption 용 서버 측 PHP 처리 코드를 구현하려고합니다. 따라서 해당 함수를 완전히 비활성화 할 수 있지만 AES 암호화/암호 해독에 어려움을 겪고 있습니다. jCryption이 클라이언트 측에서 수행하는 작업과 일치하지만 OpenSSL 기능을 사용하여 작동하도록 RSA 구성 요소를 얻었습니다.proc_open (AES)이없는 PHP 서버 측 jCryption?

특히, 나는이 두 가지 기능의 proc_open 부품을 교체하는 코드를 작성하는 어려움에 봉착 : 나는 PHP의 Mcrypt 라이브러리 및 OpenSSL이 기능을 모두 시도했습니다

$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; 
} 

, 그리고 어느 쪽도 일치하는 것 같았다 (나는 '돈 내가 손에 쥐고있는 것을 가지고 있지만, 다시 시도하고 게시 할 수 있습니다.) openssl 명령을 일치시키는 방법에 대한 조언은 정말 감사하겠습니다.

답변

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