16

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

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

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

数据是一个NSData使用“消息”的单词,dataUsingEncoding:NSASCIIStringEncoding Key是一个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 中的字节数组,它们与服务器上的字节数组相匹配。

4

5 回答 5

3

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

于 2009-10-28T18:07:09.917 回答
3

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

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

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

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

更新:我的答案是在 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 <= 16以前没有。

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

于 2011-10-25T15:54:36.827 回答
2

iPhone 使用 AES 的什么模式?你没有列出任何东西,所以也许这意味着它没有使用链接(ECB)。

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

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

于 2009-10-28T18:23:49.490 回答
0

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

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

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

于 2010-06-22T12:43:46.680 回答
0

根据您的示例,服务器做对了,而客户端做错了。

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

于 2009-10-29T13:11:14.177 回答