AES 128与CBC

时间:2014-07-01 10:02:03

标签: ios objective-c encryption aes cbc-mode

我在目标C中使用简单的AES 128而生气,并且无法在简单的测试中获得预期的加密文本。谁能告诉我我做错了什么?

测试

- (void)testAES128_1
{
    NSString *testVector    = @"6bc1bee22e409f96e93d7e117393172a";
    NSString *initVector    = @"000102030405060708090A0B0C0D0E0F";
    NSString *key           = @"2b7e151628aed2a6abf7158809cf4f3c";
    NSString *expected      = @"7649abac8119b246cee98e9b12e9197d";

    NSData *inputData = [self dataFromHexString:testVector];
    NSData *keyData = [self dataFromHexString:key];
    NSData *expectedData = [self dataFromHexString:expected];

    NSData *current = [inputData AES128EncryptWithIV:initVector andKey:key];
    // What I get in current = cf2ea38a123be20765eb8c5c56caf224 != expected

    BOOL res = [inputData isEqualToData:current];

    XCTAssertTrue(res);
}

// For Converting incoming HexString into NSData
- (NSData *)dataFromHexString:(NSString *)string
{
    NSMutableData *stringData = [[NSMutableData alloc] init];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    int i;
    for (i=0; i < [string length] / 2; i++) {
        byte_chars[0] = [string characterAtIndex:i*2];
        byte_chars[1] = [string characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [stringData appendBytes:&whole_byte length:1];
    }
    return stringData;
}

类别NSData(AES):

- (NSData *)AES128EncryptWithIV:(NSString *)iv andKey:(NSString *)key {
    char ivPtr[kCCKeySizeAES128 + 1];
    bzero(ivPtr, sizeof(ivPtr));

    // fetch iv data
    [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];

    char keyPtr[kCCKeySizeAES128+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 = [self length];

    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, 0,
                                          keyPtr, kCCKeySizeAES128,
                                          ivPtr /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

我正在使用这些AES测试向量集: http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128

由于

1 个答案:

答案 0 :(得分:5)

只是您没有将十六进制ascii中的iv转换为NSData。示例测试向量具有iv,以便获得使用初始化向量所需的匹配密文。

注意:行:     BOOL res = [inputData isEqualToData:current]; 应该:     BOOL res = [expectedData isEqualToData:current];

注意:如果没有填充,则输出块计数不会更大。

这是我的测试代码:
不需要类别,我只是在那里制作方法类方法。

+ (void)testAES128_1 {
    NSString *testVector = @"6bc1bee22e409f96e93d7e117393172a";
    NSString *initVector = @"000102030405060708090A0B0C0D0E0F";
    NSString *key        = @"2b7e151628aed2a6abf7158809cf4f3c";
    NSString *expected   = @"7649abac8119b246cee98e9b12e9197d";

    NSData *inputData    = [self dataFromHexString:testVector];
    NSData *keyData      = [self dataFromHexString:key];
    NSData *ivData       = [self dataFromHexString:initVector];
    NSData *expectedData = [self dataFromHexString:expected];

    NSError *error;
    NSData *current = [Test doCipher:inputData
                                  iv:ivData
                                 key:keyData
                             context:kCCEncrypt
                               error:&error];

    BOOL res = [expectedData isEqualToData:current];
    NSLog(@"Match: %@", res ? @"Yes" : @"No"); // Match: Yes
}

+ (NSData *)doCipher:(NSData *)dataIn
                  iv:(NSData *)iv
                 key:(NSData *)symmetricKey
             context:(CCOperation)encryptOrDecrypt // kCCEncrypt or kCCDecrypt
               error:(NSError **)error
{
    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

    ccStatus = CCCrypt( encryptOrDecrypt,
                       kCCAlgorithmAES128,
                       0, //kCCOptionPKCS7Padding,
                       symmetricKey.bytes,
                       kCCKeySizeAES128,
                       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;
}