Jav*_*edo 36
如果您需要知道如何从iOS代码中的证书中提取此信息,这里有一种方法可以执行此操作.
首先添加安全框架.
#import <Security/Security.h>
添加openssl库.您可以从https://github.com/st3fan/ios-openssl下载它们
#import <openssl/x509.h>
NSURLConnectionDelegate协议允许您决定连接是否应该能够响应保护空间.简而言之,这是您可以查看来自服务器的证书,并决定允许连接继续或取消.您要在此处执行的操作是将证书公钥与您固定的证书进行比较.现在的问题是,你如何得到这样的公钥?看看下面的代码:
首先获得X509格式的证书(你需要ssl库)
const unsigned char *certificateDataBytes = (const unsigned char *)[serverCertificateData bytes];
X509 *certificateX509 = d2i_X509(NULL, &certificateDataBytes, [serverCertificateData length]);
现在我们将准备读取公钥数据
ASN1_BIT_STRING *pubKey2 = X509_get0_pubkey_bitstr(certificateX509);
NSString *publicKeyString = [[NSString alloc] init];    
此时,您可以遍历pubKey2字符串并以十六进制格式将字节提取为具有以下循环的字符串
 for (int i = 0; i < pubKey2->length; i++)
{
    NSString *aString = [NSString stringWithFormat:@"%02x", pubKey2->data[i]];
    publicKeyString = [publicKeyString stringByAppendingString:aString];
}
打印公钥以查看它
 NSLog(@"%@", publicKeyString);
完整的代码
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
const unsigned char *certificateDataBytes = (const unsigned char *)[serverCertificateData bytes];
X509 *certificateX509 = d2i_X509(NULL, &certificateDataBytes, [serverCertificateData length]);
ASN1_BIT_STRING *pubKey2 = X509_get0_pubkey_bitstr(certificateX509);
NSString *publicKeyString = [[NSString alloc] init];    
for (int i = 0; i < pubKey2->length; i++)
 {
     NSString *aString = [NSString stringWithFormat:@"%02x", pubKey2->data[i]];
     publicKeyString = [publicKeyString stringByAppendingString:aString];
 }
if ([publicKeyString isEqual:myPinnedPublicKeyString]){
    NSLog(@"YES THEY ARE EQUAL, PROCEED");
    return YES;
}else{
   NSLog(@"Security Breach");
   [connection cancel];
   return NO;
}
}
bee*_*tra 21
据我所知,您不能直接在iOS中轻松创建预期的公钥,您需要通过证书来完成.因此,所需的步骤与固定证书类似,但您还需要从实际证书和参考证书(预期的公钥)中提取公钥.
你需要做的是:
willSendRequestForAuthenticationChallenge.一些示例代码:
 (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    // get the public key offered by the server
    SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
    SecKeyRef actualKey = SecTrustCopyPublicKey(serverTrust);
    // load the reference certificate
    NSString *certFile = [[NSBundle mainBundle] pathForResource:@"ref-cert" ofType:@"der"];
    NSData* certData = [NSData dataWithContentsOfFile:certFile];
    SecCertificateRef expectedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);
    // extract the expected public key
    SecKeyRef expectedKey = NULL;
    SecCertificateRef certRefs[1] = { expectedCertificate };
    CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, (void *) certRefs, 1, NULL);
    SecPolicyRef policy = SecPolicyCreateBasicX509();
    SecTrustRef expTrust = NULL;
    OSStatus status = SecTrustCreateWithCertificates(certArray, policy, &expTrust);
    if (status == errSecSuccess) {
      expectedKey = SecTrustCopyPublicKey(expTrust);
    }
    CFRelease(expTrust);
    CFRelease(policy);
    CFRelease(certArray);
    // check a match
    if (actualKey != NULL && expectedKey != NULL && [(__bridge id) actualKey isEqual:(__bridge id)expectedKey]) {
      // public keys match, continue with other checks
      [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
    } else {
      // public keys do not match
      [challenge.sender cancelAuthenticationChallenge:challenge];
    }
    if(actualKey) {
      CFRelease(actualKey);
    }
    if(expectedKey) {
      CFRelease(expectedKey);
    }
 }
免责声明:这只是示例代码,未经过全面测试.有关完整实现,请参阅OWASP的证书锁定示例.
请记住,使用SSL Kill Switch和类似工具始终可以避免证书固定.
您可以使用SecTrustCopyPublicKeySecurity.framework 的功能执行公钥SSL固定.请参阅AFNetworking项目的连接示例:willSendRequestForAuthenticationChallenge : .
如果您需要iOS版openSSL ,请使用https://gist.github.com/foozmeat/5154962它基于st3fan/ios-openssl,目前无效.
你可以使用这里提到的PhoneGap(Build)插件:http://www.x-services.nl/certificate-pinning-plugin-for-phonegap-to-prevent-man-in-the-middle-attacks/734
该插件支持多个证书,因此不需要同时更新服务器和客户端.如果您的指纹每隔(比如说)2年发生变化,那么实施一种强制客户端更新的机制(在您的应用中添加一个版本并在服务器上创建'minimalRequiredVersion'API方法.如果应用版本是,请告诉客户更新太低(激活新证书时为fi).
| 归档时间: | 
 | 
| 查看次数: | 30061 次 | 
| 最近记录: |