题
尝试编写几个功能,这些功能将加密或解密文件,并正在使用此处找到的类来尝试并完成此操作:
http://www.itnewb.com/v/php-encryption-decryptimption-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);
}
解决方案
尝试使用MCRYPT加密此PHP5类。在这种情况下,它使用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字节中结束)
- 该类不提供身份验证的加密。
其他提示
尽管Johns的答案很好,但仅使用Base64编码来解决二进制安全问题是过大的,并且将使您的加密文件比原始文件大33%。这是我对AES Crypt文件格式的PHP实现,该格式可以透明地解决所有问题。
https://github.com/philios33/php-aes-file-cryption
它是二进制安全的,包括经过认证的加密。由于它使用开源AES加密文件格式(.AES)与其他.AES软件完全兼容。
无论您是在加密还是解密,该界面都非常简单。您只需给它一个源文件和密码即可。
您不应使用MCRYPT来加密/解密数据。如您的问题所示,在接受的答案中,数据未经认证,这意味着它将成为选择的密文攻击的受害者。
此外,已经付出了巨大的努力来确保开发人员正确地将加密原始图放在一起。因此,您应该为PHP项目使用libsodium,而不是McRypt。 libsodium是NaCl的叉子。 NACL/libsodium的编写是为了删除开发人员发现自己所处的许多加密陷阱,例如使用MAC标签验证的定时攻击。
McRypt在PHP 7.1中被弃用,而Libsodim是处理PHP中密码学的首选方法。
在您的PHP项目中使用libsodium很容易且安全。 Scott Arciszewski撰写了一本关于将libsodium与PHP一起使用的广泛的电子书 https://paragonie.com/book/pecl-libsodium. 。对于任何从事PHP加密的人来说,都值得阅读。