我试图通过使用AES-256-CBC的Laravel(5.3)加密方法加密敏感用户信息。加密数据后,我想将它存储在我的MySQL数据库中,但我不知道应该将它保存为什么类型,也不知道它的长度。
感谢任何帮助。
答案 0 :(得分:1)
你将它保存为(加密)文本,所以...... 你应该使用longtext / blob作为mysql中的字段类型
在laravel迁移中它将是
$table->binary('data');
或
$table->longText('description');
答案 1 :(得分:1)
Laravel的encrypt方法将返回一个字符串,因此数据类型应该是varchar或文本变体,具体取决于要加密的数据的大小。
要确定大致尺寸,您可以使用以下一系列计算:
让a
=未加密数据的大小
设b
= a + 10
(为序列化添加近似填充)
设c
= b + 16 - (b MOD 16)
(计算加密数据的大小)
设d
= (c + 2 - ((c + 2) MOD 3)) / 3 * 4
(计算base64编码数据的大小)
让e
= d + 118
(为额外的有效负载添加绒毛)
设f
= (e + 2 - ((e + 2) MOD 3)) / 3 * 4
(计算base64编码数据的大小)
例如,如果您要加密9位社会安全号码,结果大约是216个字符的字符串。
详细,令人困惑的信息:加密方法返回的值不仅仅是加密文本,而且是json编码的有效负载数组的base64编码表示,其中包含序列化数据的base64编码加密值,base64编码的初始化向量(IV)和消息认证码(MAC)。因此,要确定所需字段的大小,您需要知道将要编码的数据的最大大小,然后为返回字符串中填充的这些额外信息添加一些额外的空间。
首先,让我们计算加密值的最大大小。由于您的加密算法(AES-256-CBC)是分组密码,因此使用公式很容易实现。 AES使用16字节块并且至少需要一个填充字节,因此加密值的大小将是16的下一个倍数。因此,如果原始数据是30字节,则加密数据将是32字节。如果原始数据是32字节,则加密数据将为48字节(因为AES需要至少一个填充字节,32字节变为33,然后上升到下一个16到48的倍数)。其公式为x + 16 - (x MOD 16)
。因此,对于30个字节,您将获得30 + 16 - (30 MOD 16) = 32
。
计算加密值的大小时,请记住首先序列化加密的数据。因此,例如,如果要加密社会保险号,则普通值仅为9个字符,但序列化值实际上为16个字符(s:9:"xxxxxxxxx";
)。由于序列化值是实际加密的值,并且是16字节,因此加密值的大小将为32字节(16 + 16 - (16 MOD 16) = 32
)。
除此之外,openssl_encrypt
函数还返回已经base64编码的加密数据。 Base64编码将值的大小增加大约4/3。对于原始数据中的每3个字节,base64编码将生成4字节(字符)表示。因此,对于SSN示例,加密结果为32个字节。转换为base64时,32个字节为我们提供(32 / 3) = 10.6
个3字节段。由于base64填充到下一个字节,取上限,然后乘以4,得到11 * 4 = 44
个字节。因此,我们原来的32字节加密值变为44个字符的字符串。如果您需要一个公式,可以使用(x + 2 - ((x + 2) MOD 3)) / 3 * 4
。所以,(32 + 2 - ((32 + 2) MOD 3)) / 3 * 4 = 44
。
下一条信息是MAC。 MAC是SHA256散列值,因此我们知道它将是64个字符。
最后一条信息是IV。普通IV是16个随机字节。存储在有效载荷数组中的IV是普通IV的base64编码值。因此,我们可以使用上面的公式来计算base64编码的IV的大小:(16 + 2 - ((16 + 2) MOD 3)) / 3 * 4 = 24
。
将这三条信息压缩成一个数组,然后json_encoded。由于json表示和数组中值的名称,这会增加另外大约30个字节(加或减,具体取决于在base64编码数据中转义正斜杠所需的任何额外反斜杠)。
最后,这个json_encoded值是base64_encoded,这将再次将大小增加大约4/3。
所以,要把这一切放在一起,让我们再想象你正在加密一个社会安全号码。 openssl_encrypt
结果为44个字符,MAC为64个字符,IV为24个字符,json表示添加另外约30个字符。这给了我们(44 + 64 + 24 + 30 = 162
)个字符。这个结果得到base64编码,这给了我们((162 + 2 - ((162 + 2) MOD 3)) / 3 * 4 = 216
)个字符。