- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要加密一些数据并在稍后的某个时间点解密。数据与特定用户相关联。我收集了两种可能的解决方案...
1:第一个来自官方文档(示例#1 @ http://php.net/manual/en/function.mcrypt-encrypt.php):
function encrypt($toEncrypt)
{
global $key;
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $toEncrypt, MCRYPT_MODE_CBC, $iv));
}
function decrypt($toDecrypt)
{
global $key;
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$toDecrypt = base64_decode($toDecrypt);
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, substr($toDecrypt, $iv_size), MCRYPT_MODE_CBC, substr($toDecrypt, 0, $iv_size)));
}
key 生成一次使用:
echo bin2hex(openssl_random_pseudo_bytes(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC)))
后来被称为:
$key = pack('H*', [result of above]);
1.1:我注意到加密结果总是以两个等号 ('==') 结尾。为什么? - 在 encrypt() 和 decrypt() 中分别使用 bin2hex() 和 hex2bin() 而不是 base64_encode()/base64_decode() 不会产生这些结果。
1.2:使用 bin2hex()/hex2bin() 会对结果产生任何影响(长度除外)吗?
1.3:似乎有一些讨论是否在解密时对返回结果调用修剪函数(这也适用于下面的解决方案)。为什么这是必要的?
2:第二个解决方案来自这里,Stackoverflow ( Simplest two-way encryption using PHP ):
function encrypt($key, $toEncrypt)
{
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $toEncrypt, MCRYPT_MODE_CBC, md5(md5($key))));
}
function decrypt($key, $toDecrypt)
{
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($toDecrypt), MCRYPT_MODE_CBC, md5(md5($key))), "\0");
}
我知道这两种 key 处理方法是可以互换的,我特意让它们在这方面有所不同,以突出可能的解决方案,请随意混合搭配。
我个人认为第一个提供了更严格的安全性,因为 key 和初始化向量都是适当随机化的。然而,第二种解决方案确实提供了某种形式的不可预测性,因为 key 对于每条加密数据都是唯一的(即使它受到 md5() 弱随机化的影响)。例如, key 可以是用户名。
3:那么,哪个更可取?自从 Stackoverflow 的答案获得了高达 105 票后,我就有点不知所措了。其他想法、提示?
4:奖金问题!:我在服务器安全方面并不是非常聪明,但显然获得对 PHP 文件的访问权限会暴露 key ,这会直接导致加密没用,假设攻击者也可以访问数据库。有什么办法可以隐藏 key 吗?
感谢您的阅读,祝您有愉快的一天!
编辑:综合考虑,这似乎是我最好的选择:
function encrypt($toEncrypt)
{
global $key;
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
return base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $toEncrypt, MCRYPT_MODE_CBC, $iv));
}
function decrypt($toDecrypt)
{
global $key;
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$toDecrypt = base64_decode($toDecrypt);
return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, substr($toDecrypt, $iv_size), MCRYPT_MODE_CBC, substr($toDecrypt, 0, $iv_size)));
}
使用一次创建的 key :
bin2hex(openssl_random_pseudo_bytes(32)));
最佳答案
两个代码示例之间的主要区别是第一个生成随机 initialization vector (IV) 对于每条消息,而第二条消息始终使用从 key 派生的固定 IV。
如果您从不使用同一 key 加密多条消息,则两种方法都可以。然而,encrypting multiple messages with the same key and IV is dangerous ,因此您永远不应使用第二个代码示例使用同一 key 加密多条消息。
另一个区别是第一个代码示例将 key 直接传递给 block 密码 (Rijndael),而第二个代码示例首先通过 md5()
运行它。 , 显然是在尝试将其用作 key derivation function .
如果 key 已经是随机位串(长度合适),就像您的示例 key 生成代码会生成的那样,则无需通过 md5()
运行它.相反,如果它类似于用户提供的密码,那么对它进行散列处理可能有一些优势——但在那种情况下,您真的应该使用适当的 key 派生函数,例如 PBKDF2相反,例如像这样:
$cipher = MCRYPT_RIJNDAEL_128; // = AES-256
$mode = MCRYPT_MODE_CBC;
$keylen = mcrypt_get_key_size( $cipher, $mode );
$salt = mcrypt_create_iv( $keylen, MCRYPT_DEV_URANDOM );
$iterations = 10000; // higher = slower; make this as high as you can tolerate
$key = hash_pbkdf2( 'sha256', $password, $salt, $iterations, $keylen, true );
注意正确的$salt
和 $iterations
需要值来从密码重建 key 以进行解密,因此请记住将它们存储在某个地方,例如通过将它们添加到密文中。盐的长度并不重要,只要不是很短即可;使其等于 key 长度是一个足够安全的选择。
(顺便说一句,这也是一种对密码进行散列以验证其正确性的好方法。显然,您不应该对加密和密码验证使用相同的 $key
值,但您可以安全地存储,比如说, hash( 'sha256', $key, true )
与密文一起让您验证密码/ key 是否正确。)
我在这两个代码片段中看到的其他一些问题:
两个片段都使用 MCRYPT_RIJNDAEL_256
,显然,不是 AES-256 ,而是非标准的 Rijndael-256/256 变体,具有 256 位 block 大小(和 key 大小)。它可能是安全的,但是 Rijndael 的 256 位 block 大小的变体比 128 位 block 大小的变体(被标准化为 AES)受到的密码分析审查要少得多,所以你使用它们会稍微承担更高的风险。
因此,如果您想保险起见,需要与使用标准 AES 的其他软件进行互操作,或者只需要能够告诉您的老板,是的,您正在使用标准的 NIST 批准的密码,那么您应该和MCRYPT_RIJNDAEL_128
一起去(显然,这就是 mcrypt 所称的 AES-256)。
在您的 key 生成代码中,pack( 'H*', bin2hex( ... ) )
是空操作:bin2hex()
将 key 从二进制转换为十六进制,并且 pack( 'H*', ... )
然后反过来。只需摆脱这两个功能。
此外,您生成的是 key ,而不是 IV,因此您应该使用 mcrypt_get_<b>key</b>_size()
, 不是 mcrypt_get_iv_size()
.碰巧,对于 MCRYPT_RIJNDAEL_256
没有区别(因为 IV 大小和 key 大小都是 32 字节 = 256 位),但对于 MCRYPT_RIJNDAEL_128
(以及许多其他密码)有。
正如 owlstead 指出的那样,mcrypt 的 CBC 模式实现显然使用了非标准的零填充方案。您的第二个代码示例正确地删除了填充 rtrim( $msg, "\0" )
;第一个只是调用 rtrim( $msg )
, 这也将删除消息末尾的所有空格。
此外,显然,如果您的数据可以合法地在末尾包含零字节,则此零填充方案将无法正常工作。您可以改为切换到其他一些密码模式,例如 MCRYPT_MODE_CFB
或 MCRYPT_MODE_OFB
,不需要任何填充。 (在这两者中,我通常会推荐 CFB,因为 accidental IV reuse is very bad for OFB。这对 CFB 或 CBC 都不利,但它们的故障模式灾难性要小得多。)
关于php - 两个采用 PHP 双向加密 - 哪个更可取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26273815/
我正在使用框架的对象编写一个用于加密/解密的简单库。方法如下: public static byte[] Encrypt(byte[] key, byte[] vector, byte[] input
据我所知,RIM Crypto API 似乎只提供用于对称加密 (3Des) 的 PKCS5 填充模式。我正在使用 JDE 4.6.0。 我正在尝试为黑莓应用程序提供密码学,该应用程序需要与已经使用标
我已经获得了用于加密的 Java 实现,但遗憾的是我们是一家 .net 商店,我无法将 Java 整合到我们的解决方案中。可悲的是,我也不是 Java 专家,所以我已经为此苦苦挣扎了几天,我想我终于可
我正在尝试使用 KMS 和 AWS 加密 SDK 加密数据。查看 AWS documentation 中提供的示例,似乎没有地方可以明确设置数据 key 。 我找到了 EncryptionMateri
我目前有一个用于为我的网站制作哈希的代码,该代码使用 SALT 进行哈希处理,因此密码是不可逆的...... 目前它是 100% 为我的网站工作,它是使用 ASP.NET(C#) 编码的 这是我的代码
我想要做的是在 javascript 中生成一个 key 对,并在 PHP 中使用这些加密,然后用 JS 解密。 我在附加的代码中有两个问题 它不会从装甲文本块重新加载私钥 并且它不会解密 PHP 加
在进行密码哈希时,我有以下 node.js 代码。 body.password = covid@19 salt = "hello@world" body.passwordhex = crypto.cr
我想知道的是在配置文件中加密连接字符串的明确方法。以下是我的问题: 使用机器级加密,访问我的服务器的任何人都不能编写一个小的 .Net 程序来读取连接字符串的内容吗? 如果我将我的应用程序部署到企业环
我知道 rsync 可以在文件传输期间启用/禁用 ssh 加密协议(protocol)。那么,如果 ssh 加密协议(protocol)被禁用了,是不是意味着 rsync 根本不做任何加密呢? 另外,
脚本必须搜索网页内的字符串。但该脚本不应显示它正在搜索的字符串。我的意思是搜索字符串应该采用加密格式或任何其他格式。但如果没有该搜索字符串,则不应显示网页或应在页面上显示错误。 我要开发一个插件。如果
我正在尝试加密 MySQL 上的某些字段。我正在使用 TPC-DS 的 v2.8 版本,并尝试在客户地址表的某些列上使用 AES。知道如何加密字段的所有行吗?我尝试使用 UPDATE customer
我需要一个简单的 javascript 函数,它允许我使用 key 加密 textarea 数据( key 是存储为散列 session 变量的用户密码,由 PHP 打印到字段中) 我基本上希望在用户
如何在 JavaScript 中散列/加密字符串值?我需要一种机制来隐藏 localStorage/cookie 中的一些数据吗? 这与安全问题有关,但我想为我的数据提供一些保护。 最佳答案 有很多
我有一个程序,其中数据库的密码由远程用户设置。该程序将用户名和密码保存到 xml 文件中的加密字符串中,否则应该是人类可读的。现在,这工作正常,我使用带有 key 的 C# DES 加密,它被加密和解
Kotlin 中是否有任何关于椭圆曲线加密的信息? 用于生成 key 对和加密、解密消息。 关于这个主题的信息很少甚至没有。 例如,我想实现 ECC P-521 椭圆曲线。 是否可以在 Kotlin
所以我知道 MD5 在技术上是新应用程序的禁忌,但我随机想到了这个: 自 md5($password); 不安全,不会 md5(md5($password)) 是更好的选择?我使用它的次数越多,它会变
我一直在努力使用 crypto_secretbox_easy() 在 libsodium 中加密/解密一些数据| .我似乎找不到关于使用的任何好的文档。 我想从用户那里获取密码,用它来以某种方式制作
我正在做一个加密项目 视频,我对这个程序有几个问题。 我用命令转码mp4至HLS与 ts段持续时间约为 10 秒。 首先,我需要使用数据库中的 key 加密这些视频。然而, 我不知道是否使用 ffmp
我有一个加密/复制保护问题。 我正在为使用加密狗的公司编写应用程序。请不要告诉我软件保护是没有用的,或者我应该让它自由地飞向空中,或者我花任何时间这样做都是浪费;这不是关于软件保护有效性的哲学问题,更
我对 有一个疑问VIM 加密 key . 我有一个文本文件,我使用加密该文件 :X 现在,加密 key 的存储位置(路径)。 无论是存储在单独的文件中还是存储在文本文件本身中。 如果我打开文件,它会询
我是一名优秀的程序员,十分优秀!