【问题标题】:AES encryption for Android/Java and .Net only partially identicalAndroid/Java 和 .Net 的 AES 加密仅部分相同
【发布时间】:2013-10-12 08:09:30
【问题描述】:

我正在使用带有密码和初始化向量的 AES 加密对 .Net 和 Java(在 Android 上)中的字符串进行加密(以及稍后解密)。我在每一侧分别得到了各自的加密和解密运行良好,但相比之下我不断得到不同的结果,因此不允许在一个系统上加密并在另一个系统上解密。我特别不明白为什么加密字节数组的前半部分相同,而后半部分不同(而所有其他字节数组完全相同)?

这是我从我使用的两个加密代码中得到的字节数组:

Java(为了便于比较,在负数上添加了 +256):[202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33 , 151, 246, 70, 63, 184, 118, 228, 50, 242, 224, 231, 37, 34, 16, 123, 9, 143, 81] p>

.Net:[202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33, 151, 246, 109 , 127, 84, 129, 168, 106, 21, 159, 131, 67, 75, 209, 166, 221, 190, 243]

我在下面发布了我用于加密的两个代码片段。尽管我现在正在寻找关于我做错了几个小时的提示,但我无法弄清楚我错在哪里。如果有人能指出我没有看到的东西,那就太好了……

这是我从两个代码版本中打印出所有相关值时得到的结果:

Android-Output:
    Key (String): 6543210987654321
    IV (String): 1234567890123456
    Input (String): Encrypt_this_text

    Key (Bytes): [54, 53, 52, 51, 50, 49, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49]
    IV (Bytes): [49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54]
    Input (Bytes): [69, 110, 99, 114, 121, 112, 116, 95, 116, 104, 105, 115, 95, 116, 101, 120, 116]

    Encrypted: [-54, -109, -108, -88, 9, 104, -43, -80, -82, -99, 124, -96, 54, 33, -105, -10, 70, 63, -72, 118, -28, 50, -14, -32, -25, 37, 34, 16, 123, 9, -113, 81]
    Encrypted (+256 if <0): [202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33, 151, 246, 70, 63, 184, 118, 228, 50, 242, 224, 231, 37, 34, 16, 123, 9, 143, 81]

VBNet-Output:
    Key (String)=6543210987654321
    IV (String)=1234567890123456
    Input (String)=Encrypt_this_text

    Key (Byte)=[54, 53, 52, 51, 50, 49, 48, 57, 56, 55, 54, 53, 52, 51, 50, 49]
    IV (Byte)=[49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54]
    Input (Byte)=[69, 110, 99, 114, 121, 112, 116, 95, 116, 104, 105, 115, 95, 116, 101, 120, 116]

    Encrypted=[202, 147, 148, 168, 9, 104, 213, 176, 174, 157, 124, 160, 54, 33, 151, 246, 109, 127, 84, 129, 168, 106, 21, 159, 131, 67, 75, 209, 166, 221, 190, 243]

这是用于生成加密字节数组的java代码:

String skey = "6543210987654321";
String siv = "1234567890123456";
String sinput = "Encrypt_this_text";

byte[] key = skey.getBytes("UTF8");
byte[] iv = siv.getBytes("UTF8");
byte[] input = sinput.getBytes("UTF8");

Cipher cipher = Cipher.getInstance("AES/CBC/ZeroBytePadding");
SecretKeySpec keyspec = new SecretKeySpec(key, "AES" );
IvParameterSpec ivparams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivparams);

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

...这是我的网络(在本例中为 VB)测试代码:

Dim rm As New System.Security.Cryptography.AesManaged

Dim skey As String = "6543210987654321"
Dim siv As String = "1234567890123456"
Dim sinput As String = "Encrypt_this_text"

Dim key() As Byte = System.Text.Encoding.ASCII.GetBytes(skey)
Dim IV() As Byte = System.Text.Encoding.ASCII.GetBytes(siv)
Dim input() As Byte = System.Text.Encoding.ASCII.GetBytes(sinput)

Dim ict As System.Security.Cryptography.ICryptoTransform = rm.CreateEncryptor(key, IV)

Dim encrypted() As Byte = ict.TransformFinalBlock(input, 0, input.Length)

【问题讨论】:

  • 注意:1) 对明文使用 ASCII 编码会默默地破坏外来字符。请改用 UTF-8。 2) IV 和 key 不应使用 ASCII(或 UTF-8)。它们是随机的二进制值,因此如果必须将它们转换为文本,请使用 Hex 或 Base64。 3)您必须为每条消息生成一个新的随机IV 4)为了抵抗主动攻击,您需要应用MAC。使用先加密后 MAC 方案。确保包含整个密文,包括 MAC 中的 IV。并使用恒定时间比较进行 MAC 验证。或者,您可以选择像 GCM 这样的身份验证模式,而不是自己编写它

标签: c# java android vb.net encryption


【解决方案1】:

这是由于 .NET 的 AesManaged.CreateEncryptor 中的默认填充是 PKCS7。

在 Java 中,您使用零填充进行初始化。

您可以通过将 rm 中的 Padding 属性更改为 PaddingMode.Zeros 来覆盖填充。

相关 MSDN 文章:MSDN

【讨论】:

  • 我会反其道而行之,将两者都更改为 PKCS7。您不能删除 Zeros 填充,除非您知道消息不以零字节结尾。
  • 谢谢,我自己永远不会得到这个:我以为我在某处读到网络标准默认是零填充,这就是我故意在 java 中使用零填充的原因.. . 所以,当然,它适用于您的提示(在 VBNet 中添加 rm.Padding = Security.Cryptography.PaddingMode.Zeros),反之则使用 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING");在 Java 中。
  • 我支持 CodesInChaos 的评论 - PKCS7 更适合大多数用途。
猜你喜欢
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
  • 2017-05-31
  • 2018-11-28
  • 2012-12-30
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
相关资源
最近更新 更多