当前位置: 首页 > 知识库问答 >
问题:

Java AES密码文本大小

慕容弘懿
2023-03-14

我用的是非常标准的Java AES加密/解密方式。

byte[] key = hexStringToByteArray("C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF");

byte[] message = hexStringToByteArray("01A0A1A2A3A4A5A6A703020100060001");

SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

// Instantiate the cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

byte[] encrypted = cipher.doFinal(message);

cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] original = cipher.doFinal(encrypted);

如你所见,我使用的是128位密钥和128位消息。我总是得到我期望的结果,然而,加密结果总是256位长。第二个128位总是一样的。除了截断结果,我如何确保密码只返回前128位,而不改变前128位?我觉得我有点混淆了这里块大小的定义

共有2个答案

呼延沈义
2023-03-14

您的密码实例正在使用PKCS5Padding填充,该填充在密文中总共添加了16个字节的填充。有几种方法可以纠正这一点:

选项1:不使用密码。getInstance(“AES”)使用填充,使用Cipher.getInstance(“AES/CBC/NoPadding”)。但是,不建议这样做,因为它要求明文是16字节的倍数。

选项 2:使用 BouncyCastle 作为您的加密提供商,然后使用

import org.bouncycastle.jce.provider.BouncyCastleProvider;
Cipher.getInstance("AES/CTR/NoPadding", new BouncyCastleProvider());

初始化密码。这使用计数器模式(CTR)而不是密码块链接模式(CBC ),并且计数器模式不需要任何填充。在计数器模式下,使用唯一的初始化向量是很重要的,它可以和密文一起以明文形式传输;举个例子,

byte[] IV = new byte[16];
new SecureRandom().getBytes(IV);
cipher.init(Cipher.ENCRYPT_MODE, key, IV);

然后在解密密文时,用相同的初始化向量初始化密文。这取决于你如何传递IV,但是再次强调,这不需要保密。

密码块链接模式的初始化向量也应该是唯一的,但这不像计数器模式那样关键。

苗盛
2023-03-14

在回答你的问题之前,有几件必须避免的事情。我在这段代码中看到的一件潜在危险的事情是,密码没有使用显式模式和填充指定。这意味着这取决于提供者的默认值。如果这是当前随Oracle JVM分发的提供程序,则默认值为ECBPKCS5Padding。如果这些是您想要使用的,请按以下方式指定它们:

 Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

第二个是ECB不是一个很好的使用模式选择,因为它不是很安全。CBC是一个更好的选择,因为它使用了初始化向量。

关于这个问题。加密文本大小的原因是填充方案,在本例中PKCS5。填充是必要的,以确保纯文本具有算法可以处理的长度。对于AES,它必须是16字节的倍数。在未加密数据的长度已经是16字节的倍数的情况下,填充必须添加额外的16字节(参见jbtule的注释)。像这样初始化密码会产生16字节的加密数据:

Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");

这要求未加密数据的长度已经是16字节的倍数,因为它根本不会填充它。如果不是,就会抛出异常。

确切地了解您要做什么以给出一个好的建议可能是有益的。

 类似资料:
  • 我有一个应用程序,需要在配置文件中存储一些秘密密码,如数据库和ftp密码/详细信息。我环顾四周,发现了许多使用AES的加密/解密解决方案,但我似乎不知道如何在不改变密钥的情况下使其工作。这意味着我可以加密和解密(使用相同的秘密密钥),但在重启等过程中保持持久性。我似乎无法让秘密钥匙保持不变。下面的示例显示了我的工作方法: 到目前为止还不错。然而,如果我运行它一次,我可能会得到'2Vhht/L80U

  • 以下示例有什么问题? 问题是解密字符串的第一部分是无意义的。不过,其余的都很好,我明白了...

  • 在下面的代码中(也在http://play.golang.org/p/77fRvrDa4A但是在浏览器中需要“太长的时间来处理”)124字节版本的sourceText不会加密,因为1024的“消息对于RSA公钥大小来说太长”。它和更长的124字节sourceText版本可使用2048位密钥大小。 我的问题是如何准确计算rsa中的密钥大小。GenerateKey给定源文本的字节长度?(一个小段落大小

  • 任务:凯撒算法(密码(c))通过按密钥(k)位置“旋转”每个字母来加密消息。 实现:ci=(pi k)mod26,其中ci是密码,pi是明文,k是密钥。 我的伪代码: 从命令行参数获取密钥 将键(k)转换为整数 提示用户输入纯文本(pi) 对于每个纯文本字符,保留大小写(使用C中的isalpha、isupper和islower函数)。 最后,按键移动明文字符,例如“回家!”——“Hp Ipnf!”

  • 问题内容: 我正在用Java实现与第三方应用程序的通信。作为登录过程的一部分,第三方应用程序正在发送一个加密的字符串,我必须对其进行解码并发回。我已经花了将近2天的时间进行糊涂和阅读文章,但是我找不到实现此目的的正确方法。 我有一个测试用例,其中加密的字符串为“ c1W2YO1vYQzu6czteEidrG0U4g5gT4h57vAlP7tdjcY =“,使用密码“ GAT”解密的字符串必须返回“