Post

Replies

Boosts

Views

Activity

Reply to How to create NSURLCredential from certificate and private key strings for client authentication?
Hello, my main project uses Objective-C, so my code here is in Objective-C as well, but feel free to provide examples in Swift—I can translate them into Objective-C myself. I am able to obtain both SecCertificateRef and SecKeyRef without any issues. However, my problem lies in the next step, where I need to use them to generate a SecIdentityRef. I attempted to follow the suggestions found online to store SecCertificateRef and SecKeyRef in the keychain and then retrieve the SecIdentityRef, but this approach failed, as shown in the demo in my email, or in the example below. SecCertificateRef certificateRef = [self certificateRef]; // get it not null SecKeyRef privateKeyRef = [self privateKeyRef]; // get it not null too NSString *privateTag = @"yc_clinet_pri_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 * 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); // here print null if (identityCheck != noErr) { return nil; } return identityRef; please help
2w
Reply to How to create NSURLCredential from certificate and private key strings for client authentication?
My ultimate goal is to perform client-side authentication when making requests, so I need to generate an NSURLCredential. To create the NSURLCredential, I need a SecIdentityRef. From my research, I found that storing the private key and certificate in the keychain allows me to retrieve the SecIdentityRef. Below is my code, which includes the private key and certificate. I would appreciate any help. NSString *certString = @"-----BEGIN CERTIFICATE-----MIICJjCCAcugAwIBAgIQbR5jIkUPfd6lID5G3+vSIDAKBggqhkjOPQQDAjBOMQswCQYDVQQGEwJVUzELMAkGA1UEBxMCR1oxDjAMBgNVBAoTBUNUWVVOMRAwDgYDVQQLEwdBRFYtREVWMRAwDgYDVQQDEwdyb290LWNhMB4XDTI0MDMyODA3MjA1NVoXDTM0MDMyNjA3MjE1NVowTjELMAkGA1UEBhMCVVMxCzAJBgNVBAcTAkdaMQ4wDAYDVQQKEwVDVFlVTjEQMA4GA1UECxMHQURWLURFVjEQMA4GA1UEAxMHcm9vdC1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPa/ZkLJSjZI/0KWZA54iGmfkkXcMh00vjmK1k+ZDdKepDDsa8gkHPI7I67qSARMk/Aq3+mZHx1rpf63w/sxpKCjgYowgYcwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE8Dk3jsnNaJ3gLz/caeaDU4YaE9MB8GA1UdIwQYMBaAFE8Dk3jsnNaJ3gLz/caeaDU4YaE9MCQGA1UdEQQdMBuGGXNwaWZmZTovL2MxLmVjaGEuY3R5dW4uY24wCgYIKoZIzj0EAwIDSQAwRgIhAP6K83hDw8MQVftyTzsiEiqavndUELQV2JZpYGDhS3XGAiEA0R9ShXvK/0qs+rJyKdzttmNTBQmcfq1S/nbTm983Igc=-----END CERTIFICATE-----"; NSData *certData = [self dataFromPEMString:certString replacing:@"CERTIFICATE"]; SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData); return certificate; } NSString *priKeyString = @"-----BEGIN EC PRIVATE KEY-----MHcCAQEEIDS6kb3mrIXtqtDS4Fuh6eYB3XK0lq7waNA6UR6Q8hY5oAoGCCqGSM49AwEHoUQDQgAE9r9mQslKNkj/QpZkDniIaZ+SRdwyHTS+OYrWT5kN0p6kMOxryCQc8jsjrupIBEyT8Crf6ZkfHWul/rfD+zGkoA==-----END EC PRIVATE KEY-----"; NSData *privateKeyData = [self dataFromPEMString:priKeyString replacing:@"EC PRIVATE KEY"]; NSMutableDictionary *privateKeyOptions = [@{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC, (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate, (id)kSecAttrKeySizeInBits: @256 } mutableCopy]; #if !TARGET_OS_SIMULATOR [privateKeyOptions setObject:(id)kSecAttrTokenIDSecureEnclave forKey:(id)kSecAttrTokenID]; #endif CFErrorRef error = NULL; SecKeyRef privateKey = SecKeyCreateWithData((__bridge CFDataRef)privateKeyData, (__bridge CFDictionaryRef)privateKeyOptions, &error); if (error) { CFStringRef errorDescription = CFErrorCopyDescription(error); NSLog(@"Error creating private key: %@", errorDescription); CFRelease(errorDescription); return NULL; } return privateKey; }
Oct ’24
Reply to How to create NSURLCredential from certificate and private key strings for client authentication?
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
Oct ’24