【发布时间】:2014-04-10 12:25:37
【问题描述】:
我想防止我的应用程序/服务器通信受到 MITM 攻击,因此我正在尝试设置 SSL pinning,但我在使用自签名证书使其与 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+passenger 来提供 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扩展名),我用这段代码开启SSL固定我的AFHTTPSessionManager 子类:
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
最后是der 文件:
sudo openssl x509 -outform der -in server.cer -out stopcastapp.com.der
当我更新并重新启动 nginx 时,下载 server.der 并将其添加到我的项目中(确保将其重命名为 server.cer 并重置模拟器),我得到了完全相同的结果。
可怕的kSecTrustResultRecoverableTrustFailure 再次抬起丑陋的脑袋。
我做错了什么?我喜欢这一切是如何运作的,还是我只需要调整一件小事就可以让它全部运作?如果您能以任何方式提供帮助,我将非常非常感激(我已经解决这个问题两天了)。谢谢!
【问题讨论】:
-
现在我可以在 Mac OS X 上使用 Keychain Assistant 并覆盖 AFNetworking 2.2 如何为自签名证书进行固定。 I wrote about it here。请注意,AFNetworking 中用于自签名证书的证书固定将很快得到修复。到时候我会更新这篇文章。
-
是网络问题吗?运气好吗?
-
有这方面的消息吗?
标签: ios ssl nginx openssl afnetworking-2