iOS – 以编程方式安装SSL证书

我正在写一个phonegap插件,将CA根证书和用户证书安装在应用程序钥匙串中。

以下是用于安装证书的代码:

NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:certpath]; CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data; CFStringRef password = (CFStringRef)certPassword; const void *keys[] = { kSecImportExportPassphrase }; const void *values[] = { password }; CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); OSStatus securityError = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items); if (securityError == 0) { NSLog(@" *** Certificate install Success ***"); } else { NSLog(@" *** Certificate install Failure ***"); } 

上面的代码工作正常(securityError等于0)。 但是,我正在获取这些错误:

 unknown apsd[59] <Warning>: <APSCourier: 0xee1ba80>: Stream error occurred for <APSTCPStream: 0x126940>: TLS Error Code=-9844 "peer dropped connection before responding" unknown securityd[638] <Error>: CFReadStream domain: 12 error: 8 

这表明设备不接受安装的证书,所以我想知道该证书没有validation对安装在设备上的CA根证书。

我必须为应用程序安装CA根证书吗?

有任何想法吗 ?

PS:我是Objective-C和XCode环境的新手。

编辑:

以下代码用于在CA钥匙链中存储CA根证书:

 NSString *rootCertPath = [[NSBundle mainBundle] pathForResource:@"rootca" ofType:@"cer"]; NSData *rootCertData = [NSData dataWithContentsOfFile:rootCertPath]; OSStatus err = noErr; SecCertificateRef rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef) rootCertData); CFTypeRef result; NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: (id)kSecClassCertificate, kSecClass, rootCert, kSecValueRef, nil]; err = SecItemAdd((CFDictionaryRef)dict, &result); if( err == noErr) { NSLog(@"Install root certificate success"); } else if( err == errSecDuplicateItem ) { NSLog(@"duplicate root certificate entry"); } else { NSLog(@"install root certificate failure"); } 

编辑

看来证书没有发送到服务器。 我认为我必须手动发送证书每次一个https请求时,我正在寻找一种方法来捕捉每个https电话phonegap。

将证书导入钥匙串是不够的。 新的根证书也受到用户或系统的信任。

假设您仍然拥有可变certificateSecCertificateRef ,请使用以下代码提高信任级别:

 NSDictionary *newTrustSettings = @{(id)kSecTrustSettingsResult: [NSNumber numberWithInt:kSecTrustSettingsResultTrustRoot]}; status = SecTrustSettingsSetTrustSettings(certificate, kSecTrustSettingsDomainUser, (__bridge CFTypeRef)(newTrustSettings)); if (status != errSecSuccess) { NSLog(@"Could not change the trust setting for a certificate. Error: %d", status); exit(0); } 

如果更改信任级别,则会在popup窗口中询问用户是否接受更改。

我正在寻找,设置系统钥匙串证书“永远信任”

 // Trust always, as root certificated. NSDictionary *newTrustSettings = @{(id)kSecTrustSettingsResult: [NSNumber numberWithInt:kSecTrustSettingsResultTrustRoot]}; status = SecTrustSettingsSetTrustSettings(myCertificate, kSecTrustSettingsDomainAdmin, (__bridge CFTypeRef)(newTrustSettings));