Here is the code client authentication
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {
// get identity
SecIdentityRef identity = [[YCCertificateManager instance] clientIdentity];
SecCertificateRef certificate = [[YCCertificateManager instance] certificateRef];
if (identity) {
*credential = [NSURLCredential credentialWithIdentity:identity certificates:@[] persistence:NSURLCredentialPersistencePermanent];
return NSURLSessionAuthChallengeUseCredential;
} else {
return NSURLSessionAuthChallengePerformDefaultHandling;
}
}
Therefore, I need a SecIdentityRef parameter, so I am looking for a method to obtain SecIdentityRef.
- (SecIdentityRef)clientIdentity {
SecCertificateRef certificateRef = [self certificateRef];
SecKeyRef privateKeyRef = [self privateKeyRef];
SecKeyRef publicKeyRef = SecCertificateCopyKey(certificateRef);
NSString *privateTag = @"yc_clinet_pri_tag";
NSString *publicTag = @"yc_clinet_pub_tag";
NSString *certTag = @"yc_clinet_cert_tag";
NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init];
[privateKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
[privateKeyAttr setObject:(id)kSecAttrKeyTypeEC forKey:(id)kSecAttrKeyType];
[privateKeyAttr setObject:privateTag forKey:(id)kSecAttrLabel];
[privateKeyAttr setObject:privateTag forKey:(id)kSecAttrApplicationTag];
[privateKeyAttr setObject:(__bridge id _Nonnull)(privateKeyRef) forKey:(id)kSecValueRef];
[privateKeyAttr setObject:(id)kSecAttrKeyClassPrivate forKey:(id)kSecAttrKeyClass];
[privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];
[privateKeyAttr setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(id)kSecAttrAccessible];
OSStatus privateKeyAttrCheck = SecItemAdd((CFDictionaryRef) privateKeyAttr, nil);
NSString *priKeyMsg = (__bridge_transfer NSString *)SecCopyErrorMessageString(privateKeyAttrCheck, NULL) ?: [NSString stringWithFormat:@"%d", (int)privateKeyAttrCheck];
NSLog(@"query privateKey: %@", priKeyMsg);
if ((privateKeyAttrCheck != noErr) && (privateKeyAttrCheck != errSecDuplicateItem)){
return nil;
}
NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init];
[publicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
[publicKeyAttr setObject:(id)kSecAttrKeyTypeEC forKey:(id)kSecAttrKeyType];
[publicKeyAttr setObject:publicTag forKey:(id)kSecAttrApplicationTag];
// [publicKeyAttr setObject:publicTag forKey:(id)kSecAttrPublicKeyHash];
[publicKeyAttr setObject:(__bridge id _Nonnull)(publicKeyRef) forKey:(id)kSecValueRef];
[publicKeyAttr setObject:(id)kSecAttrKeyClassPublic forKey:(id)kSecAttrKeyClass];
[publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];
[publicKeyAttr setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(id)kSecAttrAccessible];
OSStatus pubKeyCheck = SecItemAdd((CFDictionaryRef) publicKeyAttr, nil);
NSString *pubKeyMsg = (__bridge_transfer NSString *)SecCopyErrorMessageString(pubKeyCheck, NULL) ?: [NSString stringWithFormat:@"%d", (int)pubKeyCheck];
NSLog(@"query publicKey: %@", pubKeyMsg);
if ((pubKeyCheck != noErr) && (pubKeyCheck != errSecDuplicateItem)){
return nil;
}
NSMutableDictionary * queryCertificate = [[NSMutableDictionary alloc] init];
[queryCertificate setObject:(id)kSecClassCertificate forKey:(id)kSecClass];
[queryCertificate setObject:certTag forKey:(id)kSecAttrLabel];
[queryCertificate setObject:(__bridge id)certificateRef forKey:(id)kSecValueRef];
[queryCertificate setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(id)kSecAttrAccessible];
OSStatus certCheck = SecItemAdd((CFDictionaryRef)queryCertificate, nil);
NSString *certMsg = (__bridge_transfer NSString *)SecCopyErrorMessageString(certCheck, NULL) ?: [NSString stringWithFormat:@"%d", (int)certCheck];
NSLog(@"query certificate: %@", certMsg);
if ((certCheck != noErr) && (certCheck != errSecDuplicateItem)) {
return nil;
}
SecIdentityRef identityRef = NULL;
NSMutableDictionary * queryIdentityRef = [[NSMutableDictionary alloc] init];
[queryIdentityRef setObject:(id)kSecClassIdentity forKey:(id)kSecClass];
[queryIdentityRef setObject:privateTag forKey:(id)kSecAttrApplicationTag];
[queryIdentityRef setObject:certTag forKey:(id)kSecAttrLabel];
[queryIdentityRef setObject:(id)kSecAttrKeyTypeEC forKey:(id)kSecAttrKeyType];
[queryIdentityRef setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];
OSStatus identityCheck = SecItemCopyMatching((CFDictionaryRef)queryIdentityRef, (CFTypeRef *)&identityRef);
NSString *identityMsg = (__bridge_transfer NSString *)SecCopyErrorMessageString(identityCheck, NULL) ?: [NSString stringWithFormat:@"%d", (int)identityCheck];
NSLog(@"query identity: %@", identityMsg);
if (identityCheck != noErr) {
return nil;
}
return identityRef;
}
query identity: The specified item could not be found in the keychain.
Everything works fine except for the part where obtaining SecIdentityRef throws an error: "query identity: The specified item could not be found in the keychain."
please help
Topic:
App & System Services
SubTopic:
Networking
Tags: