我整天都在试图解决这个问题......
我有一个在iPhone上运行的objective-c客户端,连接到Java服务器。 iPhone正在使用AES加密数据,但我无法在服务器上解密它。我正在使用已知的密码短语和消息(单个字符串)并在iPhone上生成字节数组,使用相同的密钥和消息在Java服务器上生成比较字节数组但字节数组完全不同(因此不能在Java端解码。)
客户端正在使用具有以下设置的CommonCrypto库...
数据是使用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代码中生成的数据不匹配,字节数组完全不同。
任何人都可以看到任何明显我做错的事吗?我认为设置都是一样的...... :(
好的,所以这里...... [/ p>
iPhone客户端正在加密以下字符串“message” 它使用密钥“1234567891123456” 它使用初始化矢量“1010101010101010” 它使用的是AES128,具有CBC模式(据我所知)和kCCOptionsPKCS7Padding的选项。
加密结果(使用base64编码)是UHIYllDFAXl81ZM7OZPAuA ==
服务器正在使用相同的密钥和初始化向量加密相同的字符串。 它使用以下Cipher.getInstance(“AES / CBC / PKCS5Padding”);
加密的结果(使用base64编码)是ALBnFIHysLbvAxjvtNo9vQ ==
感谢。
这是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中的字节数组,它们与服务器上的字节数组相匹配。
答案 0 :(得分:3)
这不是我的区域,但在您拥有PKCS7
的客户端上看起来却是PKCS5
。
答案 1 :(得分:3)
我刚遇到了同样的问题。我在iOS客户端上使用CommonCrypto,使用设置:
NSData * encrypted = [data dataEncryptedUsingAlgorithm:kCCAlgorithmAES128 key:pass initializationVector:iv options:kCCOptionPKCS7Padding error:&status];
服务器使用Cipher.getInstance("AES/CBC/PKCS5Padding");
和客户端使用相同的密钥和初始化向量。
在过去的几个小时里,我的头撞到了墙上后,我终于听了杰森的建议,检查了dataEncryptedUsingAlgorithm
例程并在keyData
之后立即打印出FixKeyLengths
。事实证明我的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
。
如果您现在仍然遇到问题,可能还有其他问题。
答案 2 :(得分:2)
iPhone使用AES的模式是什么?你没有列出任何东西,所以也许这意味着它没有使用链接(ECB)。
但是,在Java端,您使用的是CBC,但未指定初始化向量。这绝对是错误的。如果您确实在使用CBC,则 拥有加密期间使用的IV。 IV不是秘密;它可以与密文一起发送。
如果您确实使用的是ECB,则没有IV,但您的Java指定了错误的模式。
答案 3 :(得分:0)
根据您的样本,服务器正确执行,而客户端则没有。
查看数据,我猜是关键是错误的。请告诉我们iPhone代码,特别是从“1234567891123456”到您的密钥的代码。
答案 4 :(得分:0)
我最近在另一个项目中遇到了这个问题。问题是密钥的长度超过一个字节,无法容纳char
方法内的dataEncryptedUsingAlgorithm
缓冲区。
问题是getBytes
上的NSString
方法是软失败的。它会将大部分字符串复制到缓冲区中,但由于密钥是一个字节太长,它会通过将第一个字符设置为NUL
(char 0)将操作“标记”为失败。
在Xcode中进入该方法,看看你的密钥char [16]缓冲区是什么样的。它可能有同样的问题,并且内容为{ 0, '2', '3', '4', ... }
。