iPhone(Objective-C)和Java之间的AES差异

16

我已经整天都在苦苦寻找解决方法了...

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

客户端使用CommonCrypto库并使用以下设置...

数据是一个包含单词"message"的NSData,使用dataUsingEncoding:NSASCIIStringEncoding进行编码。 键是一个包含短语"1234567891123456"的NSData,同样使用上述编码。 算法为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客户端正在加密以下字符串“message” 它使用密钥“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可用,而且它们似乎是兼容的。 - Simon Lee
是的,PKCS7填充与PKCS5Padding相同。如果更改为ECB没有起作用,那么iPhone很可能正在使用CBC模式。您需要确定初始化向量并确保服务器正在使用相同的向量。 - erickson
谢谢回复。我在客户端和服务器上创建了相同的IV,但仍然无法工作。这就是为什么iPhone缺乏一款体面可靠的AES库的地方! :( - Simon Lee
1
你能否发布每个环境下的明文样本和结果密文的示例? - laz
你尝试过在客户端使用AES算法的其他变体吗?(即AES192,AES256) - GameFreak
好的,下面开始...iPhone客户端正在加密以下字符串“message”,它使用密钥“1234567891123456”,使用初始化向量“1010101010101010”,并使用AES128,CBC模式(据我所知),选项为kCCOptionsPKCS7Padding。加密结果(使用base64编码)为UHIYllDFAXl81ZM7OZPAuA==服务器正在使用相同的密钥和初始化向量对相同的字符串进行加密。它使用以下Cipher.getInstance("AES/CBC/PKCS5Padding")。加密结果(使用base64编码)为ALBnFIHysLbvAxjvtNo9vQ==谢谢。 - Simon Lee
5个回答

3

我刚刚遇到了完全相同的问题。我在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 <= 16 之前没有出现过。

如果您仍然遇到问题,那可能是其他原因造成的。


嗨,我遇到了同样的问题,你能分享一下示例代码吗?谢谢。 - Nitesh Meshram
@ylian:我也遇到了同样的问题,请分享你的代码。 - Jayprakash Dubey

3

虽然这不是我的专业领域,但看起来客户端使用的是PKCS7,而服务器使用的是PKCS5


根据wikipedia的说法,这些模式是可互换的。 - lupz

2
iPhone使用AES时采用哪种模式?您没有列出任何内容,因此可能意味着它未使用链接(ECB)。
然而,在Java端,您正在使用CBC,但没有指定初始化向量。这绝对是错误的。如果您确实使用CBC,则必须拥有在加密期间使用的IV。IV不是秘密的;它可以与密文一起发送。
如果您确实使用ECB,则没有IV,但是您的Java指定了错误的模式。

0

我最近在另一个项目中遇到了这个问题。问题是密钥比dataEncryptedUsingAlgorithm方法内的char缓冲区多一个字节。

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

在Xcode中进入该方法并查看您的密钥char [16]缓冲区的外观。它可能存在相同的问题,并具有以下内容:{ 0,'2','3','4',... }


0

根据您提供的样本,服务器端是正确的,而客户端则不是。

从数据来看,我猜测密钥可能是错误的。请向我们展示iPhone代码,特别是从“1234567891123456”转换为密钥的代码。


根据请求,已将其添加到原帖中。 - Simon Lee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接