SecKeyEncrypt 関数を使用して PKCS1 パディングで RSA 暗号化を実装しようとしています。
コードは次のとおりです。
NSData *encryptText(NSString *text, SecKeyRef publicKey)
{
NSCParameterAssert(text.length > 0);
NSCParameterAssert(publicKey != NULL);
NSData *dataToEncrypt = [text dataUsingEncoding:NSUTF8StringEncoding];
const uint8_t *bytesToEncrypt = dataToEncrypt.bytes;
size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
NSCAssert(cipherBufferSize > 11, @"block size is too small: %zd", cipherBufferSize);
const size_t inputBlockSize = cipherBufferSize - 11; // since we'll use PKCS1 padding
uint8_t *cipherBuffer = (uint8_t *) malloc(sizeof(uint8_t) * cipherBufferSize);
NSMutableData *accumulator = [[NSMutableData alloc] init];
@try {
for (size_t block = 0; block * inputBlockSize < dataToEncrypt.length; block++) {
size_t blockOffset = block * inputBlockSize;
const uint8_t *chunkToEncrypt = (bytesToEncrypt + block * inputBlockSize);
const size_t remainingSize = dataToEncrypt.length - blockOffset;
const size_t subsize = remainingSize < inputBlockSize ? remainingSize : inputBlockSize;
size_t actualOutputSize = cipherBufferSize;
OSStatus status = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, chunkToEncrypt, subsize, cipherBuffer, &actualOutputSize);
if (status != noErr) {
NSLog(@"Cannot encrypt data, last SecKeyEncrypt status: %ld", status);
return nil;
}
[accumulator appendBytes:cipherBuffer length:actualOutputSize];
}
return [accumulator copy];
}
@finally {
free(cipherBuffer);
}
}
iOS 6 では問題なく動作しますが、iOS 5 では失敗し、SecKeyEncrypt は-50
( errSecParam
) を返します。で 11 を 12 に変更すると、iOS 5 で動作しinputBlockSize = cipherBufferSize - 11
ます。SecKeyGetBlockSize() - 11
Apple doc によると、PKCS1 パディングが使用されている場合、入力チャンクの長さはそれ以下である必要があります。しかし、iOS 5 では間違いなく短い入力が必要です。
ドキュメントによると、私のキーブロックサイズは64なので、入力チャンクの最大長は53です。iOS 5 では、52 以下しか機能しません。
このコードの何が問題になっていますか? それとも iOS 5 Security.framework のバグですか?
UPD:問題は 512 ビット キーでのみ再現されます。生成された 1024 ビット キーで試してみると、コードは iOS 5 で動作します11
関連する Apple ドキュメント: http://developer.apple.com/library/ios/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html#//apple_ref/c/func/SecKeyEncrypt