iOS app SSL .p12 Authentication - bad certificate error (-9825)

本小妞迷上赌 提交于 2019-12-03 16:10:34
njtman

I finally was able to resolve this problem. I found the answer here http://oso.com.pl/?p=207&lang=en

It looks like the certificate was being sent twice, causing an error on the server.

Incase the above link dies, I found the same solution already on SO (but for a different question and error).

When using Client Certificate Authentication, why do I keep getting NSURLErrorDomain Code=-1206?

Ultimately, changing this:

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceNone];

to this:

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:nil persistence:NSURLCredentialPersistenceNone];

solved my issue. It would be nice if anyone could offer more insight into this issue.

In some cases handshake may fail because server also asks intermediate and root certificates.

To fix it do the following:

Authentication challenge part:

    OSStatus status = extractIdentityAndTrust(inP12data, &myIdentity, &myTrust, password);

    SecCertificateRef myCertificate;
    SecIdentityCopyCertificate(myIdentity, &myCertificate);

    CFIndex count = SecTrustGetCertificateCount(myTrust);

    NSMutableArray* myCertificates = [NSMutableArray arrayWithCapacity:count];
    if (count > 1) {
        for (int i = 1; i < count; ++i) {
            [myCertificates addObject:(__bridge id)SecTrustGetCertificateAtIndex(myTrust, i)];
        }
    }

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:myCertificates persistence: NSURLCredentialPersistenceForSession];

Extracting method

OSStatus extractIdentityAndTrust(CFDataRef inPKCS12Data,
                             SecIdentityRef *outIdentity,
                             SecTrustRef *outTrust,
                             CFStringRef keyPassword) {

OSStatus securityError = errSecSuccess;


const void *keys[] =   { kSecImportExportPassphrase };
const void *values[] = { keyPassword };
CFDictionaryRef optionsDictionary = NULL;

/* Create a dictionary containing the passphrase if one
 was specified.  Otherwise, create an empty dictionary. */
optionsDictionary = CFDictionaryCreate(
                                       NULL, keys,
                                       values, (keyPassword ? 1 : 0),
                                       NULL, NULL);

CFArrayRef items = NULL;
securityError = SecPKCS12Import(inPKCS12Data,
                                optionsDictionary,
                                &items);

if (securityError == 0) {
    CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
    const void *tempIdentity = NULL;
    tempIdentity = CFDictionaryGetValue (myIdentityAndTrust,
                                         kSecImportItemIdentity);
    CFRetain(tempIdentity);
    *outIdentity = (SecIdentityRef)tempIdentity;
    const void *tempTrust = NULL;
    tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);

    CFRetain(tempTrust);
    *outTrust = (SecTrustRef)tempTrust;
}

if (optionsDictionary)
    CFRelease(optionsDictionary);

if (items)
    CFRelease(items);

return securityError;  } 

Please note that loop from 1 (not 0) is not a mistake. First cert is already added to "myIdentify", so only other certs should be passed as certificates, otherwise most likely you'll receive an error during handshake because of duplicating.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!