以下は、iOS 9 まで正常に動作していた私のコードです。
- (NSData *)encryptWithDataPublicKey:(NSString*)data keyTag:(NSString*)tag
{
SecKeyRef publicKey = NULL;
NSData *publicTag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
NSMutableDictionary *queryPublicKey =
[[NSMutableDictionary alloc] init];
[queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
[queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
OSStatus status = SecItemCopyMatching
((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKey);
NSData *encodedData = nil;
if (status == noErr && publicKey) {
NSData *dataToEncrypt = [data dataUsingEncoding:NSUTF8StringEncoding];
encodedData = [self encryptData:dataToEncrypt withKeyRef:publicKey];
CFRelease(publicKey);
}
return encodedData;
}
この方法は、iOS 9.x まで正常に機能していましたが、今日、XCode を 8 に更新し、iOS 10 デバイスで実行しました。アプリケーションが
CFRelease(publicKey)でクラッシュしています。
以下はクラッシュする前のコンソールからのログです。
Objective-C クラス情報を読み込めませんでした。これにより、利用可能な型情報の品質が大幅に低下します
問題を正確に取得できませんでした。
Zombie を有効にすると、クラッシュが再現されます。以下はコンソールからのログです。
*** -[Not A Type release]: 割り当て解除されたインスタンス 0x170225880 に送信されたメッセージ
前もって感謝します。
問題を取得しました。内部メソッド encodedData = [self encryptData:dataToEncrypt withKeyRef:publicKey]; があります。
SecKeyRef オブジェクトが解放されている場所。
しかし、これがiOS9までどのように機能したのだろうか???????
-(NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
const uint8_t *srcbuf = (const uint8_t *)[data bytes];
size_t srclen = (size_t)data.length;
size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
void *outbuf = malloc(block_size);
size_t src_block_size = block_size - 11;
NSMutableData *ret = [[NSMutableData alloc] init];
for(int idx=0; idx<srclen; idx+=src_block_size){
size_t data_len = srclen - idx;
if(data_len > src_block_size){
data_len = src_block_size;
}
size_t outlen = block_size;
OSStatus status = noErr;
status = SecKeyEncrypt(keyRef,
kSecPaddingPKCS1,
srcbuf + idx,
data_len,
outbuf,
&outlen
);
if (status != 0) {
ret = nil;
break;
}else{
[ret appendBytes:outbuf length:outlen];
}
}
free(outbuf);
CFRelease(keyRef);
return ret;
}
