iPhone(Objective-c)和Java之间的AES区别

Posted

技术标签:

【中文标题】iPhone(Objective-c)和Java之间的AES区别【英文标题】:AES difference between iPhone (Objective-c) and Java 【发布时间】:2010-12-10 23:19:20 【问题描述】:

我整天都在扯头发试图解决这个问题......

我有一个在 iPhone 上运行的 Objective-c 客户端,连接到 Java 服务器。 iPhone 正在使用 AES 加密数据,但我无法在服务器上对其进行解密。我正在使用已知的密码和消息(单个字符串)并在 iPhone 上生成字节数组,在 Java 服务器上使用相同的键和消息生成比较字节数组,但字节数组完全不同(因此不能在 Java 端进行解码)。

客户端正在使用具有以下设置的 CommonCrypto 库...

Data 是一个 NSData,其中包含使用 dataUsingEncoding:NSASCIIStringEncoding 的单词“消息” 密钥是NSData,再次使用上述编码保存短语“1234567891123456”。 算法是kCCAlgorithmAES128 选项是kCCOptionsPKCS7Padding(我认为这相当于服务器上的ECB?!)

服务器正在使用以下代码...

byte[] key = "1234567891123456".getBytes();
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");

SecretKeySpec k =  new SecretKeySpec(key, "AES");
c.init(Cipher.ENCRYPT_MODE, k);
byte[] encryptedData = c.doFinal("message".getBytes());

但是 encryptedData 中的数据与 Objective-c 代码中生成的数据不匹配,字节数组完全不同。

谁能看出我做错了什么?我认为设置都是一样的... :(

更新 - 根据要求....

好吧,就这样吧……

iPhone 客户端正在加密以下字符串“消息” 它使用密钥“1234567891123456” 它使用“1010101010101010”的初始化向量 它使用 AES128,具有 CBC 模式(据我所知)和 kCCOptionsPKCS7Padding 选项。

加密(base64编码)的结果是UHIYllDFAXl81ZM7OZPAuA==

服务器使用相同的密钥和初始化向量加密相同的字符串。 它使用以下 Cipher.getInstance("AES/CBC/PKCS5Padding");

加密(base64编码)的结果是ALBnFIHysLbvAxjvtNo9vQ==

谢谢。

更新 2 - 根据要求...

这是 iPhone 代码....

NSData *toencrypt = [@"message" dataUsingEncoding:NSASCIIStringEncoding];

NSData *pass = [@"1234567891123456" dataUsingEncoding:NSASCIIStringEncoding];

NSData *iv = [@"1010101010101010" dataUsingEncoding:NSASCIIStringEncoding];    

CCCryptorStatus status = kCCSuccess;

NSData *encrypted = [toencrypt dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status];

NSString *text = [NSString base64StringFromData:encrypted length:[encrypted length]];

用于加密的 NSData 类别来自这里...

http://github.com/AlanQuatermain/aqtoolkit/tree/master/CommonCrypto/

顺便说一句,我检查了 toencrypt、pass 和 iv 中的字节数组,它们与服务器上的匹配。

【问题讨论】:

我已将服务器更改为按照建议使用 ECB,但仍然无法正常工作。顺便说一句,我确实注意到服务器使用 PKCS5 和客户端使用 PKCS7,但是客户端上没有 5 可用,服务器上没有 7 可用,显然它们无论如何都是兼容的。 是的,PKCS7 填充与 PKCS5Padding 相同。如果更改为 ECB 不起作用,则 iPhone 可能正在使用 CBC 模式。您需要确定初始化向量并确保服务器使用的是相同的。 感谢您的回复。我在客户端和服务器上创建了一个相同的 IV,但仍然无法正常工作。这就是严重缺乏适用于 iPhone 的体面且可靠的 AES 库的地方! :( 您能否发布一个纯文本示例以及每个环境中生成的密文? 您是否尝试过在客户端使用 AES 算法的其他变体? (即 AES192、AES256) 【参考方案1】:

这不是我的区域,但看起来在客户端上你有PKCS7,但在服务器上你有PKCS5

【讨论】:

从wikipedia 开始,这些模式是可以互换的。【参考方案2】:

我刚刚遇到了完全相同的问题。我在 ios 客户端上使用 CommonCrypto,使用设置:

NSData * encrypted = [data dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status];

服务器使用Cipher.getInstance("AES/CBC/PKCS5Padding");,其密钥和初始化向量与客户端相同。

在最后几个小时撞墙之后,我终于按照 Jason 的建议检查了 dataEncryptedUsingAlgorithm 例程并在 FixKeyLengths 之后打印出 keyData。原来我的 128 位密钥扩展为 192 位,并在末尾添加了 0。修复此问题后,一切正常。 :)

更新:我的答案是在 2 年前发布的,这个问题似乎在最新的NSData+CommonCrypto 代码中得到了修复。具体来说,这是导致问题的部分:

static void FixKeyLengths( CCAlgorithm algorithm, NSMutableData * keyData, NSMutableData * ivData )

  NSUInteger keyLength = [keyData length];
  switch ( algorithm )
  
    case kCCAlgorithmAES128:
    
      if ( keyLength <= 16 )
      
        [keyData setLength: 16];
      
      else if ( keyLength <= 24 )
      
        [keyData setLength: 24];
      
      else
      
        [keyData setLength: 32];
      

      break;
    

第一次检查 keyLength &lt;= 16 以前不存在。

如果您现在仍然遇到问题,那可能是其他问题。

【讨论】:

您好,我也遇到同样的问题,能否分享示例代码。谢谢。 @ylian :我面临同样的问题。请分享您的代码。【参考方案3】:

iPhone 使用 AES 的什么模式?您没有列出任何内容,所以这可能意味着它没有使用链接 (ECB)。

但是,在 Java 端,您使用的是 CBC,但没有指定初始化向量。那绝对是错误的。如果您真的在使用 CBC,您必须拥有在加密期间使用的 IV。 IV 不是秘密。可以和密文一起发送。

如果你真的使用ECB,没有IV,但是你的Java指定了错误的模式。

【讨论】:

【参考方案4】:

根据您的示例,服务器运行正常,而客户端运行不正常。

看数据,我猜是key错了。请向我们展示 iPhone 代码,尤其是从“1234567891123456”到您的密钥的代码。

【讨论】:

按要求添加到原帖中。【参考方案5】:

我最近在另一个项目中遇到了这个问题。问题是密钥太长了一个字节,无法放入dataEncryptedUsingAlgorithm 方法内的char 缓冲区。

问题在于NSString 上的getBytes 方法是软失败的。它将大部分字符串复制到缓冲区中,但由于密钥太长一个字节,它会通过将第一个字符设置为 NUL(字符 0)将操作“标记”为失败。

进入 Xcode 中的那个方法,看看你的键 char[16] 缓冲区是什么样子的。它可能有同样的问题,并且有 0, '2', '3', '4', ... 的内容。

【讨论】:

以上是关于iPhone(Objective-c)和Java之间的AES区别的主要内容,如果未能解决你的问题,请参考以下文章

如何将 int 从 iPhone 发送到 Apple Watch 标签(objective-c)

使用 Objective-C - iPhone 设置代理用户名和密码

iPhone 上的 Objective-C - NSOperationQueue 和 NSInvocationOperation 的使用

Objective-c用iphone 4s插入数据

iPhone - SBJsonParser 的另一个 Objective-C 内存泄漏

如何用 Objective-C 判断 iPhone 是不是连接到 wifi 网络?