使用空字符串作为SecretKeySpec

时间:2018-04-02 14:00:07

标签: android cryptography aes

所以我的问题直截了当 有人可以使用空字符串作为带有AES的SecretKeySpec

String a = "";
Key secretKeySpec = new SecretKeySpec(a.getBytes("UTF8"), "AES");

然后用它来加密字符串

String str = "String that needs encoding";
byte[] bytes = str.getBytes("UTF8");
Cipher instance = Cipher.getInstance("AES/ECB/PKCS7Padding");
instance.init(1, secretKeySpec);
byte[] b = new byte[instance.getBlockSize()];
instance.doFinal(b, instance.update(bytes, 0, bytes.length, b, 0));
String str2 = new String(Base64.encode(b));

这只是整个代码的片段

2 个答案:

答案 0 :(得分:1)

这不会起作用,因为AES的密钥大小固定为16字节(128位),24字节(192位)或32字节(256位)。

空的SecretKeySpec意味着你正在使用长度为0的密钥。我认为这将最终出现在以下异常中:

java.lang.IllegalArgumentException: Empty key

BTW:你的代码很奇怪,因为它会对数据进行部分加密两次:

instance.doFinal(b, instance.update(bytes, 0, bytes.length, b, 0));

首先instance.update将内容从bytes加密到b。然后instance.doFinal再次加密b的内容。

答案 1 :(得分:0)

任何字符串都不应该直接用作键,所以对我来说这个问题毫无意义。如果要从密码短语生成密钥,则应使用密码哈希,例如PBKDF2,bcrypt,scrypt或Argon2。

对称密钥由多个位组成,通常是字节或八位字节。对于对手来说,这些字节应该是完全随机的。如果它们不存在那么你将无法实现对称密码所承诺的安全性。

您可以将密钥存储为十六进制或基本64.但是不建议这样做,因为对于许多托管语言(如Java),字符串通常永久保存在内存中。如果一个密钥(最初)由字节组成,那么这些字节应该在不再需要时立即清除。

请注意,对于需要密码的95%的情况,ECB不是安全操作模式。而是使用安全的操作模式,例如GCM,并为密文添加唯一或安全的随机(12字节)IV。

这取决于加密函数实现接受哪种密钥,即使它们没有意义(毕竟你期望至少128位的随机性)。例如,HMAC身份验证 - 不是密码 - 接受任何大小的密钥。但是,Java实现似乎需要SecretKeySpec至少一个字节。

总而言之,我想空的字符串就在那里让你填写。