http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/に記載されている正確な方法を使用して、公開鍵でデータを検証しようとしています。
シミュレータ iOS 6.1、iOS 4.3、および iOS 5.0 でコードをテストしました。iOS 6.1 では動作しますが、iOS 4.3 および iOS 5.0 では動作しません。iOS 4.3 および iOS 5.0 では、SecKeyRawVerify がエラー コード -50 (入力パラメーターの 1 つが間違っている) で失敗します。
ここで何が悪いのか考えている人はいますか?
以下は、私が使用している検証機能のコードです。ここで使用される関数の定義を参照してください
コード:
+ (SecKeyRef)getPublicKeyRef:(NSString*)key
{
NSString* tag = @"com.publickey";
NSString *s_key = [NSString string];
NSArray *a_key = [key componentsSeparatedByString:@"\n"];
BOOL f_key = FALSE;
for (NSString *a_line in a_key) {
if ([a_line isEqualToString:@"-----BEGIN PUBLIC KEY-----"]) {
f_key = TRUE;
}
else if ([a_line isEqualToString:@"-----END PUBLIC KEY-----"]) {
f_key = FALSE;
}
else if (f_key) {
s_key = [s_key stringByAppendingString:a_line];
}
}
if (s_key.length == 0) return(FALSE);
// This will be base64 encoded, decode it.
NSData *d_key = [Base64 decode:s_key];//[NSData dataFromBase64String:s_key];
d_key = [CryptoUtil stripPublicKeyHeader:d_key];
if (d_key == nil) return(FALSE);
NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
// Delete any old lingering key with the same tag
NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
[publicKey setObject:(id) kSecClassKey forKey:(id)kSecClass];
[publicKey setObject:(id) kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[publicKey setObject:d_tag forKey:(id)kSecAttrApplicationTag];
SecItemDelete((CFDictionaryRef)publicKey);
CFTypeRef persistKey = nil;
// Add persistent version of the key to system keychain
[publicKey setObject:d_key forKey:(id)kSecValueData];
[publicKey setObject:(id) kSecAttrKeyClassPublic forKey:(id)kSecAttrKeyClass];
[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];
OSStatus secStatus = SecItemAdd((CFDictionaryRef)publicKey, &persistKey);
if (persistKey != nil) CFRelease(persistKey);
if ((secStatus != noErr) && (secStatus != errSecDuplicateItem)) {
[publicKey release];
return(FALSE);
}
// Now fetch the SecKeyRef version of the key
SecKeyRef keyRef = nil;
[publicKey removeObjectForKey:(id)kSecValueData];
[publicKey removeObjectForKey:(id)kSecReturnPersistentRef];
[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];
[publicKey setObject:(id) kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
secStatus = SecItemCopyMatching((CFDictionaryRef)publicKey,(CFTypeRef *)&keyRef);
[publicKey release];
if (keyRef == nil) return(FALSE);
return keyRef;
}
+ (BOOL)verifyMessage:(NSString *)msg forSignature:(NSString*)signature forPublicKey:(NSString*)publicKey
{
// Search for the two sections: Data and a signature.
NSString *s_data = msg, *s_signature = signature;
if ((s_data.length == 0) || (s_signature.length == 0)) return(FALSE);
// These will be base64 encoded, decode them.
NSData *d_data = [s_data dataUsingEncoding:NSUTF8StringEncoding];
if (d_data == nil) return(FALSE);
NSData *d_signature = [Base64 decode:s_signature];
if (d_signature == nil) return(FALSE);
// Make SHA-256 hash of the data
uint8_t h_data[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(d_data.bytes, d_data.length, h_data);
NSData* d_hash = [NSData dataWithBytes:h_data length:CC_SHA256_DIGEST_LENGTH];
// The signature is generated against the binary form of the data, validate
//it.
BOOL valid = FALSE;
OSStatus secStatus = SecKeyRawVerify([CryptoUtil getPublicKeyRef:publicKey],
kSecPaddingPKCS1SHA256,
d_hash.bytes, d_hash.length,
d_signature.bytes,
d_signature.length);
if (secStatus == errSecSuccess) {
valid = TRUE;
}
return(valid);
}
エラー コード: SecKeyRawVerify は、iOS 5.0 および iOS 4.3 ではエラー コード -50 (入力パラメーターの 1 つが間違っています) で失敗しますが、iOS 6.1 では呼び出しは成功します。
前もって感謝します。