没有真正的理由不使用256位的AES.确保在CBC模式和PKCS#7填充中使用它.正如你所说,快速而安全.
我读过(未测试过)Blowfish的速度可能稍微快一些......但是Blowfish的主要缺点是设置时间长,这会使你的情况变得糟糕.此外,AES更"经过验证".
这是假设它确实是必要的对称加密您的cookie数据.正如其他人所指出的那样,它确实不是必要的,并且只有少数边缘情况除此之外别无选择.通常,它更适合您更改设计,并返回随机会话标识符,或者必要时单向哈希(使用SHA-256).
在您的情况下,除了"常规"随机会话标识符,您的问题是"记住我"功能 - 这也应该实现为:
一个长的随机数,存储在数据库中并映射到用户帐户;
或者包含例如用户名,时间戳,mebbe盐和秘密服务器密钥的密钥散列(例如HMAC).这当然可以在服务器端进行验证......
好像我们对你原来的具体问题有点偏僻 - 并通过改变设计改变了你的问题的基础......
所以只要我们这样做,我也强烈建议反对这个功能坚持"记住我",有几个原因,其中最大的一个:
更有可能的是,有人可能窃取该用户的记住密钥,允许他们欺骗用户的身份(然后可能更改他的密码);
CSRF - 跨站请求伪造.您的功能将有效地允许匿名攻击者使不知情的用户向您的应用程序提交"已验证"的请求,即使没有实际登录也是如此.
添加HMAC(加密然后MAC)是必不可少的.否则填充oracles可能会破坏AES-CBC的机密性.| @ N13只要您使用好的随机密钥(如您所愿),AES-256就没有理由比AES-128弱. (5认同)
最后,没有人关心隐私或安全.这就是为什么从gmail到amazon的每个大型网站都有一个"记住我"复选框.人们宁愿丢失数据或被黑客入侵而不是输入他们的密码.所以,给他们想要的东西,因为你所竞争的所有人都已经做了. (3认同)
cletus.. 18
这涉及两个不同的问题.
首先,会话劫持.这是第三方发现经过身份验证的cookie并获取其他人详细信息的地方.
其次,有会话数据安全性.我的意思是你将数据存储在cookie中(例如用户名).这不是一个好主意.任何此类数据从根本上都是不值得信任的,就像HTML表单数据不可信(无论您使用什么Javascript验证和/或HTML长度限制,如果有的话),因为客户可以自由提交他们想要的内容.
您经常会发现人们(正确地)提倡对HTML表单数据进行清理,但cookie表面数据将被盲目接受.大错.事实上,我从不在cookie中存储任何信息.我将其视为会话密钥,就是这样.
如果您打算将数据存储在cookie中,我强烈建议您重新考虑.
加密此数据不会使信息更受信任,因为对称加密容易受到暴力攻击.显然,AES-256比DES(heh)要好,但256位的安全性并不一定意味着你的想法.
一方面,SALT通常根据算法生成或者易受攻击.
另一方面,cookie数据是婴儿床攻击的主要候选者.如果已知或怀疑加密数据中的用户名是嘿,那就是你的婴儿床.
这让我们回到第一点:劫持.
应该指出的是,在PHP的共享托管环境中(作为一个示例),您的会话数据只是存储在文件系统上,并且可以由同一主机上的任何其他人读取,尽管他们不一定知道它是用于哪个站点.因此,在没有某种形式的加密的情况下,永远不要存储明文密码,信用卡号,广泛的个人详细信息或在会话数据中可能被视为敏感的任何内容,或者更好的是,只需在会话中存储密钥并存储实际的敏感内容数据库中的数据.
注意:以上内容并非PHP独有.
但那是服务器端加密.
现在您可以争辩说,使用一些额外数据加密会话将使其更安全,免遭劫持.一个常见的例子是用户的IP地址.问题是很多人在许多不同的地方使用相同的PC /笔记本电脑(例如Wifi热点,工作,家庭).此外,许多环境将使用各种IP地址作为源地址,尤其是在企业环境中.
您也可以使用用户代理,但这是可猜测的.
实际上,据我所知,根本没有使用cookie加密的真正原因.我从来没有想过有这个问题,但鉴于这个问题,我一直在寻求证明是对还是错.我找到了一些关于人们建议加密cookie数据的方法的线程,透明地使用Apache模块,等等,但这些似乎都是通过保护存储在cookie中的数据(这是你不应该做的)来实现的.
我还没有看到加密cookie的安全性论据,该cookie只代表会话密钥.
如果有人可以指出相反的事情,我将很高兴被证明是错误的.
没有真正的理由不使用256位的AES.确保在CBC模式和PKCS#7填充中使用它.正如你所说,快速而安全.
我读过(未测试过)Blowfish的速度可能稍微快一些......但是Blowfish的主要缺点是设置时间长,这会使你的情况变得糟糕.此外,AES更"经过验证".
这是假设它确实是必要的对称加密您的cookie数据.正如其他人所指出的那样,它确实不是必要的,并且只有少数边缘情况除此之外别无选择.通常,它更适合您更改设计,并返回随机会话标识符,或者必要时单向哈希(使用SHA-256).
在您的情况下,除了"常规"随机会话标识符,您的问题是"记住我"功能 - 这也应该实现为:
一个长的随机数,存储在数据库中并映射到用户帐户;
或者包含例如用户名,时间戳,mebbe盐和秘密服务器密钥的密钥散列(例如HMAC).这当然可以在服务器端进行验证......
好像我们对你原来的具体问题有点偏僻 - 并通过改变设计改变了你的问题的基础......
所以只要我们这样做,我也强烈建议反对这个功能坚持"记住我",有几个原因,其中最大的一个:
更有可能的是,有人可能窃取该用户的记住密钥,允许他们欺骗用户的身份(然后可能更改他的密码);
CSRF - 跨站请求伪造.您的功能将有效地允许匿名攻击者使不知情的用户向您的应用程序提交"已验证"的请求,即使没有实际登录也是如此.
这涉及两个不同的问题.
首先,会话劫持.这是第三方发现经过身份验证的cookie并获取其他人详细信息的地方.
其次,有会话数据安全性.我的意思是你将数据存储在cookie中(例如用户名).这不是一个好主意.任何此类数据从根本上都是不值得信任的,就像HTML表单数据不可信(无论您使用什么Javascript验证和/或HTML长度限制,如果有的话),因为客户可以自由提交他们想要的内容.
您经常会发现人们(正确地)提倡对HTML表单数据进行清理,但cookie表面数据将被盲目接受.大错.事实上,我从不在cookie中存储任何信息.我将其视为会话密钥,就是这样.
如果您打算将数据存储在cookie中,我强烈建议您重新考虑.
加密此数据不会使信息更受信任,因为对称加密容易受到暴力攻击.显然,AES-256比DES(heh)要好,但256位的安全性并不一定意味着你的想法.
一方面,SALT通常根据算法生成或者易受攻击.
另一方面,cookie数据是婴儿床攻击的主要候选者.如果已知或怀疑加密数据中的用户名是嘿,那就是你的婴儿床.
这让我们回到第一点:劫持.
应该指出的是,在PHP的共享托管环境中(作为一个示例),您的会话数据只是存储在文件系统上,并且可以由同一主机上的任何其他人读取,尽管他们不一定知道它是用于哪个站点.因此,在没有某种形式的加密的情况下,永远不要存储明文密码,信用卡号,广泛的个人详细信息或在会话数据中可能被视为敏感的任何内容,或者更好的是,只需在会话中存储密钥并存储实际的敏感内容数据库中的数据.
注意:以上内容并非PHP独有.
但那是服务器端加密.
现在您可以争辩说,使用一些额外数据加密会话将使其更安全,免遭劫持.一个常见的例子是用户的IP地址.问题是很多人在许多不同的地方使用相同的PC /笔记本电脑(例如Wifi热点,工作,家庭).此外,许多环境将使用各种IP地址作为源地址,尤其是在企业环境中.
您也可以使用用户代理,但这是可猜测的.
实际上,据我所知,根本没有使用cookie加密的真正原因.我从来没有想过有这个问题,但鉴于这个问题,我一直在寻求证明是对还是错.我找到了一些关于人们建议加密cookie数据的方法的线程,透明地使用Apache模块,等等,但这些似乎都是通过保护存储在cookie中的数据(这是你不应该做的)来实现的.
我还没有看到加密cookie的安全性论据,该cookie只代表会话密钥.
如果有人可以指出相反的事情,我将很高兴被证明是错误的.
安全警告:这两个功能不安全.他们使用的是ECB模式,无法验证密文.请参阅此答案以获得更好的前进方法.
对于想要在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');