ios – AFNetworking 2.2使用自签名证书进行SSL固定

我想阻止我的应用程序/服务器通信从MITM攻击,所以我试图设置SSL固定,但我在使用自签名证书使用AFNetworking 2.2时遇到问题.我认为这主要是我如何生成证书的问题.

我首先尝试根据these instructions生成自签名证书:

生成私钥:

sudo openssl genrsa -des3 -out server.key 2048

生成签名请求,并在询问公共名称时使用域名:

sudo openssl req -new -key server.key -out server.csr

生成证书:

sudo openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

最后,将其转换为der格式(自AFNetworking requires it起)

sudo openssl x509 -outform der -in server.crt -out server.der

服务器是Ubuntu 12.04,运行ngninx乘客来提供Rails 4应用程序.这是我的nginx服务器配置打开SSL的位:

server {
  listen 80;
  listen 443;
  server_name myapp.com;
  passenger_enabled on;
  root /var/www/myapp/current/public;
  rails_env production;
  ssl on;
  ssl_certificate /etc/nginx/ssl/server.crt;
  ssl_certificate_key /etc/nginx/ssl/server.key;
}

重新启动nginx后,下载der文件,将其添加到我的项目中,并将其重命名为“server.cer”(因为AFNetworking要求证书使用.cer扩展名),我使用此代码打开我的AFHTTPSessionManager子类的SSL固定:

client.securityPolicy = [AFSecurityPolicy 
                          policyWithPinningMode:AFSSLPinningModeCertificate];

然后,在第一次向服务器发出请求时,AFNetworking会尝试验证“信任在AFServerTrustIsValid函数中是否有效:

static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) {
    SecTrustResultType result = 0;

    OSStatus status = SecTrustEvaluate(serverTrust, &result);
    NSCAssert(status == errSecSuccess, @"SecTrustEvaluate error: %ld", (long int)status);

    return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
}

如果我在返回时放置一个断点,我可以看到结果始终是kSecTrustResultRecoverableTrustFailure.

如果我通过在安全策略上将allowInvalidCertificates设置为YES来跳过AFServerTrustIsValid函数,则请求成功.但如果我不需要,我真的不想允许无效的证书.

回到绘图板,this SO question引导我到this tutorial创建一个自签名证书,同时创建一个CA.我设置我的openssl.cnf文件是这样的:

[ req ]
default_md = sha1
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
countryName = United Kingdon
countryName_default = UK
countryName_min = 2
countryName_max = 2
localityName = Locality
localityName_default = London
organizationName = Organization
organizationName_default = Eric Organization
commonName = Common Name
commonName_max = 64

[ certauth ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
crlDistributionPoints = @crl

[ server ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
nsCertType = server
subjectAltName = DNS:myapp.com
crlDistributionPoints = @crl

[ crl ]
URI=http://testca.local/ca.crl

然后使用这些命令生成所有内容.首先是CA的东西:

sudo openssl req -config ./openssl.cnf -newkey rsa:2048 -nodes -keyform PEM -keyout ca.key -x509 -days 3650 -extensions certauth -outform PEM -out ca.cer

然后是服务器的私钥:

sudo openssl genrsa -out server.key 2048

签名请求:

sudo openssl req -config ./openssl.cnf -new -key server.key -out server.req

证书:

sudo openssl x509 -req -in server.req -CA ca.cer -CAkey ca.key -set_serial 100 -extfile openssl.cnf -extensions server -days 365 -outform PEM -out server.cer

最后是文件:

sudo openssl x509 -outform der -in server.cer -out stopcastapp.com.der

当我更新并重新启动nginx时,下载并将server.der添加到我的项目中(确保将其重命名为server.cer并重置模拟器),我得到了完全相同的结果.

可怕的kSecTrustResultRecoverableTrustFailure再次陷入丑陋的脑袋.

我究竟做错了什么?我是否喜欢这一切是如何工作的,或者我是否需要调整一个小东西才能使它全部工作?如果你能以任何方式提供帮助,我真的非常感激(我已经解决了这个问题两天了).谢谢!

最佳答案
在代码中的某处,您需要指定此类或类似的内容.您需要告诉代码接受无效证书(AKA自签名).

self.allowsInvalidSSLCertificate = YES;

转载注明原文:ios – AFNetworking 2.2使用自签名证书进行SSL固定 - 代码日志