【问题标题】:iOS - Install SSL certificate programmaticallyiOS - 以编程方式安装 SSL 证书
【发布时间】:2012-09-29 17:17:33
【问题描述】:

我正在编写一个 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

这表明设备不接受安装的证书,所以我想知道证书没有针对设备上安装的 CA Root 证书进行验证。

我是否必须为应用安装 CA Root 证书?

有什么想法吗?

P.S:我是 Objective-C 和 XCode 环境的新手。

编辑:

以下代码用于将CA根证书存储在keychain中:

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 请求时我都必须手动发送证书...... 我正在寻找一种方法来捕获 phonegap 中的每个 https 调用。

【问题讨论】:

  • 看看 [这里][1],这是关于同一主题的较旧的 SO 答案。 [1]:stackoverflow.com/questions/5323686/…
  • 我用我的 cer 文件尝试了相同的 sn-p,它不起作用...
  • 一般来说,如果应用可以修改设备全局使用的受信任 CA 证书列表,尤其是在没有明确用户干预的情况下,需要询问一些安全问题。
  • Bruno:它将证书添加到您的应用程序的钥匙串沙箱中,即没有其他应用程序会信任您的证书。

标签: objective-c ios cordova ssl certificate


【解决方案1】:

斯威夫特 4.0

let rootCertPath = Bundle.main.path(forResource: "XXXXX", ofType: "der")
    let rootCertData = NSData(contentsOfFile: rootCertPath!)
    var err: OSStatus = noErr
    let rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, rootCertData!)

    //var result: CFTypeRef1
    let dict = NSDictionary.init(objects: [kSecClassCertificate, rootCert!], forKeys: [kSecClass as! NSCopying, kSecValueRef as! NSCopying])

    err = SecItemAdd(dict, nil)

    if(err == noErr) {
        NSLog("Install root certificate success");
    } else if( err == errSecDuplicateItem ) {
        NSLog("duplicate root certificate entry");
    } else {
        NSLog("install root certificate failure");
    }

【讨论】:

    【解决方案2】:

    我一直在寻找,为系统钥匙串证书设置“始终信任”,

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

    【讨论】:

      【解决方案3】:

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

      假设您在变量certificate 中仍有SecCertificateRef,请使用以下代码提高信任级别:

      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);
      }
      

      更改信任级别将在弹出窗口中询问用户是否接受更改。

      【讨论】:

      • 未声明的标识符 kSecTrustSettingsResult 并且我已经导入了 Security 类?!我做错了什么?
      • 这似乎依赖于 Apple 提供的open source security library,特别是SecTrustSettings.h 中给出的定义。上面的答案比表面上看到的要多!
      • 是否希望我可以实现相同的信任设置而不导入这个主要用 C++ 编写的庞大(和旧)库?至少有一个指向底层 Security.framework 函数的指针(可能)包裹在下面?
      • 如何将 libsecurity_keychain 库添加到您的项目中?我无法构建它。任何人都能让它工作吗?
      猜你喜欢
      • 2011-09-11
      • 2011-07-02
      • 2011-07-16
      • 2020-06-12
      • 2017-02-08
      • 1970-01-01
      • 2010-11-28
      • 2012-10-09
      • 1970-01-01
      相关资源
      最近更新 更多