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, чтобы убедиться, что он сверен именно с этим.

Другие вопросы по тегам