iPhone (Objective-c) 和 Java 之间的 AES 区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1638971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AES difference between iPhone (Objective-c) and Java
提问by Simon Lee
I have been tearing my hair out all day trying to solve this...
我整天都在扯头发试图解决这个问题......
I have an objective-c client running on the iPhone, connecting to a Java server. The iPhone is encrypting data using AES but I cannot decrypt it on the server. I am using a known passphrase and message (single string) and am generating the byte array on the iPhone, generating a comparison byte array on the Java server using the same key and message but the byte arrays are completely different (and hence can't be decoded on the Java side).
我有一个在 iPhone 上运行的 Objective-c 客户端,连接到 Java 服务器。iPhone 正在使用 AES 加密数据,但我无法在服务器上对其进行解密。我正在使用已知的密码和消息(单个字符串)并在 iPhone 上生成字节数组,在 Java 服务器上使用相同的密钥和消息生成一个比较字节数组,但字节数组完全不同(因此不能在 Java 端解码)。
The client is using the CommonCrypto library with the following settings...
客户端正在使用具有以下设置的 CommonCrypto 库...
Data is an NSDataholding the word "message" using dataUsingEncoding:NSASCIIStringEncodingKey is an NSDataholding the phrase "1234567891123456" again using the encoding as above.
Algorithm is kCCAlgorithmAES128Options is kCCOptionsPKCS7Padding(which I believe equates to ECB on the server?!)
Data 是NSData使用dataUsingEncoding:NSASCIIStringEncodingKey保存单词“message”NSData使用上述编码再次保存短语“1234567891123456”。算法是kCCAlgorithmAES128选项是kCCOptionsPKCS7Padding(我认为这等同于服务器上的 ECB?!)
The server is using the following code...
服务器正在使用以下代码...
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());
BUT the data in encryptedData does not match that which is being generated in the objective-c code, the byte arrays are completely different.
但是 encryptedData 中的数据与 Objective-c 代码中生成的数据不匹配,字节数组完全不同。
Can anyone see anything obvious I am doing wrong? I thinkthe settings are all the same... :(
谁能看出我做错了什么?我认为设置都是一样的...... :(
- UPDATE - As requested....
- 更新 - 根据要求....
Ok so here goes....
好的,这里是......
iPhone client is encrypting the following string "message" It uses the key "1234567891123456" It uses an initialisation vector of "1010101010101010" It is using AES128, with CBC mode (as far as I can tell) and options of kCCOptionsPKCS7Padding.
iPhone 客户端正在加密以下字符串“message” 它使用密钥“1234567891123456” 它使用“1010101010101010”的初始化向量 它使用 AES128,具有 CBC 模式(据我所知)和 kCCOptionsPKCS7Padding 选项。
The result of the encryption (with base64 encoding) is UHIYllDFAXl81ZM7OZPAuA==
加密的结果(使用base64编码)是UHIYllDFAXl81ZM7OZPAuA==
The server is encrypting the same string, with the same key and initialisation vector. It is using the following Cipher.getInstance("AES/CBC/PKCS5Padding");
服务器使用相同的密钥和初始化向量加密相同的字符串。它使用以下 Cipher.getInstance("AES/CBC/PKCS5Padding");
The result of the encryption (with base64 encoding) is ALBnFIHysLbvAxjvtNo9vQ==
加密的结果(使用 base64 编码)是 ALBnFIHysLbvAxjvtNo9vQ==
Thanks.
谢谢。
- UPDATE 2 - As requested...
- 更新 2 - 根据要求...
Here is the iPhone code....
这是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]];
The NSData category for encrypting comes from here...
用于加密的 NSData 类别来自这里...
http://github.com/AlanQuatermain/aqtoolkit/tree/master/CommonCrypto/
http://github.com/AlanQuatermain/aqtoolkit/tree/master/CommonCrypto/
Incidentally, I have checked the byte arrays that are in toencrypt, pass and iv and they match those that are on the server.
顺便说一下,我检查了 toencrypt、pass 和 iv 中的字节数组,它们与服务器上的字节数组相匹配。
回答by GameFreak
This is not my area but it looks like on the client you have PKCS7but on the server you have PKCS5.
这不是我的领域,但它看起来像在您拥有的客户端PKCS7上,但在您拥有的服务器上PKCS5。
回答by ylian
I just ran across the exact same problem. I am using CommonCrypto on the iOS client, using settings:
我刚刚遇到了完全相同的问题。我在 iOS 客户端上使用 CommonCrypto,使用设置:
NSData * encrypted = [data dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status];
The server uses Cipher.getInstance("AES/CBC/PKCS5Padding");with the same key and initialization vector as the client.
服务器使用Cipher.getInstance("AES/CBC/PKCS5Padding");与客户端相同的密钥和初始化向量。
After banging my head against the wall for the last few hours, I finally followed Jason's advice and checked the dataEncryptedUsingAlgorithmroutine and printed out keyDataright after FixKeyLengths. It turns out my 128bit key was extended to 192bit with 0s added to the end. After fixing this, everything works properly. :)
敲我的头撞在墙上的最后几个小时后,我终于跟着杰森的咨询和检查dataEncryptedUsingAlgorithm程序和打印出来keyData之后FixKeyLengths。事实证明,我的 128 位密钥已扩展到 192 位,并在末尾添加了 0。修复此问题后,一切正常。:)
Update: My answer was posted almost 2 years ago, and this issue seems to be fixed in the latest NSData+CommonCryptocode. Specifically, this was the part that caused the issue:
更新:我的回答是在大约 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;
}
The first check keyLength <= 16wasn't there before.
keyLength <= 16之前没有第一张支票。
If you are still experiencing problems now, it's probably something else.
如果您现在仍然遇到问题,则可能是其他原因。
回答by erickson
What mode is the iPhone using with AES? You don't list anything, so perhaps that means it's using no chaining (ECB).
iPhone 使用 AES 什么模式?你没有列出任何东西,所以也许这意味着它没有使用链接(ECB)。
However, on the Java side, you are using CBC, but not specifying an initialization vector. That is definitely wrong. If you really are using CBC, you haveto have the IV that was used during encryption. The IV is not secret; it can be sent along with the ciphertext.
但是,在 Java 方面,您使用的是 CBC,但未指定初始化向量。那绝对是错误的。如果您确实在使用 CBC,则必须拥有加密期间使用的 IV。IV 不是秘密;它可以与密文一起发送。
If you are really using ECB, there is no IV, but your Java specifies the wrong mode.
如果你真的在使用ECB,没有IV,但是你的Java指定了错误的模式。
回答by Rasmus Faber
Based on your samples, the server is doing it right, and the client is not.
根据您的示例,服务器做得对,而客户端则不对。
Looking at the data, I would guess that the key is wrong. Please show us the iPhone code, especially the code to go from "1234567891123456" to your key.
看数据,我猜是key错了。请向我们展示 iPhone 代码,尤其是从“1234567891123456”到您的密钥的代码。
回答by Jason
I recently ran across this in another project. The problem was that the key was one byte too long to fit into the charbuffer inside of the dataEncryptedUsingAlgorithmmethod.
我最近在另一个项目中遇到了这个问题。问题是密钥太长了一个字节,无法放入方法char内部的缓冲区中dataEncryptedUsingAlgorithm。
The problem was that the getBytesmethod on the NSStringwas soft-failing. It would copy most of the string into the buffer, but then since the key was one byte too long, it would "mark" the operation as failed by setting the first char to NUL(char 0).
问题是该getBytes方法NSString是软失败的。它会将大部分字符串复制到缓冲区中,但由于密钥太长一个字节,它将通过将第一个字符设置为NUL(char 0)来“标记”操作失败。
Step into that method in Xcode and see what your key char[16] buffer looks like. It may have this same problem, and have the contents { 0, '2', '3', '4', ... }.
在 Xcode 中进入该方法并查看您的 key char[16] 缓冲区是什么样的。它可能有同样的问题,并且有内容{ 0, '2', '3', '4', ... }。

