2012-07-20 81 views
2

我已經將自簽名X509證書導入到我的iPhone中,只需將certificate.pem發送給它並安裝到設備上即可。現在我想驗證我的iOS應用程序中必須使用上述證書籤名的特定證書。基本上,導入的證書充當CA的根證書。iOS導入自簽名和自行創建的CA證書

導入的證書是否存儲在鑰匙串中?

如何以編程方式驗證基於導入的另一個證書? (第二個證書只有在被導入前的CA證書籤名時纔有效)

有沒有人有過這些場景的經驗?

在此先感謝!

回答

3

1)是 - 它坐落在您的鑰匙串中。

2)您使用信任SecTrustCreateWithCertificates()SecTrustEvaluate()針對所有證書或您自己的證書對其進行驗證。 3)如果您通過一系列的證書對其進行驗證,您可以選擇在鑰匙串中查找自己的證書;得到DER;計算其SHA1並將其與您的代碼中硬編碼的SHA1進行比較。

代碼如下所示。

NSMutableArray *serverChain = -- array with what you want to check 
NSMutableArray *trustedCertRefs = <your-hardcoded-certs>; 

SecTrustRef noHostTrustRef = NULL; 
OSErr status = SecTrustCreateWithCertificates((__bridge CFArrayRef)serverChain, 
           SecPolicyCreateSSL(NO, nil), &noHostTrustRef); 

if (status != noErr) { 
    NSLog(@"SecTrustCreateWithCertificates failed: %hd", status); 
    [[challenge sender] cancelAuthenticationChallenge:challenge]; 
} 


status = SecTrustSetAnchorCertificates(noHostTrustRef, 
         (__bridge CFArrayRef)trustedCertRefs); 
if (status != noErr) { 
    NSLog(@"SecTrustSetAnchorCertificates failed: %hd", status); 
    [[challenge sender] cancelAuthenticationChallenge:challenge]; 
} 

status = SecTrustEvaluate(noHostTrustRef, &result); 
if (status != noErr) { 
    NSLog(@"SecTrustEvaluate failed: %hd", status); 
    [[challenge sender] cancelAuthenticationChallenge:challenge]; 
} 
CFRelease(noHostTrustRef); 

/* From SecTrust.h: 
* 
* SecTrustResultType results have two dimensions. They specify both whether 
* evaluation suceeded and whether this is because of a user decision. 
* 
* In practice the commonly expected result is kSecTrustResultUnspecified, 
* which indicates a positive result that wasn't decided by the user. 
* 
* The common failure is kSecTrustResultRecoverableTrustFailure, which means a 
* negative result. kSecTrustResultProceed and kSecTrustResultDeny are the 
* positive and negative result respectively when decided by the user. User 
* decisions are persisted through the use of SecTrustCopyExceptions() and 
* SecTrustSetExceptions(). Finally kSecTrustResultFatalTrustFailure is a 
* negative result that should not be circumvented. In fact only in the case 
* of kSecTrustResultRecoverableTrustFailure should a user ever be asked. 
*/ 
switch (result) { 
    case kSecTrustResultProceed: // 1 
    case kSecTrustResultConfirm: // 2 
    case kSecTrustResultUnspecified: // 4 
     return YES 
     break; 
    case kSecTrustResultRecoverableTrustFailure: // 5 
    case kSecTrustResultDeny: // 3 
    case kSecTrustResultFatalTrustFailure: // 6 
    case kSecTrustResultOtherError: // 7 
    case kSecTrustResultInvalid: // 0 
    default: 
     return NO: 
     break; 
} 
[[challenge sender] cancelAuthenticationChallenge:challenge]; 

,或者如果你得到一個信任鏈,從它(對你的證書,因此)已經證實對鑰匙扣網絡堆棧說 - 那麼你可以提取證書;對他們做一個SecCertificateCopyData();然後SHA1 NSData與您的硬編碼sha1進行比較,以確保對其進行驗證。

+0

謝謝!正是我在找什麼。順便說一下,是否也可以從鑰匙串中獲取/提取整個證書? (例如,如果您在代碼中將NSData用作鑰匙串中的NSData,但它是使用Apple的iPhone配置實用程序或任何其他MDM部署的?) – Chris 2012-07-20 17:59:14

+1

是的 - 下面是我使用的代碼。實際上,如果你需要一個預先確定的標識符,它實際上會多一點。對不起,格式化 - 但評論是有點困難的代碼。隨意創建一個問題,以便我可以正確剪切和粘貼。 CFDictionaryCreate(),SecItemCopyMatching(),檢查SecIdentityGetTypeID()強制轉換,CFDataRef der = SecCertificateCopyData(cert); const unsigned char * ptr = CFDataGetBytePtr(der); long len = CFDataGetLength(der); d2i_X509(&x509,&ptr,len); _sha1 = [(__bridge NSData *)der sha1]; _der =(__bridge_transfer NSData *)der; CFRelease(der); – 2012-07-22 10:39:27

+0

我試過你的代碼(和Apple的示例代碼),但它總是在'SecTrustEvaluate'上崩潰。新帖子:http://stackoverflow.com/questions/11608847/always-exc-bad-access-on-sectrustevaluate – Chris 2012-07-23 08:26:27