首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Laravel 4加密:预期的字符数

Laravel 4加密:预期的字符数
EN

Stack Overflow用户
提问于 2015-01-16 19:50:47
回答 2查看 2.3K关注 0票数 2

我刚刚遇到了一个有趣的小问题。

使用Laravel 4,我对一些条目进行加密,然后将它们添加到db中,包括电子邮件地址。

数据库是在默认varchar长度为255的情况下设置的。

我刚刚有一个条目被加密为309个字符,通过切断数据库中的50多个字符来破坏加密。

我已经(暂时)修正了这个问题,只需将varchar长度增加到500个,从理论上讲,这应该可以覆盖我,但我想确定一下。

我不知道加密是如何工作的,但是为了设置我的数据库,是否有一种方法可以从加密输出中判断出最大字符长度?

我是否应该将字段类型从varchar更改为其他类型,以确保不再发生这种情况?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-17 13:25:51

结论

首先,请注意,在4.0.0到4.2.16之间(这似乎是最新的版本)发生了相当多的变化。

该方案以42个字符188个字符的惊人开销开始,4.0大约244个字符(考虑到我没有忘记任何新行等等)。因此,为了安全起见,如果明文中的字符编码为单个字节,则可能需要200个字符( 4.2 )和256个字符( 4.0 )加上1.8倍的纯文本大小。

分析

我只是研究了有关这个函数的Laravel 4.0的源代码Laravel 4.2。让我们先进入大小:

  1. 数据是序列化的,因此加密大小取决于值的类型(可能是字符串)的大小;
  2. 序列化的数据是使用Rijndael 256或AES填充的,因此这意味着添加1至32字节或1至16字节--这取决于4.0或4.2的使用;
  3. 该数据用密钥和IV加密;
  4. 密文和IV分别转换为base64;
  5. 计算在base64编码的密文上使用SHA-256的HMAC,返回64个字节的小写十六进制字符串。
  6. 然后,密文由base64_encode(json_encode(compact('iv', 'value', 'mac')))组成(当然,其中的值是基本的64密文,mac是HMAC值)。

s::"";中的一个字符串,其中<i>是字符串的大小,<s>是字符串(我在这里假定platform编码的大小)。请注意,我不能100%确定Laravel没有使用任何环绕字符串值的方法,也许有人可以帮我清除掉。

计算

总之,所有的事情都非常依赖于字符编码,对我来说做一个很好的估计是相当危险的。现在假设字节和字符之间存在1:1的关系(例如US):

  1. 序列化可将字符串的9个字符累加到999个字符。
  2. 填充最多可达16或32个字节,我们假定这些字节也是字符。
  3. 加密使数据保持相同大小。
  4. PHP中的base64创建了ceil(len / 3) * 4字符,但是让我们简化一下,对于(len * 4) / 3 + 4来说,64编码的基本IV是44个字符。
  5. 完整的HMAC是64个字符
  6. JSON编码增加了引号和冒号的3个*5个字符,加上大括号和逗号周围的4个字符,总计19个字符(假设json_encode在这里不以空格结尾,基数64再次增加相同的开销)

好的,我在这里有点累了,但是您可以看到它至少两次用base64编码扩展明文。最后,这是一个增加了相当多开销的方案;他们本可以使用base64(IV|ciphertext|mac)来大幅降低开销。

备注

  • 如果您现在没有使用4.2,我会认真考虑升级到最新版本,因为4.2修复了很多安全问题
  • 示例代码使用字符串作为键,并且不清楚是否容易使用字节;
  • 文档确实警告除了Rijndael默认值以外的键大小,但忘记提到字符串编码问题;
  • 填充总是被执行,即使使用CTR模式,哪种类型会违背目的;
  • Laravel使用PKCS#7填充,但是由于序列化总是以;结束,所以这并不是必要的;
  • 看到验证加密被用于数据库加密是件好事( IV没有被使用,固定在4.2中)。
票数 6
EN

Stack Overflow用户

发布于 2015-01-16 20:39:35

@MaartenBodewes‘在解释实际字符串的长度方面做得很好。然而,你永远不可能知道它是肯定的,所以这里有两个选项来处理这种情况。

1.将字段设置为text

将字段从有限的varchar更改为“自扩展”text。这可能是更简单的一个,特别是如果您期望相当长的输入,我肯定会推荐这一点。

2.让你的varchar更长

正如您已经做的那样,根据您期望/允许的输入长度,使您的varchar更长。我会乘以5倍。

但别到此为止!在代码中添加检查以确保数据不被截断:

代码语言:javascript
运行
复制
$encrypted = Crypt::encrypt($input);
if(strlen($encrypted) > 500){
   // do something about it
}

你能做些什么

您可以将错误写入日志并添加加密数据(这样您可以在扩展DB字段的长度之后手动重新插入数据)。

代码语言:javascript
运行
复制
Log::error('An encrypted value was too long for the DB field xy. Length: '.strlen($encrypted).' Data: '.$encrypted);

显然,这意味着您必须频繁地检查日志(或通过邮件将它们发送给您),而且由于DB中的数据不正确,用户在使用应用程序时可能会遇到错误。

另一种方法是抛出一个异常(并向用户显示一个错误),当然还将其写入日志,这样您就可以修复它.

不管怎样,

无论您选择选项1还是选项2,您都应该始终限制输入字段的可接受长度。服务器端和客户端。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27991717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档