使用PKCS7Padding的AES CBC加密在Java和Objective-C中有不同的结果
我用Java为Android创建了一个应用程序,并使用使用PKCS7Padding的AES CBC加密在Java和Objective-C中有不同的结果,java,objective-c,encryption,aes,cbc-mode,Java,Objective C,Encryption,Aes,Cbc Mode,我用Java为Android创建了一个应用程序,并使用Cipher类用AES加密数据。现在我想用CommonCrypto类将该算法引入iOS。代码可以工作,但有不同的结果 这是Java中的代码: public static String Decrypt(String text, String key) throws Exception { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] keyB
Cipher
类用AES加密数据。现在我想用CommonCrypto
类将该算法引入iOS。代码可以工作,但有不同的结果
这是Java中的代码:
public static String Decrypt(String text, String key) 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);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] results = new byte[text.length()];
BASE64Decoder decoder = new BASE64Decoder();
try {
results = cipher.doFinal(decoder.decodeBuffer(text));
} catch (Exception e) {
System.out.print("Erron in Decryption");
}
return new String(results, "UTF-8");
}
public static String Encrypt(String text, String key) 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);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
System.out.println(keyBytes);
System.out.println(keySpec);
System.out.println(ivSpec);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(results);
}
+ (NSString*)AES256EncryptData:(NSString*)data WithKey:(NSString*)key {
char keyPtr[kCCKeySizeAES128]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = data.length;
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
data.UTF8String, dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
}
free(buffer); //free the buffer;
return nil;
}
+ (NSString*)AES256DecryptData:(NSString*)data WithKey:(NSString*)key {
char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = data.length;
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
data.UTF8String, dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [[NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
}
free(buffer); //free the buffer;
return nil;
}
这是Objective-C中的代码:
public static String Decrypt(String text, String key) 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);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] results = new byte[text.length()];
BASE64Decoder decoder = new BASE64Decoder();
try {
results = cipher.doFinal(decoder.decodeBuffer(text));
} catch (Exception e) {
System.out.print("Erron in Decryption");
}
return new String(results, "UTF-8");
}
public static String Encrypt(String text, String key) 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);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
System.out.println(keyBytes);
System.out.println(keySpec);
System.out.println(ivSpec);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(results);
}
+ (NSString*)AES256EncryptData:(NSString*)data WithKey:(NSString*)key {
char keyPtr[kCCKeySizeAES128]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = data.length;
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
data.UTF8String, dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
}
free(buffer); //free the buffer;
return nil;
}
+ (NSString*)AES256DecryptData:(NSString*)data WithKey:(NSString*)key {
char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = data.length;
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
data.UTF8String, dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [[NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
}
free(buffer); //free the buffer;
return nil;
}
更新1:
数据:要加密的文本
键:testkey
Java(所需)结果:7ptTEyImNz9KgC96+JPFXQ==
目标C结果:
U7FAVHi01q0Hhf+m9NsKjw==
在java代码中,您使用的是IV参数:
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
在目标C中,IV参数设置为空:
CCCrypt(.., NULL /* initialization vector (optional) */,
除此之外,IV参数应该是一些随机值,而不是您的密钥(或部分密钥)。其思想是输出不同的密码文本并防止块模式匹配您的问题在于Objective-C代码。您应该在Java和Obj-C中使用相同的方法。您可以使用此代码使其返回相同的结果: AES.h
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCrypto.h>
@interface AES : NSObject
+ (NSData *)Encrypt:(NSString *)data WithKey:(NSString *)key;
+ (NSString *)Decrypt:(NSData *)data WithKey:(NSString *)key;
+ (NSData *)AESOperation:(CCOperation)operation OnData:(NSData *)data key:(NSString *)key;
@end
您需要向ObjC代码中添加一个iv,而不是NULL
不要为iv使用密钥,而是创建一个随机字节的iv,将其预先添加到加密数据以用于解密。在ObjC中,您可以使用
SecRandomCopyBytes
创建随机iv:
uint8_t iv[kCCBlockSizeAES128];
SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, iv);
输出:
iv:8617dcf92de01ac2c0b92763b206b3f5
请发布结果和所需结果。@JulienLopez使用上面的示例DataSuper不安全代码编辑此帖子。永远不要把你的钥匙或钥匙的任何部分当作静脉注射用。我怎么能把它放在Obj-C里?对不起,我是一个新的加密技术。在internet或stackoverflow(即)上有很多例子。如果您想在Objective和java中获得相同的结果,则需要应用相同的逻辑来获得IV。但是,如前所述,最好保持IV的随机性,不要使用IV的密钥,它们需要不同,并且每次加密的IV应该不同。iv不需要保密。@zaph我同意这一点,但在这里,我刚刚为您翻译了java代码him@zaph您可能需要检查两种语言中的填充大小。检查一下你的静脉注射。这些是最重要的因素。就我而言,钥匙和iv是一样的。但这不是正确的方法