【问题标题】:AES128 CBC encryption in Java and Objective C giving different outputsJava和Objective C中的AES128 CBC加密提供不同的输出
【发布时间】:2017-07-10 01:24:42
【问题描述】:

我的 java 和 Objective c 加密方法产生不同的输出 - AES128、CBC 模式。

键:YnA+lracf9xaiJO1oA/bTQ==
iV:190Dt3MNeL32o9Kd37HZlQ==
纯文本:text to encrypt

Java 输出:mHZpz52LOK2K76t3B/EUuA==
Obj C 输出:Fb0D46H4tN+ukgI05x/Dbg==

Java 代码:

public static String AESEncrypt(String text, String key, String iv) throws Exception {
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
     byte[] keyBytes = new byte[16];
     byte[] b = key.getBytes("UTF-8");
     int len = b.length;
     if (len > keyBytes.length)
         len = keyBytes.length;
     System.arraycopy(b, 0, keyBytes, 0, len);

     byte[] keyBytesiv = new byte[16];
     byte[] biv = iv.getBytes("UTF-8");
     int leniv = biv.length;
     if (leniv > keyBytesiv.length)
         leniv = keyBytesiv.length;
     System.arraycopy(biv, 0, keyBytes, 0, len);
     SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
     IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv);

     cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

     byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
     BASE64Encoder encoder = new BASE64Encoder();
     return encoder.encode(results);
 }

目标 C 代码

+ (NSData *)AESOperation:(CCOperation)operation OnData:(NSData *)data key:(NSData *)key iV:(NSData *) iv {

  NSUInteger dataLength = [data length];
  size_t bufferSize = dataLength + kCCBlockSizeAES128;
  void *buffer = malloc(bufferSize);

  size_t numBytesEncrypted = 0;
  CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                      kCCAlgorithmAES128,
                                      kCCOptionPKCS7Padding,
                                      [key bytes],
                                      kCCBlockSizeAES128,
                                      [iv bytes],
                                      [data bytes],
                                      dataLength,
                                      buffer,
                                      bufferSize,
                                      &numBytesEncrypted);
  if (cryptStatus == kCCSuccess) {
     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
  }

  free(buffer);
  return nil;
}

【问题讨论】:

  • 你需要对key和iv进行base64解码,还要检查你的arraycopys,第二个有bug。
  • IV 必须是不可预测的(阅读:随机)。不要使用静态 IV,因为这会使密码具有确定性,因此在语义上不安全。观察密文的攻击者可以确定之前发送相同消息前缀的时间。 IV 不是秘密,因此您可以将其与密文一起发送。通常,它只是简单地添加到密文中,并在解密之前被切掉。
  • 最好对您的密文进行身份验证,这样就不会像padding oracle attack 这样的攻击。这可以通过 GCM 或 EAX 等经过身份验证的模式或encrypt-then-MAC 方案来完成。
  • 你在 Objective-c 中使用了什么?任何 3rd 方 sdk 或库?

标签: java objective-c encryption base64 aes


【解决方案1】:

有两种解决此类问题的方法,可以组合使用:

  • 作为健全性检查,尝试解密加密文本并查看它是否与两种语言的原始文本匹配。

  • 尝试使用另一个库(第三个)并与前两个值进行比较。

所以我尝试使用在线工具解密密文,并且可以使用 Objective C 输出恢复原始文本(“要加密的文本”)。它表明 Java 代码有问题。我怀疑这可能与输入 (key, iv) 是 base64 编码的事实有关,而它似乎被简单地视为 UTF-8 编码(getBytes() 调用)。

【讨论】:

    【解决方案2】:

    感谢上面的建议,我能够解决 java 代码上的问题。这是我在 java 和 Objective c 上实现 AES128 CBC 模式的 Java 代码

    public static String AESEncrypt(String text, String key, String iv) throws Exception {
    
         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
         byte[] keyBytes = new byte[16];
         byte[] b = new BASE64Decoder().decodeBuffer(key);
         int len = b.length;
         if (len > keyBytes.length)
             len = keyBytes.length;
         System.arraycopy(b, 0, keyBytes, 0, len);
    
         byte[] keyBytesiv = new byte[16];
         byte[] biv = new BASE64Decoder().decodeBuffer(iv);
         int leniv = biv.length;
         if (leniv > keyBytesiv.length)
             leniv = keyBytesiv.length;
         System.arraycopy(biv, 0, keyBytesiv, 0, len);
    
         SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
         IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv);
    
         cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
    
         byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
         BASE64Encoder encoder = new BASE64Encoder();
         return encoder.encode(results);
     }
    

    【讨论】:

    • 你能帮我在这段代码中获取BASE64Decoder和BASE64Encoder吗?或者我应该为这个功能使用任何特定的库?
    猜你喜欢
    • 2020-03-29
    • 2014-07-07
    • 2014-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    相关资源
    最近更新 更多