2013-05-06 4 views
0

나는 iOS 응용 프로그램에서 RNCryptor을 사용하고 있습니다. 응용 프로그램의 일부 문제로 인해, 나는 PHP 5.4를 실행하는 데이터 서버 측의 일부를 해독해야합니다. RNCryptor 패키지에는 PHP 코드가 포함되어 있지만 RNCryptor의 2.x 분기에서만 작동합니다. 내 데이터는 1.x 지점으로 암호화되었습니다. 안타깝게도 RNCryptor 2.x는 1.x와 역 호환되지 않습니다.PHP를 사용하여 RNCryptor 1.x의 출력을 암호 해독

내가 알 수있는 한,이 분기의 유일한 차이점은 1.x는 AES CTR 모드를 사용하여 텍스트를 암호화하는 반면 2.x는 이제 AES CBC를 사용한다는 것입니다. 그러나 CTR을 사용하기 위해 PHP 코드를 적용하는 방법을 알아 내지 못했습니다. 1.x와 2.x 사이에 다른 변경 사항이 있는지 확실하지 않습니다. 나는 1.x에 관한 유용한 정보가 거의 없다.

다음은 2.X 라인에서 데이터를 해독하기위한 RNCryptor 코드입니다 :

/** 
* @param string $b64_data Data encrypted by RNCryptor 2.x 
* @return string|false Decrypted plaintext string, or false if decryption fails 
*/ 
function decrypt_data($b64_data) { 
    global $gPassword; // the password string that was used to encrypt the data 

    // kRNCryptorAES256Settings 
    $algorithm = MCRYPT_RIJNDAEL_128; 
    $key_size = 32; 
    $mode = MCRYPT_MODE_CBC; 
    $pbkdf2_iterations = 10000; 
    $pbkdf2_prf = 'sha1'; 
    $hmac_algorithm = 'sha256'; 

    // back to binary    
    $bin_data = base64_decode($b64_data); 
    // extract salt 
    $salt = substr($bin_data, 2, 8); 
    // extract HMAC salt 
    $hmac_salt = substr($bin_data, 10, 8); 
    // extract IV 
    $iv = substr($bin_data, 18, 16); 
    // extract data 
    $data = substr($bin_data, 34, strlen($bin_data) - 34 - 32); 
    $dataWithoutHMAC = chr(2).chr(1).$salt.$hmac_salt.$iv.$data; 
    // extract HMAC 
    $hmac = substr($bin_data, strlen($bin_data) - 32); 
    // make HMAC key 
    $hmac_key = hash_pbkdf2($pbkdf2_prf, $gPassword, $hmac_salt, $pbkdf2_iterations, $key_size, true); 
    // make HMAC hash 
    $hmac_hash = hash_hmac($hmac_algorithm, $dataWithoutHMAC , $hmac_key, true); 
    // check if HMAC hash matches HMAC 
    if($hmac_hash != $hmac) { 
     echo "HMAC mismatch".$nl.$nl.$nl; 
     return false; 
    } 
    // make data key 
    $key = hash_pbkdf2($pbkdf2_prf, $gPassword, $salt, $pbkdf2_iterations, $key_size, true); 

    // decrypt 
    $cypher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); 
    // initialize encryption handle 
    if (mcrypt_generic_init($cypher, $key, $iv) != -1) { 
     // decrypt 
     $decrypted = mdecrypt_generic($cypher, $data); 

     // http://www.php.net/manual/en/function.mdecrypt-generic.php 
     // We found that sometimes the resulting padding is not null characters "\0" but rather one of several control characters. 
     // If you know your data is not supposed to have any trailing control characters "as we did" you can strip them like so. 
     $decrypted = preg_replace("/\p{Cc}*$/u", "", $decrypted); 

     // clean up 
     mcrypt_generic_deinit($cypher); 
     mcrypt_module_close($cypher); 

     return trim($decrypted); 
    } 
    return false; 
} 

정말 RNCryptor의 1.x에서 선으로 암호화 된 데이터와 함께 작동하는 위의 같은 기능이 필요합니다. 그것의 짧은, 누구든지 내가 어떻게 위의 기능을 스스로 적응할 수있는 알고? 감사!

+0

$ hmac_algorithm을 'sha512'또는 'sha384'로 변경해보십시오. 이로 인해 문제가 해결 될 수 있습니다. 그러나, PHP는 아직 그 알고리즘을 지원하는지 모르겠다. – Dropzilla

+0

불행히도, 그것은 작동하지 않았다. 그러나 나는 그것을 알아 냈다. 아래 내 대답을 참조하십시오. – curtisdf

답변

0

내 문제가 내가 생각한 것과 약간 다르다는 것을 깨달았습니다. 실제로 RNCryptor 2.0을 무의식적으로 사용하고 있었지만 근본적인 문제가 여전히 남아 있다는 것을 알았습니다. PHP 구현 RNCryptor에 포함 된 내용이 내 데이터를 해독하지 못하는 것으로 나타났습니다.

RNCryptor는 데이터를 자체적으로 암호화하는 것이 아니라 여러 시간 동안 연구하고 테스트 한 후에 배웠습니다. 또한 사용자 정의 헤더와 HMAC 디지털 서명을 추가합니다. 안타깝게도 헤더와 HMAC를 배치하기위한 스키마는 RNCryptor 1.0이 출시 된 이래로 몇 번 변경되었습니다.

RNCryptor 1.0과 1.1은 스키마 버전 0을 사용합니다. 필자가 생각하기에 머리말을 붙였습니다. PHP에서 AES CTR Little Endian en/decryption을 사용할 수 없습니다. (누구나 아시 겠지만)

RNCryptor 2.0은 스키마 버전 1을 사용하고 RNCryptor 2.1은 스키마 2를 사용합니다. 유일한 차이점은 스키마 1에서 HMAC는 헤더가 아니라 페이로드에서 생성된다는 것입니다. 스키마 2 올바르게 페이로드 플러스 머리글에서 HMAC를 생성합니다 (따라서 더 안전한 방법입니다.) 자세한 내용은 this post on Rob Napier's blog에서 찾을 수 있습니다.

이 문제를 문서화하고 다른 사람 (당신!)이 문제를 일으키는 것을 방지하기 위해 RNCryptor에 포함 된 PHP 구현을 정밀 검사하기로 결정했습니다. 또한 구현을 현대화하고 객체 지향적으로 만들고 싶었습니다. my forked RNCryptor on Github을 참조하십시오. 끌어 오기 요청도 제출 했으므로 희망적으로는 rnapier/RNCryptor으로 끝납니다.

건배!