如何存储iv、salt和密文?
How to store iv, salt and cipher text?
从这个on how to achieve password based encryption可以看出,我需要保存salt、IV和密文以便稍后解密。
由此iv and salt can be stored along with cipher text
我以这种格式存储十六进制值
DatatypeConverter.printHexBinary(salt) + DatatypeConverter.printHexBinary(iv) + DatatypeConverter.printHexBinary(ciphertext);
我需要以二进制格式存储值吗?
DatatypeConverter.printBase64Binary(salt) + DatatypeConverter.printBase64Binary(iv) + DatatypeConverter.printBase64Binary(ciphertext));
输出清楚地表明 salt 和 iv 结束的位置,这很糟糕
lIvyAA/PZg4=fE4gTZUCPTrKQpUKo+Z1SA==4/gAdiOqyPOAzXR69i0wlC7YFn9/KOGitZqpOW2y3ms=
以十六进制格式存储会不会有数据丢失的影响?
IV的长度是固定的吗?在我的例子中,它总是 32 个字符(十六进制)
或者我什至还需要存储 IV 的长度?因为盐长度最初固定为 8 位(16 个十六进制字符)
(我使用 PBKDF2WithHmacSHA1 算法生成密钥,AES/CBC/PKCS5Padding 生成密码)
Base64 以 3 字节 的块编码为 4 base64 字符 。如果需要编码的字节数不是 3 的倍数,则最后一个块用一个或两个 =
填充,以指示该块不是完整的 3 个字节。
由于盐和 IV 都不需要保密,因此能够检测到它们开始或停止的位置确实没有任何问题。 base64 padding char =
不是问题——但你应该有办法将三个编码字符串分开。你可以例如只需用 :
.
分隔各个部分
IV 的大小与您的加密算法的块大小相同。在这种情况下,您使用 AES,其块大小为 128 位 ,即 16 字节 。如果十六进制编码,这将得到 32 字节,如果 base64 编码,这将得到 24 字节。 Salt 并没有真正的固定长度,将取决于您的实现。
我认为有必要再次强调一下上面提到的接受的答案。
也就是说,没有必要也没有必要试图隐藏盐或静脉注射液。您的密码术的安全性完全取决于密钥的保密性,并且仅取决于密钥的保密性。 IV 和盐可以与密文一起以明文形式分发,只要密钥保持秘密,密文就保持安全。
理解并接受这一点很重要,否则您会绕着轴转,试图混淆无关紧要的事情。默默无闻是没有安全感的。
然而,重要的是要注意,salt 应该在加密强度高的伪随机数生成器中生成。应该为每个正在加密的新纯文本生成一个新的盐。同样,应该为每个新密文随机生成 IV。
这些参数需要是独立的和不可预测的,但不需要是秘密的。
因此您可以将它们存储在单独的字段中或将它们分隔在单个字段中,或者对三个字段中的前两个字段使用固定长度。不过,为了获得最大的灵活性和未来验证,我建议使用分隔字段,并包括处理数据所需的所有参数。如果您使用 PBE,我也会包括算法名称和迭代次数,而不是依赖默认值。
从这个on how to achieve password based encryption可以看出,我需要保存salt、IV和密文以便稍后解密。
由此iv and salt can be stored along with cipher text
我以这种格式存储十六进制值
DatatypeConverter.printHexBinary(salt) + DatatypeConverter.printHexBinary(iv) + DatatypeConverter.printHexBinary(ciphertext);
我需要以二进制格式存储值吗?
DatatypeConverter.printBase64Binary(salt) + DatatypeConverter.printBase64Binary(iv) + DatatypeConverter.printBase64Binary(ciphertext));
输出清楚地表明 salt 和 iv 结束的位置,这很糟糕
lIvyAA/PZg4=fE4gTZUCPTrKQpUKo+Z1SA==4/gAdiOqyPOAzXR69i0wlC7YFn9/KOGitZqpOW2y3ms=
以十六进制格式存储会不会有数据丢失的影响?
IV的长度是固定的吗?在我的例子中,它总是 32 个字符(十六进制) 或者我什至还需要存储 IV 的长度?因为盐长度最初固定为 8 位(16 个十六进制字符)
(我使用 PBKDF2WithHmacSHA1 算法生成密钥,AES/CBC/PKCS5Padding 生成密码)
Base64 以 3 字节 的块编码为 4 base64 字符 。如果需要编码的字节数不是 3 的倍数,则最后一个块用一个或两个 =
填充,以指示该块不是完整的 3 个字节。
由于盐和 IV 都不需要保密,因此能够检测到它们开始或停止的位置确实没有任何问题。 base64 padding char =
不是问题——但你应该有办法将三个编码字符串分开。你可以例如只需用 :
.
IV 的大小与您的加密算法的块大小相同。在这种情况下,您使用 AES,其块大小为 128 位 ,即 16 字节 。如果十六进制编码,这将得到 32 字节,如果 base64 编码,这将得到 24 字节。 Salt 并没有真正的固定长度,将取决于您的实现。
我认为有必要再次强调一下上面提到的接受的答案。
也就是说,没有必要也没有必要试图隐藏盐或静脉注射液。您的密码术的安全性完全取决于密钥的保密性,并且仅取决于密钥的保密性。 IV 和盐可以与密文一起以明文形式分发,只要密钥保持秘密,密文就保持安全。
理解并接受这一点很重要,否则您会绕着轴转,试图混淆无关紧要的事情。默默无闻是没有安全感的。
然而,重要的是要注意,salt 应该在加密强度高的伪随机数生成器中生成。应该为每个正在加密的新纯文本生成一个新的盐。同样,应该为每个新密文随机生成 IV。
这些参数需要是独立的和不可预测的,但不需要是秘密的。
因此您可以将它们存储在单独的字段中或将它们分隔在单个字段中,或者对三个字段中的前两个字段使用固定长度。不过,为了获得最大的灵活性和未来验证,我建议使用分隔字段,并包括处理数据所需的所有参数。如果您使用 PBE,我也会包括算法名称和迭代次数,而不是依赖默认值。