我编写了使用 iOS 的 Common Crypto 来加密和解密 NSData
对象的代码。加密 key 为 AES128,存储在 iOS 钥匙串(keychain)中。我可以成功加密和解密数据,所以我知道那部分代码正在工作。不过,作为完整性检查,我还生成了第二个 AES128 key ,并尝试解密使用第一个加密 key 加密的数据。我原本期望 CCCryptorStatus 值不是 kCCSuccess ,但事实并非如此。我收到了一个 NSData
对象,没有错误。我的加密/解密代码看起来像这样......
-(NSData *)dataDecryptedUsingAlgorithm:(CCAlgorithm)algorithm
data:(NSData *)data
key:(id)key
initializationVector:(id)iv
options:(CCOptions)options
error:(CCCryptorStatus *)error {
CCCryptorRef cryptor = NULL;
CCCryptorStatus status = kCCSuccess;
NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]);
NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]);
NSMutableData * keyData, * ivData;
if ( [key isKindOfClass: [NSData class]] )
keyData = (NSMutableData *) [key mutableCopy];
else
keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
if ( [iv isKindOfClass: [NSString class]] )
ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
else
ivData = (NSMutableData *) [iv mutableCopy]; // data or nil
// [keyData autorelease];
// [ivData autorelease];
// ensure correct lengths for key and iv data, based on algorithms
FixKeyLengths( algorithm, keyData, ivData );
status = CCCryptorCreate( kCCDecrypt, algorithm, options,
[keyData bytes], [keyData length], [ivData bytes],
&cryptor );
if ( status != kCCSuccess )
{
if ( error != NULL )
*error = status;
return ( nil );
}
NSData *result = [self runCryptor:cryptor onData:data result:&status];
if ( (result == nil) && (error != NULL) )
*error = status;
CCCryptorRelease(cryptor);
return ( result );
}
-(NSData *)dataEncryptedUsingAlgorithm:(CCAlgorithm) algorithm
data:(NSData *)data
key:(id)key
initializationVector:(id)iv
options:(CCOptions)options
error:(CCCryptorStatus *)error {
CCCryptorRef cryptor = NULL;
CCCryptorStatus status = kCCSuccess;
NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]);
NSParameterAssert(iv == nil || [iv isKindOfClass: [NSData class]] || [iv isKindOfClass: [NSString class]]);
NSMutableData * keyData, * ivData;
if ( [key isKindOfClass: [NSData class]] )
keyData = (NSMutableData *) [key mutableCopy];
else
keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
if ( [iv isKindOfClass: [NSString class]] )
ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
else
ivData = (NSMutableData *) [iv mutableCopy]; // data or nil
// [keyData autorelease];
// [ivData autorelease];
// ensure correct lengths for key and iv data, based on algorithms
FixKeyLengths( algorithm, keyData, ivData );
status = CCCryptorCreate( kCCEncrypt, algorithm, options,
[keyData bytes], [keyData length], [ivData bytes],
&cryptor );
if ( status != kCCSuccess )
{
if ( error != NULL )
*error = status;
return ( nil );
}
NSData *result = [self runCryptor:cryptor onData:data result:&status];
if ( (result == nil) && (error != NULL) )
*error = status;
CCCryptorRelease( cryptor );
return ( result );
}
-(NSData *)runCryptor:(CCCryptorRef)cryptor onData:(NSData *)data result:(CCCryptorStatus *)status {
size_t bufsize = CCCryptorGetOutputLength( cryptor, (size_t)[data length], true );
void * buf = malloc( bufsize );
size_t bufused = 0;
size_t bytesTotal = 0;
*status = CCCryptorUpdate( cryptor, [data bytes], (size_t)[data length],
buf, bufsize, &bufused );
if ( *status != kCCSuccess )
{
free( buf );
return ( nil );
}
bytesTotal += bufused;
// From Brent Royal-Gordon (Twitter: architechies):
// Need to update buf ptr past used bytes when calling CCCryptorFinal()
*status = CCCryptorFinal( cryptor, buf + bufused, bufsize - bufused, &bufused );
if ( *status != kCCSuccess )
{
free( buf );
return ( nil );
}
bytesTotal += bufused;
return ( [NSData dataWithBytesNoCopy: buf length: bytesTotal] );
}
当我调用加密和解密方法时,我传入 kCCAlgorithmAES128
作为我的算法,并传入 kCCOptionPKCS7Padding
作为我的选项。有没有办法捕获使用错误 key 进行解密的情况,以便我可以返回适当的错误?
最佳答案
正如 Zaph 所指出的,区分坏 key 和损坏数据的唯一可靠方法是某种婴儿床(即以该术语的最广泛含义使用;即您对加密的了解)。如果您对此方法感兴趣,请参阅 RNCryptor v4 spec 。目前还没有实现,它只是一个规范,但它包含一个验证器字段,可用于确定密码是否正确。它使用 HKDF-Expand 步骤将一些初始 key Material 转换为验证 token 。
请注意,您的方法的这一部分非常令人担忧:
if ( [iv isKindOfClass: [NSString class]] )
ivData = [[iv dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
else
ivData = (NSMutableData *) [iv mutableCopy]; // data or nil
如果传入一个字符串,则其键空间比您预期的要小得多。即使它是 16 个完全随机字节的字符串,合法的 UTF8 字符串所代表的空间也比等效的 16 个字节的随机数据小得多。
关于ios - 通用加密——测试解密中的坏 key ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25651074/