IOS相互认证

我试图在 IOS 5中实现相互认证,但是我遇到麻烦:
{NSUnderlyingError = "Error Domain=kCFErrorDomainCFNetwork Code=-1200 \"An SSL error has occurred and a secure connection to the server cannot be made.\" UserInfo=0x18d830 {NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.,_kCFNetworkCFStreamSSLErrorOriginalValue=-9800,_kCFStreamPropertySSLClientCertificateState=0,NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?,NSErrorFailingURLStringKey=https://192.168.24.110:8081/t01.json,kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0xceaa2d0>,NSErrorFailingURLKey=https://192.168.24.110:8081/t01.json}

我生成的密钥,证书和pkcs12服务器(自签名或假CA我总是得到这个问题)和客户端这样:

openssl genrsa -out client.key 1024
openssl req -new -key client.key -out client.csr

self-signed
openssl req -new -key ca.key -x509 -days 1095 -out ca.crt

CA signed
openssl x509 -req -days 365 -in client.csr -CA server.crt -CAkey server.key -CAcreateserial -out client.crt

CRT to PEM
openssl x509 -in client.crt -out client.der -outform DER
openssl x509 -in client.der -inform DER -out client.pem -outform PEM

PEM TO PKCS 12
openssl pkcs12 -export -in client.pem -inkey client.key -out client.p12

当我在浏览器(FF15)中导入时,生成的client.p12文件工作得很好.所以问题不在前面的步骤中.

IOS端我试过这个例子:http://vanjakom.wordpress.com/tag/nsurlconnection/

这是我发现这个例子不行的时候写的:

// Returns an array containing the certificate
- (CFArrayRef)getCertificate:(SecIdentityRef) identity {
    SecCertificateRef certificate = nil;

    SecIdentityCopyCertificate(identity,&certificate);
    SecCertificateRef certs[1] = { certificate };

    CFArrayRef array = CFArrayCreate(NULL,(const void **) certs,1,NULL);

    SecPolicyRef myPolicy   = SecPolicyCreateBasicX509();
    SecTrustRef myTrust;

    OSStatus status = SecTrustCreateWithCertificates(array,myPolicy,&myTrust);
    if (status == noErr) {
        NSLog(@"No Err creating certificate");
    } else {
        NSLog(@"Possible Err Creating certificate");
    }
    return array;
}

// Returns the identity
- (SecIdentityRef)getClientCertificate {
    SecIdentityRef identityApp = nil;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *documentsDirectoryPath = [paths objectAtIndex:0];
    NSString *myFilePath = [documentsDirectoryPath stringByAppendingPathComponent:@"file12.p12"]; 
    NSData *PKCS12Data = [NSData dataWithContentsOfFile:myFilePath];

    CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
    CFStringRef password = CFSTR("password");
    const void *keys[] = { kSecImportExportPassphrase };//kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef options = CFDictionaryCreate(NULL,keys,values,NULL,NULL);
    CFArrayRef items = CFArrayCreate(NULL,NULL);
    OSStatus securityError = SecPKCS12Import(inPKCS12Data,options,&items);
    CFRelease(options);
    CFRelease(password);
    if (securityError == errSecSuccess) {
        NSLog(@"Success opening p12 certificate. Items: %ld",CFArrayGetCount(items));
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items,0);
        identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);
    } else {
        NSLog(@"Error opening Certificate.");
    }

    return identityApp;
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    if ([challenge previousFailureCount] == 0) {
        SecIdentityRef identity = [self getClientCertificate];  // Go get a SecIdentityRef
        CFArrayRef certs = [self getCertificate:identity]; // Get an array of certificates
        // Convert the CFArrayRef to a NSArray
        NSArray *myArray = (__bridge NSArray *)certs;

        // Create the NSURLCredential
        NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:myArray persistence:NSURLCredentialPersistencePermanent];

        // Send
        [challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge];    
    } else {
        // Failed
        [[challenge sender] cancelAuthenticationChallenge:challenge];
    }
}

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    return YES;
}

在这两种情况下,我都不能自主地使用客户端.
此外,我还在设备(iPhone / iPad)上安装了server.crt证书,但是我不断收到“Error Domain = NSURLErrorDomain Code = -1200”.

有任何想法吗?
谢谢.

解决方法

我写的代码工作完美,问题是服务器端.

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...