2010-03-15 100 views
21

嘗試寫一對夫婦,將加密或解密文件的功能和現在用在這裏發現的類,試圖做到這一點:加密/解密文件,這個Mcrypt

http://www.itnewb.com/v/PHP-Encryption-Decryption-Using-the-MCrypt-Library-libmcrypt

加密功能下面似乎工作,因爲它似乎加密文件並將其放置在預期的目錄中。我試圖現在解密文件,它只是隨着消息「無法完成解密」(它在那裏編碼...)消失在PHP錯誤日誌中沒有什麼,所以我不知道爲什麼它失敗,但mcrypt的完全是新的給我,我比傾向於更相信我在這裏做得不對...

這裏的功能是:

//ENCRYPT FILE 
    function encryptFile() { 
     global $cryptastic; 
     $pass = PGPPASS; 
     $salt = PGPSALT; 
     $key = $cryptastic->pbkdf2($pass, $salt, 1000, 32) or die("Failed to generate secret key."); 

     if ($handle = opendir(PATH.'/ftpd')) { 
      while (false !== ($file = readdir($handle))) { 
       if ($file != "." && $file != "..") { 
        $newfile = PATH.'/encrypted/'.$file.'.txt'; 
        $msg = file_get_contents(PATH.'/ftpd/'.$file); 
        $encrypted = $cryptastic->encrypt($msg, $key) or die("Failed to complete encryption."); 
        $nfile = fopen($newfile, 'w'); 
        fwrite($nfile, $encrypted); 
        fclose($nfile); 
        unlink(PATH.'/ftpd/'.$file); 

       } 
      } 
      closedir($handle); 
     }  


//DECRYPT FILE 
    function inFTP() { 
     global $cryptastic; 
     $pass = PGPPASS; 
     $salt = PGPSALT; 
     $key = $cryptastic->pbkdf2($pass, $salt, 1000, 32) or die("Failed to generate secret key."); 

     if ($handle = opendir(PATH.'/encrypted')) { 
      while (false !== ($file = readdir($handle))) { 
       if ($file != "." && $file != "..") { 
        $newfile = PATH.'/decrypted/'.$file; 
        $msg = PATH.'/encrypted/'.$file; 
        $decrypted = $cryptastic->decrypt($msg, $key) or die("Failed to complete decryption."); 
        $nfile = fopen($newfile, 'w'); 
        fwrite($nfile, $decrypted); 
        fclose($nfile); 
        //unlink(PATH.'/encrypted/'.$file); 

       } 
      } 
      closedir($handle); 
     }  
     //$crypt->decrypt($file); 
    } 
+0

cryptastic類是不是有某種您可以調用的錯誤報告方法? – 2010-03-15 15:30:10

回答

54

嘗試使用加密這個PHP5類使用mcrypt。在這種情況下,它使用AES加密。您需要更改每個使用它的網站的密鑰。如果你至少不使用它,它可能會指導你編寫你自己的版本。

<?php 

class Encryption 
{ 
    const CIPHER = MCRYPT_RIJNDAEL_128; // Rijndael-128 is AES 
    const MODE = MCRYPT_MODE_CBC; 

    /* Cryptographic key of length 16, 24 or 32. NOT a password! */ 
    private $key; 
    public function __construct($key) { 
     $this->key = $key; 
    } 

    public function encrypt($plaintext) { 
     $ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE); 
     $iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM); 
     $ciphertext = mcrypt_encrypt(self::CIPHER, $this->key, $plaintext, self::MODE, $iv); 
     return base64_encode($iv.$ciphertext); 
    } 

    public function decrypt($ciphertext) { 
     $ciphertext = base64_decode($ciphertext); 
     $ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE); 
     if (strlen($ciphertext) < $ivSize) { 
      throw new Exception('Missing initialization vector'); 
     } 

     $iv = substr($ciphertext, 0, $ivSize); 
     $ciphertext = substr($ciphertext, $ivSize); 
     $plaintext = mcrypt_decrypt(self::CIPHER, $this->key, $ciphertext, self::MODE, $iv); 
     return rtrim($plaintext, "\0"); 
    } 
} 

用法:

$key = /* CRYPTOGRAPHIC!!! key */; 
$crypt = new Encryption($key); 
$encrypted_string = $crypt->encrypt('this is a test'); 
$decrypted_string = $crypt->decrypt($encrypted_string); // this is a test 

注:

  • 該類不是用於處理二進制數據的使用(其可以在NUL字節結束)安全
  • 此類不提供認證加密。
+3

這是否適用於二進制數據,如圖像? – 2011-10-11 10:37:18

+3

對於二進制數據,我認爲你必須base64_encode它在encription – 2012-12-23 10:30:54

+4

這是正確的。我在文本文件上運行了這個類,它運行得非常好。對於二進制文件,有必要在加密之前對信息進行編碼。 如果文件大於100MB左右,base64_encode會導致性能問題,所以您可能需要考慮將文件拆分爲塊進行加密。從安全角度來看,這不是一個理想的解決方案,因爲它爲恢復部分明文提供了更多機會。但是,它的工作。 – 2013-02-21 19:46:51

1

CakePHP Rijndael算法有一個不錯的implementation。我不直接在這裏發佈代碼,因爲不確定法律後果。

Here are the api docsSecurity::rijndael()方法。

如果編碼文件,你會調用此方法與「encrypt」之前要base64_encode(),並base64_decode()調用此方法與「decrypt

+0

base64_ *爲我工作的二進制數據。謝謝! – adela 2015-02-25 16:03:48

2

雖然約翰的回答是好,使用base64編碼只是修復後二進制安全問題是矯枉過正,並會使您的加密文件比原來大33%。這是我的PHP實現AES Crypt文件格式,它透明地解決了所有上述問題。

https://github.com/philios33/PHP-AES-File-Encryption

它是二進制安全的,包括認證加密。由於它使用開源的crypt文件格式(.aes),它與其他.aes軟件完全兼容。

https://www.aescrypt.com/

的接口是相當簡單的你是否加密或解密。你只要給它一個源文件和密碼。

1

您不應該使用Mcrypt來加密/解密數據。正如你的問題和接受的答案所示,數據沒有通過認證,這意味着它將成爲選擇密文攻擊的受害者。

此外,爲確保開發人員正確地將加密原語組合在一起,已經做了大量努力。因此,而不是Mcrypt,您應該爲您的PHP項目使用libsodium。 libsodium是NaCl的一個分支。 NaCl/libsodium是爲了消除開發者發現的許多加密陷阱,例如使用MAC標籤驗證的定時攻擊。

Mcrypt在PHP 7.1中不推薦使用,libsodim是PHP中處理加密的首選方法。

在您的PHP項目中使用libsodium非常簡單且安全。 Scott Arciszewski在https://paragonie.com/book/pecl-libsodium上撰寫了關於在PHP中使用libsodium的大量電子書。任何人在做PHP密碼學都值得讀。