不同的方式做到這一點是使用Public keys
(鋼釘關鍵)爲進行比較,顯得更爲wiki
起初,你加載的所有證書,你有什麼Bundle
+ (NSSet *)certificatesInBundle:(NSBundle *)bundle {
NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."];
NSMutableSet *certificates = [NSMutableSet setWithCapacity:[paths count]];
for (NSString *path in paths) {
NSData *certificateData = [NSData dataWithContentsOfFile:path];
[certificates addObject:certificateData];
}
return [NSSet setWithSet:certificates];
}
+ (NSSet *)defaultPinnedCertificates {
static NSSet *_defaultPinnedCertificates = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
_defaultPinnedCertificates = [self certificatesInBundle:bundle];
});
return _defaultPinnedCertificates;
}
_pinnedCertificates = [YOUR_CLASS defaultPinnedCertificates];
並從中創建public key
- (void)setPinnedCertificates:(NSSet *)pinnedCertificates {
_pinnedCertificates = pinnedCertificates;
if (self.pinnedCertificates) {
NSMutableSet *mutablePinnedPublicKeys = [NSMutableSet setWithCapacity:[self.pinnedCertificates count]];
for (NSData *certificate in self.pinnedCertificates) {
id publicKey = AFPublicKeyForCertificate(certificate);
if (!publicKey) {
continue;
}
[mutablePinnedPublicKeys addObject:publicKey];
}
self.pinnedPublicKeys = [NSSet setWithSet:mutablePinnedPublicKeys];
} else {
self.pinnedPublicKeys = nil;
}
}
static id AFPublicKeyForCertificate(NSData *certificate) {
id allowedPublicKey = nil;
SecCertificateRef allowedCertificate;
SecCertificateRef allowedCertificates[1];
CFArrayRef tempCertificates = nil;
SecPolicyRef policy = nil;
SecTrustRef allowedTrust = nil;
SecTrustResultType result;
allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate);
allowedCertificates[0] = allowedCertificate;
tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL);
policy = SecPolicyCreateBasicX509();
SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust);
SecTrustEvaluate(allowedTrust, &result);
allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust);
if (allowedTrust) {
CFRelease(allowedTrust);
}
if (policy) {
CFRelease(policy);
}
if (tempCertificates) {
CFRelease(tempCertificates);
}
if (allowedCertificate) {
CFRelease(allowedCertificate);
}
return allowedPublicKey;
}
和
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
方法檢查
NSMutableArray *policies = [NSMutableArray array];
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)];
SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
NSUInteger trustedPublicKeyCount = 0;
NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust);
for (id trustChainPublicKey in publicKeys) {
for (id pinnedPublicKey in self.pinnedPublicKeys) {
if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) {
trustedPublicKeyCount += 1;
}
}
}
return trustedPublicKeyCount > 0;
static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) {
SecPolicyRef policy = SecPolicyCreateBasicX509();
CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust);
NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount];
for (CFIndex i = 0; i < certificateCount; i++) {
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i);
SecCertificateRef someCertificates[] = {certificate};
CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL);
SecTrustRef trust;
SecTrustCreateWithCertificates(certificates, policy, &trust);
SecTrustResultType result;
SecTrustEvaluate(trust, &result);
[trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)];
if (trust) {
CFRelease(trust);
}
if (certificates) {
CFRelease(certificates);
}
continue;
}
CFRelease(policy);
return [NSArray arrayWithArray:trustChain];
}
static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) {
return [(__bridge id)key1 isEqual:(__bridge id)key2];
}
此代碼形式AFNetwking
對於這種方式,您無需更新本地證書,如果它在遠程服務器
更新你能更具體一些嗎?你在哪裏獲得固定證書?您已將其作爲參數傳遞給setPinnedCertificates方法。 – iPhoneDeveloper
你的固定證書包(本地證書)請閱讀答案的最高句子 – iSashok
你能舉個例子嗎?你怎麼稱呼那個方法?我們在哪裏獲得固定證書? – iPhoneDeveloper