Base64是可解密的,因此没有使用它的意义。我的想法是在将用户和密码base64编码之前和之后对其进行混淆,这样即使在解密后,如果您尝试解密,您也会得到一些看起来很有趣的文本。是否有一个PHP函数可以接受值,并使字符串生成唯一的混淆文本,并在重新输入该值时解除混淆?
有什么建议吗?
你不应该加密密码,而应该使用像bcrypt这样的算法对密码进行哈希。 这个答案解释了如何在PHP中正确实现密码哈希。 不过,以下是如何加密/解密:
$key = 'password to (en/de)crypt';
$string = ' string to be encrypted '; // note the spaces
加密:
$iv = mcrypt_create_iv(
mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC),
MCRYPT_DEV_URANDOM
);
$encrypted = base64_encode(
$iv .
mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
hash('sha256', $key, true),
$string,
MCRYPT_MODE_CBC,
$iv
)
);
要解密:
$data = base64_decode($encrypted);
$iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));
$decrypted = rtrim(
mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
hash('sha256', $key, true),
substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)),
MCRYPT_MODE_CBC,
$iv
),
"\0"
);
警告:上述示例对信息进行了加密,但未对密文进行身份验证以防篡改。您不应该依赖未经身份验证的加密来保证安全性,尤其是由于所提供的代码易受填充神谕攻击的影响。此外,不要仅使用“密码”作为加密密钥。加密密钥应该是随机字符串。
echo 'Encrypted:' . "\n";
var_dump($encrypted); // "m1DSXVlAKJnLm7k3WrVd51omGL/05JJrPluBonO9W+9ohkNuw8rWdJW6NeLNc688="
echo "\n";
echo 'Decrypted:' . "\n";
var_dump($decrypted); // " string to be encrypted "
$string
周围空格的意义。它们是在加密之前人为添加以增加破解难度吗?如果我理解有误请不要介意 ;) - wired00[r]trim()
来去掉这些空字节,但在此过程中也会删除空格。我添加了这些空格,以便人们可以测试和验证正确的修剪解密后的字符串的方法是:$original = rtrim($decrypted, "\0");
- 注意 \0
。=) - Alix AxelPBKDF2
... - ircmaxell安全警告:此类不安全。 它使用的是Rijndael256-ECB,这不是语义上安全的。仅仅因为"它可以工作"并不意味着"它是安全的"。此外,由于未使用适当的填充方式,它会剥离尾随空格。
最近发现了这个类,它能完美运行!
class Encryption {
var $skey = "yourSecretKey"; // you can change it
public function safe_b64encode($string) {
$data = base64_encode($string);
$data = str_replace(array('+','/','='),array('-','_',''),$data);
return $data;
}
public function safe_b64decode($string) {
$data = str_replace(array('-','_'),array('+','/'),$string);
$mod4 = strlen($data) % 4;
if ($mod4) {
$data .= substr('====', $mod4);
}
return base64_decode($data);
}
public function encode($value){
if(!$value){return false;}
$text = $value;
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->skey, $text, MCRYPT_MODE_ECB, $iv);
return trim($this->safe_b64encode($crypttext));
}
public function decode($value){
if(!$value){return false;}
$crypttext = $this->safe_b64decode($value);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decrypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->skey, $crypttext, MCRYPT_MODE_ECB, $iv);
return trim($decrypttext);
}
}
并且要调用它:
$str = "My secret String";
$converter = new Encryption;
$encoded = $converter->encode($str );
$decoded = $converter->decode($encoded);
echo "$encoded<p>$decoded";
Warning: mcrypt_encrypt(): Key of size 4 not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported in
是针对 PHP 5.6.x 的。 - Editor安全警告:此代码不安全。
工作示例
define('SALT', 'whateveryouwant');
function encrypt($text)
{
return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))));
}
function decrypt($text)
{
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, SALT, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)));
}
$encryptedmessage = encrypt("your message");
echo decrypt($encryptedmessage);
安全警告:此代码存在不安全性。除了容易受到选择明文攻击的影响外,它对
unserialize()
的依赖也使其容易受到PHP对象注入的攻击。
为了处理字符串/数组,我使用以下两个函数:
function encryptStringArray ($stringArray, $key = "Your secret salt thingie") {
$s = strtr(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), serialize($stringArray), MCRYPT_MODE_CBC, md5(md5($key)))), '+/=', '-_,');
return $s;
}
function decryptStringArray ($stringArray, $key = "Your secret salt thingie") {
$s = unserialize(rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode(strtr($stringArray, '-_,', '+/=')), MCRYPT_MODE_CBC, md5(md5($key))), "\0"));
return $s;
}
它是灵活的,因为在加密之前,字符串/数组会被序列化,所以你可以通过URL存储/发送字符串或数组。
md5($key)
作为密钥,而将 md5(md5($key))
作为初始向量(IV)? - Scott Arciszewski这只会给你一点保护。如果攻击者可以在你的应用程序中运行任意代码,他们可以以与你的应用程序完全相同的方式获取密码。如果你在文件中存储一个秘密密钥,并在传输到数据库时使用该密钥进行加密并在传输出时进行解密,则仍然可以从某些SQL注入攻击和错误的数据库备份中获得一些保护。但是你应该使用绑定参数来完全避免SQL注入问题。
如果决定加密,你应该使用一些高级加密库,否则你可能会做错。你必须正确设置密钥、消息填充和完整性检查,否则所有的加密努力都没有多大用处。例如,GPGME 是一个不错的选择。Mcrypt 太低级了,你很可能会做错。
请看mycrypt():http://us.php.net/manual/en/book.mcrypt.php
如果您正在使用postgres,则可以使用pgcrypto进行数据库级加密。(这使得搜索和排序更加容易)
即使您可以访问代码,加密/解密数据库中的数据的最佳方法是使用两个不同的密码:每个用户使用一个私有密码(user-pass
),所有用户使用一个私有代码(system-pass
)。
场景
user-pass
以md5格式存储在数据库中,并用于验证每个用户登录系统。每个用户的user-pass都是不同的。system-pass
,用于加密/解密数据。该system-pass对于每个用户都是相同的。