How to calculate the maximum length of the output of the Laravel encryption method?
设置
给出以下内容:
1 |
对于长度为1的字符串是否可以知道
语境
数据库存储-需要存储加密的值,并希望设置输入字符串的验证,因此最长长度的输入字符串在加密后可以不截断地插入db中。
基本测试
使用以下代码片段在本地运行一些非常原始的测试:
1 2 3 4 5 6 7 8 9 10 | Route::get('/test', function() { echo '<table>'; for ($i=0; $i < 100; $i++) { $s = str_repeat('a', $i); $l1 = strlen($s); $l2 = strlen(Crypt::encryptString($s)); echo"<tr><td>$l1</td><td>$l2</td></tr>"; } echo '</table>'; }); |
我可以看到以下内容,但是在运行之间会有所不同,例如,字符串" a"的长度将为188或192(较长的值似乎在244和248之间)。
因此必须有一个公式。我已经看到了
输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 0 192 1 188 2 188 3 192 4 188 5 188 6 188 7 192 8 192 9 188 10 188 11 192 12 192 13 192 14 192 15 192 16 220 17 220 18 216 19 216 20 220 |
编辑
好吧,所以在与下面的@Luke Joshua Park聊天之后,长度的差异来自laravel加密功能以及创建
加密方法内的
当包含
真正的问题-
The real problem - can $iv and $value contain more than a single '/'?
好的。 IV的最坏情况是IV
21个正斜杠*每个额外的3个字节= 63个额外的字节。
对于HMAC-SHA-2-256,您可以获得32个字节的0xFF(最坏的情况),在base64中为
42个正斜杠=> 126个额外字节。
对于密文,再次,整个输出可能是(但可能不是)
最大值的广义公式似乎是
- IV:24 63 = 87
- HMAC:24 63 = 87
- JSON属性名称:10
- JSON结构:19
-
密文:
ceil(ceil((n+1) / 16) * 16 / 3) * 4 * 4 (我用n 作为字节。填充的密文是ceil((n 1)/块大小)*块大小,base64是4 * ceil(数据/ 3),多余的* 4是"一切都是斜杠") - 再次使用Base64:4 * ceil(sum / 3)
=
对于产生400字节的
浏览
1 | {"iv":"<128 bits in base64>","value":"<x bits in base64>","mac":"<256 bits in hex>" } |
其中
这意味着对于长度为1的输入纯文本,输出的大小应为:
- IV(base64)的24个字符。
- 密文(base64)的24个字符。
- SHA256 mac(十六进制)为64个字符。
- JSON字段名称的10个字符。
-
19个额外的JSON字符,例如
{ ," ,: 。 -
整个过程的最后一轮base64编码...(
ceil(141 / 3) * 4 )
总共给出188。最大波动是192,这是奇怪的-输入的大小完全没有变化(因为纯文本应始终为16字节,介于0到15之间)。
请注意,我将向@Luke Joshua Park颁发赏金,因为他让我最接近最终成为(最接近a)解决方案的方法。
(不是)解决方案
答案是,没有具体的答案,不是没有未知数和方差。在撰写本文时,三个人(我自己,Luke和bartonjs)都在关注这一点,但对于100%准确的解决方案仍然存在疑问。
提出这个问题是为了找出一种可靠的类型和大小来存储加密数据,理想情况下以数据库独立的方式进行(我不想指定特定的数据库,因为我想知道和理解如何计算长度,而不管其保留方式如何)。
但是,在最坏的情况下,即使是最小长度的字符串也很长(创建包含许多斜杠的随机$ iv -不可能或不可能)。
那么...该怎么办?
因此,无论原始字符串的长度如何,将加密数据存储为文本字段而不是varchar(在mysql land中)似乎是最好,最一致和最可靠的。这是一个令人失望的无聊答案,没有花哨的数学运算。这不是我想接受的答案,但是最有意义。
但是,密码呢?
在短暂的愚蠢时刻,我想,但是密码字段呢?那是一个