Java 和 Objective C 中的 AES128 CBC 加密给出不同的输出
AES128 CBC encryption in Java and Objective C giving different outputs
我的 java 和 objective c 加密方法产生不同的输出 - AES128、CBC 模式。
键:YnA+lracf9xaiJO1oA/bTQ==
iV: 190Dt3MNeL32o9Kd37HZlQ==
纯文本:text to encrypt
Java 输出:mHZpz52LOK2K76t3B/EUuA==
Obj C 输出:Fb0D46H4tN+ukgI05x/Dbg==
Java代码:
public static String AESEncrypt(String text, String key, String iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes = new byte[16];
byte[] b = key.getBytes("UTF-8");
int len = b.length;
if (len > keyBytes.length)
len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
byte[] keyBytesiv = new byte[16];
byte[] biv = iv.getBytes("UTF-8");
int leniv = biv.length;
if (leniv > keyBytesiv.length)
leniv = keyBytesiv.length;
System.arraycopy(biv, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(results);
}
Objective C代码
+ (NSData *)AESOperation:(CCOperation)operation OnData:(NSData *)data key:(NSData *)key iV:(NSData *) iv {
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
[key bytes],
kCCBlockSizeAES128,
[iv bytes],
[data bytes],
dataLength,
buffer,
bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
解决此类问题的方法有两种,可以结合使用:
作为健全性检查,尝试解密加密文本并查看它是否与两种语言的原始文本匹配。
尝试使用另一个库(第三个库)并与前两个值进行比较。
所以我尝试用在线工具解密密文,并且可以通过Objective C输出恢复原始文本("text to encrypt")。它表明 Java 代码有问题。我怀疑这可能与输入 (key, iv) 是 base64 编码的事实有关,而它似乎被简单地视为 UTF-8 编码(getBytes()
调用)。
由于上述建议,我能够解决 java 代码中的问题。这是我在 java 和 objective c
上实现 AES128 CBC 模式的 Java 代码
public static String AESEncrypt(String text, String key, String iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes = new byte[16];
byte[] b = new BASE64Decoder().decodeBuffer(key);
int len = b.length;
if (len > keyBytes.length)
len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
byte[] keyBytesiv = new byte[16];
byte[] biv = new BASE64Decoder().decodeBuffer(iv);
int leniv = biv.length;
if (leniv > keyBytesiv.length)
leniv = keyBytesiv.length;
System.arraycopy(biv, 0, keyBytesiv, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(results);
}
我的 java 和 objective c 加密方法产生不同的输出 - AES128、CBC 模式。
键:YnA+lracf9xaiJO1oA/bTQ==
iV: 190Dt3MNeL32o9Kd37HZlQ==
纯文本:text to encrypt
Java 输出:mHZpz52LOK2K76t3B/EUuA==
Obj C 输出:Fb0D46H4tN+ukgI05x/Dbg==
Java代码:
public static String AESEncrypt(String text, String key, String iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes = new byte[16];
byte[] b = key.getBytes("UTF-8");
int len = b.length;
if (len > keyBytes.length)
len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
byte[] keyBytesiv = new byte[16];
byte[] biv = iv.getBytes("UTF-8");
int leniv = biv.length;
if (leniv > keyBytesiv.length)
leniv = keyBytesiv.length;
System.arraycopy(biv, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(results);
}
Objective C代码
+ (NSData *)AESOperation:(CCOperation)operation OnData:(NSData *)data key:(NSData *)key iV:(NSData *) iv {
NSUInteger dataLength = [data length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
[key bytes],
kCCBlockSizeAES128,
[iv bytes],
[data bytes],
dataLength,
buffer,
bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
解决此类问题的方法有两种,可以结合使用:
作为健全性检查,尝试解密加密文本并查看它是否与两种语言的原始文本匹配。
尝试使用另一个库(第三个库)并与前两个值进行比较。
所以我尝试用在线工具解密密文,并且可以通过Objective C输出恢复原始文本("text to encrypt")。它表明 Java 代码有问题。我怀疑这可能与输入 (key, iv) 是 base64 编码的事实有关,而它似乎被简单地视为 UTF-8 编码(getBytes()
调用)。
由于上述建议,我能够解决 java 代码中的问题。这是我在 java 和 objective c
上实现 AES128 CBC 模式的 Java 代码public static String AESEncrypt(String text, String key, String iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes = new byte[16];
byte[] b = new BASE64Decoder().decodeBuffer(key);
int len = b.length;
if (len > keyBytes.length)
len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
byte[] keyBytesiv = new byte[16];
byte[] biv = new BASE64Decoder().decodeBuffer(iv);
int leniv = biv.length;
if (leniv > keyBytesiv.length)
leniv = keyBytesiv.length;
System.arraycopy(biv, 0, keyBytesiv, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytesiv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(results);
}