2

我们有一个客户端-服务器架构,其中服务器使用 AES 密钥包装算法 ( rfc 3394 ) 将 AES 密钥与其他 AES 密钥一起返回给客户端。我们需要在 iOS 上实现一个解包这些密钥的客户端。

我对 iOS 开发一无所知(我负责服务器和 Web 服务 API,所以我指定了 AES Key Wrap 假设这不会是一个问题),客户端的人告诉我他们有很难实现这一点。

那么,如何在 iOS 上解开 AES 密钥呢?有没有图书馆可以做到这一点?我发现这个文档似乎正是我需要的,但他们声称它不可用。

4

1 回答 1

4

我想我回答这个问题有点晚了......希望这个答案对其他人有用。

无论如何,Apple 提供了这些方法来包装/解包密钥:

  • CCSymmetricKeyWrap
  • CCSymmetricKeyUnwrap

它们位于CommonCrypto/CommonSymmetricKeywrap.hMacOS 和 iOS 中并可在其中使用。

使用这两种方法的示例如下(请注意,由于 ,此代码不能立即在您自己的代码中使用XCTAssert's):

#import <CommonCrypto/CommonCrypto.h>

// The size of the Key Encryptions Key has to be:
// kCCKeySizeAES128 (16), kCCKeySizeAES192 (24) or kCCKeySizeAES256 (32) bytes
u_int8_t kekBytes[kCCKeySizeAES128] = {
    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
};

// The size of the data to cipher has to be a multiple of 64 bits
u_int8_t plainBytes[2 * sizeof(u_int64_t)] = {
    0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
    0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0x11
};

// WRAP KEY

// The size of the ciphered data is equal to the size of the plain data
// + another 64 bits
size_t cipheredBytesSize = (sizeof(plainBytes) + sizeof(u_int64_t));
u_int8_t cipheredBytes[cipheredBytesSize];

CCCryptorStatus status = CCSymmetricKeyWrap(kCCWRAPAES,
                                            CCrfc3394_iv,
                                            CCrfc3394_ivLen,
                                            kekBytes,
                                            sizeof(kekBytes),
                                            plainBytes,
                                            sizeof(plainBytes),
                                            cipheredBytes,
                                            &cipheredBytesSize);
XCTAssertEqual(status, kCCSuccess);
XCTAssertEqual(cipheredBytesSize, sizeof(plainBytes) + sizeof(u_int64_t));

// UNWRAP KEY

size_t sizeDecipheredPlainData = sizeof(plainBytes);
u_int8_t decipheredPlainBytes[sizeDecipheredPlainData];

status = CCSymmetricKeyUnwrap(kCCWRAPAES,
                              CCrfc3394_iv,
                              CCrfc3394_ivLen,
                              kekBytes,
                              sizeof(kekBytes),
                              cipheredBytes,
                              cipheredBytesSize,
                              decipheredPlainBytes,
                              &sizeDecipheredPlainData);
XCTAssertEqual(status, kCCSuccess);
XCTAssertEqual(sizeDecipheredPlainData, sizeof(plainBytes));

XCTAssertEqual(memcmp(plainBytes, decipheredPlainBytes, sizeof(plainBytes)), 0);

现在,前一段时间我编写了一个符合RFC 3394RFC 5649的库。后者称为 AES Key Wrap with Padding,描述了如何包装/解包大小不是 64 位的倍数的密钥,实际上,它可以是任何大小。该库位于GitHub中,也可在CocoaPods中使用。但是,老实说,除非您必须包装任何大小的密钥,否则使用它没有多大意义。

不过,下面还有另一个关于如何使用它的示例:

#import <CommonCrypto/CommonCrypto.h>

// The size of the Key Encryptions Key has to be:
// kCCKeySizeAES128 (16), kCCKeySizeAES192 (24) or kCCKeySizeAES256 (32) bytes
u_char kekBytes[kCCKeySizeAES128] = {
    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
};
NSData *keyEncryptionKey = [NSData dataWithBytes:kekBytes length:sizeof(kekBytes)];

// AES Key Wrap

// The size of the data to cipher has to be a multiple of 64 bits
u_char plainBytes[2 * sizeof(uint64_t)] = {
    0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
    0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0x11
};
NSData *expectedPlainData = [NSData dataWithBytes:plainBytes length:sizeof(plainBytes)];

NSData *cipheredData = [AKWAesKeyWrap cipheredDataByWrappingPlainData:expectedPlainData
                                                 withKeyEncryptionKey:keyEncryptionKey
                                                                error:nil];
NSData *plainData = [AKWAesKeyWrap plainDataByUnwrappingCipheredData:cipheredData
                                                withKeyEncryptionKey:keyEncryptionKey
                                                               error:nil];

XCTAssertEqualObjects(expectedPlainData, plainData);

// AES Key Wrap with Padding

// The plain data can be as small as 1 byte
u_char plainBytesWithPadding[1] = {0x10};
expectedPlainData = [NSData dataWithBytes:plainBytesWithPadding length:sizeof(plainBytesWithPadding)];

cipheredData = [AKWAesKeyWrap cipheredDataByWrappingWithPaddingPlainData:expectedPlainData
                                                   usingKeyEncryptionKey:keyEncryptionKey
                                                                   error:nil];
plainData = [AKWAesKeyWrap plainDataByUnwrappingWithPaddingCipheredData:cipheredData
                                                  usingKeyEncryptionKey:keyEncryptionKey
                                                                  error:nil];

XCTAssertEqualObjects(expectedPlainData, plainData);

问候。

于 2016-10-06T23:15:07.173 回答