由于这个问题相当受欢迎,我认为给它更新很有用。
让我强调AviD对此问题的正确答案:
您不应存储任何需要在Cookie中加密的数据。而是在Cookie中存储大小合适的(128位/ 16字节)随机密钥并存储您想要保密的信息在服务器上,由cookie的密钥标识。
我正在寻找有关加密Cookie的“最佳”加密算法的信息。
我有以下要求:
一定要快 将对(几乎)每个请求进行加密和解密数据
它将在小数据集上运行,通常是大约100个字符或更少的字符串
它必须是安全的,但它不像我们确保银行交易安全
我们需要能够解密信息,以便SHA1等出来。
现在我已经读过Blowfish快速而安全,我读过AES快速而安全。 Blowfish的块大小较小。
我认为这两种算法都提供了足够的安全性?所以速度将成为决定性因素。 但我真的不知道这些算法是否适合小字符串,以及是否有更适合加密cookie的算法。
所以我的问题是:
什么加密算法最适合加密cookie数据?
更新
更确切地说,我们想要加密2个cookie:一个包含会话信息,另一个包含“记住我”信息。
该平台是PHP上的Linux上的apache模块。
更新2
我同意cletus将任何信息存储在cookie中是不安全的。
但是,我们要求实现'记住我'功能。可接受的方法是设置cookie。如果客户端提供此cookie,则允许他或她以(几乎)相同的权限访问系统,就像他/她提供有效的用户名密码组合一样。
所以我们至少要加密cookie中的所有数据,以便它:
a)恶意用户无法读取内容,
b)恶意用户无法制作自己的Cookie或篡改它。
(在我们对它做任何事情之前,对所有来自cookie的数据进行消毒并检查其有效性,但这是另一个故事)
会话cookie不再包含sessionId / timestamp。它可以在没有加密的情况下使用,但我认为加密它没什么害处? (计算时间除外)。
因此我们必须在cookie中存储一些数据,加密它的最佳方法是什么?
更新3
对这个问题的回答使我重新考虑所选择的方法。我确实可以做同样的事情而不需要加密。我不应该加密数据,而应该只发送没有上下文且无法猜到的无意义的数据。
然而,我也不知所措:
我认为加密使我们能够将数据发送到BigBadWorld™,并且仍然(相当)确定没有人可以读取或篡改它...
这不是加密的全部意义吗?
但是下面的反应推动:不要相信加密来实现安全性。
我错过了什么?
答案 0 :(得分:24)
没有真正的理由不使用256位的AES。确保在CBC mode和PKCS#7填充中使用它。 正如你所说,快速而安全。
我已阅读(未测试)Blowfish可能稍快一些......但是Blowfish的主要缺点是设置时间长,这会使您的情况变得糟糕。此外,AES更“经过验证”。
这假设确实 对对称加密您的cookie数据是必要的。正如其他人所指出的那样,它确实不是必要的,并且只有少数边缘情况除此之外别无选择。通常,它更适合您更改设计,并返回随机会话标识符,或者必要时单向哈希(使用SHA-256)。
在您的情况下,除了“常规”随机会话标识符,您的问题是“记住我”功能 - 这也应该实现为:
似乎我们已经对您原来的具体问题略微偏离了主题 - 并通过更改设计改变了问题的基础....
所以,只要我们这样做,我也强烈建议反对持续“记住我”的这个特征,原因有几个,其中最大的是:
答案 1 :(得分:19)
这涉及两个不同的问题。
首先,会话劫持。这是第三方发现经过身份验证的cookie并获取其他人详细信息的地方。
其次,会话数据安全性。我的意思是你将数据存储在cookie中(例如用户名)。这不是一个好主意。任何此类数据从根本上都是不值得信任的,就像HTML表单数据不可信(无论您使用什么Javascript验证和/或HTML长度限制,如果有的话),因为客户可以自由提交他们想要的内容。
您经常会发现人们(正确地)主张对HTML表单数据进行清理,但cookie表面数据会被盲目接受。大错。事实上,我从不在cookie中存储任何信息。我将其视为会话密钥,这就是全部。
如果您打算将数据存储在Cookie中,我强烈建议您重新考虑。
加密此数据不会使信息更受信任,因为对称加密容易受到暴力攻击。显然,AES-256比DES(heh)更好,但256位的安全性并不一定意味着它的意思。
首先,SALT通常是根据算法生成的,否则很容易受到攻击。
另一方面,cookie数据是crib攻击的主要候选者。如果已知或怀疑加密数据中的用户名是嘿,那就是你的婴儿床。
这让我们回到第一点:劫持。
应该指出的是,在PHP的共享托管环境中(作为一个示例),您的会话数据只是存储在文件系统上,并且可以由同一主机上的任何其他人读取,尽管他们不一定知道哪个站点是为了。因此,在没有某种形式的加密的情况下,永远不要存储明文密码,信用卡号,广泛的个人详细信息或在会话数据中可能被视为敏感的任何内容,或者更好的是,只需在会话中存储密钥并存储实际的敏感信息数据库中的数据。
注意:上述内容并非PHP独有。
但那是服务器端加密。
现在你可能会争辩说用一些额外的数据加密会话会使它更加安全,不会被劫持。一个常见的例子是用户的IP地址。问题是很多人在许多不同的地方使用相同的PC /笔记本电脑(例如Wifi热点,工作,家庭)。此外,许多环境将使用各种IP地址作为源地址,尤其是在企业环境中。
您也可以使用用户代理,但这是可以猜测的。
实际上,据我所知,根本没有真正的理由使用cookie加密。我从来没有想过有这个问题,但鉴于这个问题,我一直在寻求证明是对还是错。我找到了一些关于人们建议加密cookie数据的方法的线程,透明地用Apache模块做等等,但这些都似乎都是通过保护存储在cookie中的数据(这是你不应该做的)来实现的。
我还没有看到加密cookie的安全性参数,该cookie只代表会话密钥。
如果有人可以指出相反的事情,我将很高兴被证明是错误的。
答案 2 :(得分:9)
安全警告:这两项功能不安全。他们正在使用ECB mode而未能使用authenticate the ciphertext。有关更好的前进方法,请参阅this answer。
对于想要在PHP脚本中使用此方法的读者。以下是使用256位Rijndael(非AES)的工作示例。
function encrypt($text, $salt)
{
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, $salt)
{
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)));
}
然后保存cookie
setcookie("PHPSESSION", encrypt('thecookiedata', 'longsecretsalt'));
并阅读下一页:
$data = decrypt($_COOKIE['PHPSESSION'], 'longsecretsalt');
答案 3 :(得分:4)
通过在EAX模式下使用AES,您可以安全地实现所需。密文将大于明文;这对于安全加密是正常的。
攻击者当然会从密文中知道明文的长度,但他们无法确定其他任何内容。
随机生成AES密钥。
确保并为每次加密使用新的随机数,并使用“关联数据”字段确保您为一个目的加密的内容不会显示为另一个(因此诸如用户名和cookie名称之类的内容)可以去那里)
下面的反应推动:做 不信任加密来完成 安全
更多“如果你不是加密专家,你会低估出错的容易程度”。例如,AFAICT此线程中没有其他人讨论了链接模式或消息完整性,它涵盖了两个常见的初学者错误。
答案 4 :(得分:4)
如果您需要PHP中快速,安全的加密Cookie,请查看Halite如何实现它们。 Halite依靠the libsodium PECL extension来提供安全加密。
<?php
use \ParagonIE\Halite\Cookie;
use \ParagonIE\Halite\Symmetric\Key;
use \ParagonIE\Halite\Symmetric\SecretKey;
// You can also use Key::deriveFromPassword($password, $salt, Key::CRYPTO_SECRETBOX);
$encryption_key = new SecretKey($some_constant_32byte_string_here);
$cookie = new Cookie($encryption_key);
$cookie->store('index', $any_value);
$some_value = $cookie->fetch('other_index');
如果您无法安装PECL扩展程序,请让您的系统管理员或托管服务提供商为您执行此操作。如果他们拒绝,你仍然可以选择。
其他答案指示您使用openssl或mcrypt加密数据,但是他们错过了至关重要的一步。如果您想要safely encrypt data in PHP,则必须对您的消息进行身份验证。
使用OpenSSL扩展,您需要遵循的过程如下所示:
(甚至在考虑加密之前)生成128位,192位或256位随机字符串。这将是您的主密钥。
请勿使用人类可读的密码。如果您出于某种原因必须使用人类可读的密码,请向Cryptography SE寻求指导。
如果您需要特别关注,我的雇主会提供technology consulting services,包括加密功能的开发。
random_bytes(openssl_cipher_iv_length('aes-256-cbc'))
$eKey
)$aKey
)openssl_encrypt()
)使用aes-256-ctr
加密您的字符串,并使用第2步中的加密密钥($eKey
)。hash_hmac('sha256', $iv.$ciphertext, $aKey)
。 加密后进行身份验证非常重要,并且还要封装IV / nonce。 bin2hex()
或base64_encode()
对其进行编码。 (警告:此方法可能泄漏缓存时间信息。)hash_equals()
通过用户提供的HMAC重新计算IV / nonce和密文的HMAC来验证身份验证标记。$eKey
解密密文。如果您想了解这一切是如何一起看的,请参阅this answer which has sample code。
如果这听起来太多,请使用defuse/php-encryption或zend-crypt并将其称为一天。
但是,我们要求实现'记住我'功能。可接受的方法是设置cookie。如果客户端提供此cookie,则允许他或她以(几乎)相同的权限访问系统,就像他/她提供有效的用户名密码组合一样。
加密实际上不是这项工作的正确工具。您想对secure remember me cookies in PHP:
执行此过程selector
。 (随机选择器而不仅仅是一个顺序ID的目的是不泄漏您的网站上有多少活跃用户。如果您愿意泄露此信息,请随意使用顺序ID 。)validator
,用于自动验证用户。validator
的哈希值(简单的SHA-256哈希就足够了)。selector
和validator
的哈希值存储在为自动登录保留的数据库表中。selector
和validator
存储在客户端的Cookie中。selector
和validator
。selector
执行数据库查找(使用prepared statements!)。validator
。hash_equals()
将步骤3中计算的哈希值与数据库中存储的哈希值进行比较。这是Gatekeeper用于长期用户身份验证的策略,它是迄今为止满足此要求的最安全策略。
答案 5 :(得分:2)
虽然两者都非常强大,但AES是标准。
对于小块数据的安全性:越小越好。泄露的加密数据越少,您使用密钥的时间就越长。在不给系统带来风险的情况下,在给定算法的一个密钥内可以加密多少数据总是存在理论上的限制。
答案 6 :(得分:2)
如果你加密cookie,服务器仍然需要对它进行解码才能读取它(检查相同的密钥),因此任何加密的cookie都是没有意义的,因为如果被盗(并且未被编辑),它仍将导致黑客正确到您的帐户。它就像不加密一样不安全。
我相信有人偷你的cookie的真正问题是服务器和客户端之间的连接。使用主机提供的SSL连接。
至于你的cookie,你需要在数据库中为每个用户创建一个长的随机id,(让它更改每个登录)并将其设置为cookie或会话。可以通过php检查包含密钥的cookie,如果它等于数据库中的帐户或表,则将数据转储到网页上,就像正常一样。
答案 7 :(得分:2)
正如之前评论中指出的那样,您必须将完整性保护应用于您发送给用户并接受回复的任何密文。否则,可以修改受保护的数据,或者恢复加密密钥。
特别是PHP世界充满了忽略这一点的坏例子(见PHP cryptography - proceed with care),但这适用于任何语言。
我见过的一个很好的例子是PHP-CryptLib,它使用组合加密认证模式来完成这项工作。对于Python pyOCB提供了类似的功能。
答案 8 :(得分:1)
为什么要加密cookie?
正如我所看到的,有两种情况:要么给客户钥匙,要么你没有。
如果您没有将密钥提供给客户端,那么您为什么要向他们提供数据?除非你打破一些奇怪的游戏,打破弱加密(你明确没有),你也可以将数据存储在服务器上。
如果您 将客户端的密钥交给客户端,那么为什么要在第一时间对其进行加密?如果你不加密密钥的通信,那么加密cookie是没有意义的:MITM可以查看cookie并向你发送他想要的任何cookie。如果您使用加密通道到客户端,为什么加密存储数据的额外开销呢?
如果您担心客户端计算机上的其他用户正在阅读cookie,请放弃并假设浏览器设置好的权限位:)
答案 9 :(得分:0)
答案 10 :(得分:0)
我认为“赠送”任何数据甚至是加密的,当涉及用户名和密码时都不好...... 有很多JS可以嗅到它...... 我建议你在用户数据库表中创建一个字段cookie_auth或者其他......
首次登录后收集:当前:浏览器,IP,一些自己的盐键,加上你的主机名var ......
在该字段中创建哈希并存储... 设置一个cookie ... 当cookie“响应”将所有这些与存储的哈希进行比较并完成...
即使有人“偷”了一个cookie,他们也无法使用它: - )
希望这会有所帮助: - )
FEHA vision.to
答案 11 :(得分:0)
此外,我已经尝试了mcrypt_encrypt
,请记住一件事。如果你做base64_encode(mcrypt_encrypt(...))
。
然后,您执行base64_decode
并输出加密数据(echo
)。你可能会被搞砸而没有看到任何东西。但是,如果你做mcrypt_decrypt( ... base64_decode($value) )
。您将看到原始数据。
答案 12 :(得分:-1)
说了这么多可怕的话,但这是对的,但让我们看看乐观的一面,一点常识和对网站的持续监视可能会一直节省您的时间。
保存cookie是Web开发的重要组成部分,因此人们不能忽略它。但是我们也应该尽量避免;我仅在即使用户关闭浏览器后仍想扩展登录会话时,才看到Cookies的使用。如果不希望将用户会话扩展到关闭浏览器之外,则应使用会话组件。即使使用会话组件,也应该注意会话劫持。
无论如何,回到Cookie的东西;我认为,如果遵循以下预防措施,我很确定我们会在安全方面。
我将precautionary measurement
分为两个阶段
第一阶段:开发
path
属性expiration_date
secure
,httpOnly
属性blowfish
,然后在其顶部使用base64_encode
。阶段2:操作/审核
burp
之类的工具定期进行站点审核。