iOS импортирует самоподписанные и самостоятельно созданные сертификаты CA
Я импортировал самоподписанный сертификат X509 в свой iPhone, просто отправив ему по электронной почте Certificate.pem и установив его на устройстве. Теперь я хотел бы проверить определенный сертификат в моем приложении iOS, который должен быть подписан с использованием вышеупомянутого сертификата. По сути, импортированный сертификат действует как корневой сертификат для CA.
Хранится ли импортированный сертификат в связке ключей?
Как программно проверить другой сертификат на основе импортированного? (второй сертификат действителен, только если он подписан ранее импортированным сертификатом CA)
Кто-нибудь имел опыт работы с этими сценариями?
Заранее спасибо!
1 ответ
1) да - он сидит в вашей цепочке для ключей.
2) вы подтверждаете это с помощью траста SecTrustCreateWithCertificates()
, SecTrustEvaluate()
против всех сертификатов или только ваших собственных.
3) Если вы проверили его на предмет большого количества сертификатов, вы можете при желании найти свой собственный сертификат в цепочке для ключей; получить МЭД; вычислите его 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, чтобы убедиться, что он сверен именно с этим.