使用 IV 的 AES-128 CBC 加密在 objective-C 中如何工作?

How does AES-128 CBC encryption with IV work in objective-C?

我正在尝试使用 'AES-128 CBC with IV' 加密字符串。这是输入参数和预期输出:

关键: 000102030405060708090A0B0C0D0E0F

四: 00102030405060708090A0B0C0D0E0F0

输入数据: EA010B23CDA9B16F0001020304050607

输出: B773C36749E87D3F8FED98FE52026A15

我已验证此网站上的输出: http://extranet.cryptomathic.com/aescalc/index?key=000102030405060708090A0B0C0D0E0F&iv=00102030405060708090A0B0C0D0E0F0&input=EA010B23CDA9B16F0001020304050607&mode=cbc&action=Encrypt&output=B773C36749E87D3F8FED98FE52026A15

How to encrypt a string with AES-128 CBC with IV in objective C? (With same result as http://extranet.cryptomathic.com/aescalc) I am trying to get the encrypted string - B773C36749E87D3F8FED98FE52026A15 , but no luck.



我尝试使用这个库进行加密:https://github.com/Pakhee/Cross-platform-AES-encryption/tree/master/iOS

这是我的 objective c 代码:

NSString* data = @"EA010B23CDA9B16F0001020304050607";
NSString* key = @"000102030405060708090A0B0C0D0E0F";
NSString* iv = @"00102030405060708090A0B0C0D0E0F0";


NSData *encryptedData = [[StringEncryption alloc] encrypt:[@"EA010B23CDA9B16F0001020304050607" dataUsingEncoding:NSUTF8StringEncoding] key:key iv:iv];
NSLog(@"encryptedData %@", encryptedData);

加密数据的输出是: <68f8ed75 e79f2ba2 c80e67a2 f0c84b7a c4b07fd1 59e937e5 14644cba c0ddb60c 40502375 7798e7a1 58bd05a5 b3d9e7bd>



我希望 *encryptedData 的值应该是 <42373733 43333637 34394538 37443346 38464544 39384645 35323032 36413135>,它是 B773C36749E87D8155[FED255]FED255B773C36749E87D3F855

我试过另一个图书馆 - https://github.com/dev5tec/FBEncryptor

NSData* _data = [data dataUsingEncoding:NSUTF8StringEncoding];
NSData* _key = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData* _iv = [iv dataUsingEncoding:NSUTF8StringEncoding];


NSData *encryptedData2 = [FBEncryptorAES encryptData:_data key:_key iv:_iv];
NSLog(@"encryptedData2 = %@", encryptedData2);

输出为 <2beea977 aef69eb1 ed9f6dd0 7bf5f1ce d1e5df46 2cbf8465 773f122d 03267abb 2e113d9b 07189268 4fd6babe 7b1c0056>

似乎我使用了错误的库,或者我对加密函数的输入有误。 objective c 的 AES 库有什么推荐吗?

Common Crypto 是用于 iOS 和 OSX 加密的正确方法。发布它以提供正确的输入。

输入的密钥、iv 和数据似乎是十六进制的。 Cryptomathic 期望它的输入是十六进制的,它的输出是十六进制的,所以它可以正常工作。

但 ObjC 代码使用:

NSString* data = @"EA010B23CDA9B16F0001020304050607";
NSData* _data = [data dataUsingEncoding:NSUTF8StringEncoding];

使用十六进制作为字符串
而是使用十六进制到数据转换,例如链接到的@Larme,请参阅第一条评论。

从输入和输出的大小来看,您似乎正在使用 PKCS#7 填充,如果输入是块大小的精确倍数,它会添加一个完整的填充块,Cryptomathic 不会添加 PKCS#7 填充。

更新

@interface Crypt : NSObject
+ (NSData *)aes128Data:(NSData *)dataIn;
+ (NSData *)dataFromHexString:(NSString *)hexString;
@end

@implementation Crypt

+ (NSData *)aes128Data:(NSData *)dataIn
             operation:(CCOperation)operation  // kCC Encrypt, Decrypt
                   key:(NSData *)key
               options:(CCOptions)options      // kCCOption PKCS7Padding, ECBMode,
                    iv:(NSData *)iv
                 error:(NSError **)error
{
    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

    ccStatus = CCCrypt( operation,
                       kCCAlgorithmAES,
                       options,
                       key.bytes, key.length,
                       iv.bytes,
                       dataIn.bytes, dataIn.length,
                       dataOut.mutableBytes, dataOut.length,
                       &cryptBytes);

    if (ccStatus == kCCSuccess) {
        dataOut.length = cryptBytes;
    }
    else {
        if (error) {
            *error = [NSError errorWithDomain:@"kEncryptionError"
                                         code:ccStatus
                                     userInfo:nil];
        }
        dataOut = nil;
    }

    return dataOut;
}

+ (NSData *)dataFromHexString:(NSString *)hexString {
    char buf[3];
    buf[2] = '[=11=]';
    unsigned char *bytes = malloc([hexString length]/2);
    unsigned char *bp = bytes;
    for (CFIndex i = 0; i < [hexString length]; i += 2) {
        buf[0] = [hexString characterAtIndex:i];
        buf[1] = [hexString characterAtIndex:i+1];
        char *b2 = NULL;
        *bp++ = strtol(buf, &b2, 16);
    }

    return [NSData dataWithBytesNoCopy:bytes length:[hexString length]/2 freeWhenDone:YES];
}

@end

NSString *dataHexString = @"EA010B23CDA9B16F0001020304050607";
NSString *keyHexString = @"000102030405060708090A0B0C0D0E0F";
NSString *ivHexString = @"00102030405060708090A0B0C0D0E0F0";

NSLog(@"dataHexString: %@", dataHexString);
NSLog(@"keyHexString:  %@", keyHexString);
NSLog(@"ivHexString:   %@", ivHexString);

NSData *data = [Crypt dataFromHexString:dataHexString];
NSData *key  = [Crypt dataFromHexString:keyHexString];
NSData *iv   = [Crypt dataFromHexString:ivHexString];

NSLog(@"data: %@", data);
NSLog(@"key:  %@", key);
NSLog(@"iv:   %@", iv);

NSError *error;
NSData *encryptedData = [Crypt
                         aes128Data:data
                         operation:kCCEncrypt
                         key:key
                         options:0
                         iv:iv
                         error:&error];

NSLog(@"encryptedData %@", encryptedData);

输出:

dataHexString: EA010B23CDA9B16F0001020304050607
keyHexString:  000102030405060708090A0B0C0D0E0F
ivHexString:   00102030405060708090A0B0C0D0E0F0

data: <ea010b23 cda9b16f 00010203 04050607>
key:  <00010203 04050607 08090a0b 0c0d0e0f>
iv:   <00102030 40506070 8090a0b0 c0d0e0f0>

encryptedData: <b773c367 49e87d3f 8fed98fe 52026a15>

注意 encryptedData 匹配 Cryptomathic 结果。