簡體   English   中英

iOS:自簽名證書有問題。 SSL握手錯誤(-9824)

[英]iOS: Having problems with self-signed certificate. SSL Handshake Error (-9824)

我有一個需要執行兩步身份驗證的應用程序,總而言之,我要從服務器獲取每個用戶的base64編碼的pem格式證書,並在每次請求時使用它們。

首先,我生成一個密鑰對,創建一個CSR,給他們CSR,他們給我證書,這是我必須使用它並失敗的地方。 對於每個單獨的請求,我在控制台中遇到以下錯誤:

CFNetwork SSLHandshake失敗(-4)

CFNetwork SSLHandshake失敗(-9824)

CFNetwork SSLHandshake失敗(-9824)

NSURLConnection / CFURLConnection HTTP加載失敗(kCFStreamErrorDomainSSL,-9824)

我的方法如下:

-從發送給我的PEM格式的簽名證書中獲取DER編碼的數據

-制作一個我添加到鑰匙串的SecCertificateRef

-通過標簽在鑰匙串中查詢SecIdentityRef

-然后我做了一些大多數不必要的事情,例如從身份中搶走SecCertificateRef和私鑰,以確保發生了什么

-我還會插入服務器上的CA證書,並從鑰匙串中獲取對它的引用(不確定是否需要將其用於證書,但是我嘗試使用或不使用它-結果相同)

-然后,我使用身份和證書初始化憑據,並在獲得NSURLAuthenticationMethodClientCertificate auth方法時使用它(我不進行檢查,但是除了服務器信任之外,僅此而已)。

因此,到目前為止,沒有什么是NULL,所有內容都已初始化並且看起來不錯,但請求未成功。 當我嘗試在所有請求上使用服務器信任憑證時,我通過並沒有得到該錯誤,但是我的服務器在應有的情況下給了我一個安全性錯誤。 一旦我將自定義憑據用於任何挑戰,就會遇到上述錯誤。

注意:我知道代碼很亂,我不應該在每個請求上插入證書,但是它仍處於早期工作中,這不是問題,因為ref得到正確的實例化

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
    SSLConnectionWrapper *wrapper = [self wrapperForConnection:connection];


    NSString *certStringBase64 = [[NSUserDefaults standardUserDefaults] SSLCertificateForUserWithID:wrapper.userID];
    NSData *certData = [[NSData alloc] initWithBase64EncodedString:certStringBase64 options:0];
    NSString *certString = [[NSString alloc] initWithData:certData encoding:NSUTF8StringEncoding];

    certString = [certString stringByReplacingOccurrencesOfString:@"-----BEGIN CERTIFICATE-----" withString:@""];
    certString = [certString stringByReplacingOccurrencesOfString:@"-----END CERTIFICATE-----" withString:@""];
    certString = [[certString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""];
    //at this point certString contains the DER encoded certificate data

    SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)([[NSData alloc] initWithBase64EncodedString:certString options:kNilOptions]));

    OSStatus err = SecItemAdd((__bridge CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
                                                          (__bridge id) kSecClassCertificate, kSecClass,
                                                          cert, kSecValueRef,
                                                          kCFBooleanTrue, kSecReturnPersistentRef,
                                                          [NSString stringWithFormat:@"CertLabel_UserID_%@", wrapper.userID], kSecAttrLabel,
                                                          nil], NULL);

    const void *keys[] =   { kSecClass, kSecReturnRef,  kSecAttrLabel };

    const void *values[] = { kSecClassIdentity, kCFBooleanTrue, (__bridge const void *)([NSString stringWithFormat:@"CertLabel_UserID_%@", wrapper.userID]) };

    CFDictionaryRef queryForIdentityDict = CFDictionaryCreate(NULL, keys, values,
                                                              3, NULL, NULL);

    SecIdentityRef identityKeychainRef = NULL;
    OSStatus s = SecItemCopyMatching(queryForIdentityDict, (CFTypeRef *)&identityKeychainRef);

    SecCertificateRef certKeychainRef = NULL;
    OSStatus s2 = SecIdentityCopyCertificate(identityKeychainRef, &certKeychainRef);

    SecKeyRef privateKey;
    SecIdentityCopyPrivateKey(identityKeychainRef, &privateKey);

    NSString *stringForCACert = [self stringForCACert];

    SecCertificateRef caCert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)([[NSData alloc] initWithBase64EncodedString:stringForCACert options:kNilOptions]));
    OSStatus s3 = SecItemAdd((__bridge CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
                                                          (__bridge id) kSecClassCertificate, kSecClass,
                                                          caCert, kSecValueRef,
                                                           @"CACert", kSecAttrLabel,
                                                          nil], NULL);

    const void *keys1[] =   { kSecClass, kSecReturnRef,  kSecAttrLabel };

    const void *values1[] = { kSecClassCertificate, kCFBooleanTrue, @"CACert" };

    CFDictionaryRef queryForCACert = CFDictionaryCreate(NULL, keys1, values1,
                                                              3, NULL, NULL);

    SecCertificateRef caCertKeychainRef = NULL;
    OSStatus s4 = SecItemCopyMatching(queryForCACert, (CFTypeRef *)&caCertKeychainRef);

    NSURLCredential *credential = [[NSURLCredential alloc] initWithIdentity:identityKeychainRef certificates:@[ (__bridge id)certKeychainRef, (__bridge id) caCertKeychainRef] persistence:NSURLCredentialPersistencePermanent];

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {

        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
    }else{
        [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
    }

}

這是服務器面臨的身份驗證挑戰。 您可以通過以下代碼繞過(使用NSURLCOnnection)

+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host {
    return YES;
}

注意 :如果您在應用商店上載應用, 不要在上面使用。

對於上述iOS 9無法正常運行,請按以下步驟編輯plist

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM