• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

iOS 使用自签名 TLS/SSL 证书连接不起作用

[复制链接]
菜鸟教程小白 发表于 2022-12-12 19:18:04 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我想对 iOS 应用程序的 MITM 攻击加密和保护网络连接。由于应用程序只会连接到一台服务器,因此不需要由像 VeriSign 这样的 CA 签署证书。我想对证书进行自签名并将其与应用程序一起分发。

我尝试了这个,但最终得到 kSecTrustResultRecoverableTrustFailure 并且无法弄清楚我哪里出错了。有人可以查看它并确定问题或指出我如何调试它的方向吗?是因为我在 localhost 上使用/测试有问题吗?

我认为这是创建证书或设置服务器时的问题,但我不知道它是什么。我用 openssl s_client 对其进行了测试,它似乎可以工作,但 iOS 不接受它(见下文)。我可以接受 kSecTrustResultRecoverableTrustFailure 为成功,但宁愿避免它。

创建证书

我的 openssl.cnf。最后一行指定了 subjectAltName,应该是唯一重要的。

[ req ]
default_bits = 2048 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = sha256 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
# Variable name   Prompt string
# #----------------------   ----------------------------------
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64

# Default values for the above, for consistency and less typing.
# Variable name   Value
#------------------------------   ------------------------------
0.organizationName_default = The Sample Company
localityName_default = Metropolis
stateOrProvinceName_default = New York
countryName_default = US

[ server ]
basicConstraints = critical,CA:FALSE
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
nsCertType = server
subjectAltName = IP:127.0.0.1,DNS:localhost

这就是我创建证书的方式。我使用 sha256,因为 md5 似乎不受支持。之后我将证书转换为 iOS 需要的 DER 格式。

macbook:~/Documents/app/https-test/cert$ openssl req -x509 -sha256 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 356 -nodes -config openssl.cnf
Generating a 2048 bit RSA private key
..+++
............................................................+++
writing new private key to 'key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]E
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:com
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
macbook:~/Documents/app/https-test/cert$ ls
cert.der    cert.pem    key.pem     openssl.cnf
macbook:~/Documents/app/https-test/cert$ openssl x509 -in cert.pem -outform der -out cert.der

服务器

服务器是接受https请求的node.js服务器。

var https = require('https');
var fs = require('fs');

var options = {
    key: fs.readFileSync('../cert/key.pem'),
    cert: fs.readFileSync('../cert/cert.pem')
};

https.createServer(options, function (req, res) {
    res.writeHead(200);
    res.end("test return\n");
}).listen(8443);

我用以下输出测试了这个服务器:

macbook:~/Documents/app/https-test/server$ openssl s_client -showcerts -host localhost -port 8443 -CAfile ../cert/cert.pem
CONNECTED(00000003)
depth=0 /O=The Sample Company/L=Metropolis/ST=New York/C=US
verify return:1
---
Certificate chain
 0 s:/O=The Sample Company/L=Metropolis/ST=New York/C=US
   i:/O=The Sample Company/L=Metropolis/ST=New York/C=US
-----BEGIN CERTIFICATE-----
MIIDIDCCAggCCQClnXQ2tGOF1jANBgkqhkiG9w0BAQsFADBSMRswGQYDVQQKExJU
aGUgU2FtcGxlIENvbXBhbnkxEzARBgNVBAcTCk1ldHJvcG9saXMxETAPBgNVBAgT
CE5ldyBZb3JrMQswCQYDVQQGEwJVUzAeFw0xNDAyMjQwMDEwMTJaFw0xNTAyMTUw
MDEwMTJaMFIxGzAZBgNVBAoTElRoZSBTYW1wbGUgQ29tcGFueTETMBEGA1UEBxMK
TWV0cm9wb2xpczERMA8GA1UECBMITmV3IFlvcmsxCzAJBgNVBAYTAlVTMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzudBEZmW78S9EnxQzObf778qIBRf
/pUPVKSC31/8iVLM3w71GtHxI39Gt+WwAhMRRKmO+EhsFWDmQZfg3GNsws4Uj/uO
8I6Xp9rF7IWBIAZ37X2nUPD/qEU4+SFmiNi8POaXPt+5mQQLYFfun5YzpZPoiPpi
wuIkcgY8mOJlNv7Hr4AnyMtMMnscZis+ELVky5Q/mDsiamHzPPGjjKYKDMfwYj8S
yAz0GLKrcHBBm4Re++mefJU0sdapAYEliAJdTs0aBA5lxcRBzkKlFwxgsQrhtwL9
xBY+RC/PbnVWRF/YVrd7o6JvXmWOPFDlbL99v9tGGjoUyFDeLoIMaqaGmwIDAQAB
MA0GCSqGSIb3DQEBCwUAA4IBAQAdnvu4W6GoWkAALpvpEgXBMKq2sApLHib+i8Be
+LrAS/zA1GxlMqswUBUvtGuQq88oGWC/eU3n3PvRE2tuIARg4ZSGo2/KdYfvOFYy
O7hnwdlAYirdj3XKUnomj0sVgeAjJV4xSha7aOzs9mNyLquJvewBEAvQdJnPRYfS
LwSUq5kbbiHyFWHmJnTUfLpfKj0w+LNO4Jrb0GdFs7ZWq3R0Mscig668Htue4xST
jWEh0f/ZcWLK+UVvTvpMb9DTM8oOV94EHt+slaIMEzD2hWjtLcwGfUzX5qYU450v
Kt1b40tBHRHi8ytstg4qdLlwf0NpXejcLQiW1CgNZoEIBtP+
-----END CERTIFICATE-----
---
Server certificate
subject=/O=The Sample Company/L=Metropolis/ST=New York/C=US
issuer=/O=The Sample Company/L=Metropolis/ST=New York/C=US
---
No client certificate CA names sent
---
SSL handshake has read 983 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID: C8901BBE04CB24444E0DDEA60EB7A72A64822E652973AD1D16E27D1E1F29F828
    Session-ID-ctx:
    Master-Key: D143A0F58C848B0E1BCA7BDF22EEBC326F811961CC10FF3A653715A8D8F96F5825AFC6D200F334D2E1581BFECA940111
    Key-Arg   : None
    Start Time: 1393256956
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
^C

iOS 应用

应用程序使用这个 NSURLConnectionDelegate https://gist.github.com/dhoerl/2051599



Best Answer-推荐答案


iOS code you linked to期望服务器的证书在设备的受信任的根证书存储中,或者至少由受信任的根证书颁发机构签名。您收到的错误表明情况并非如此。

该错误意味着证书不受信任。根据定义,自签名证书不受信任,因为它不是由受信任的根证书颁发机构签名的(因此无法验证证书的签名者是否就是他们所说的那个人)。

如果您只想要 SSL 加密的好处而不需要保护免受 MITM 攻击,您可以通过在 NSURLConnection 委托(delegate)的 didReceiveAuthenticationChallenge 方法中执行以下操作来绕过服务器检查:

- (void)connectionNSURLConnection *)connection didReceiveAuthenticationChallengeNSURLAuthenticationChallenge *)challenge 
{
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];

    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

请注意,这不会阻止 MITM 攻击,因为您现在允许连接到任何 SSL 主机,但如果您确实需要这种保护,则不应使用自签名证书。如果您只想要 SSL 提供的加密,自签名证书就可以了。

也就是说,如果您将服务器证书与您的应用程序捆绑在一起,您可以进行服务器身份验证 - 这称为证书固定。您需要在上面的 didReceiveAuthenticationChallenge 方法中添加代码,以将服务器的证书与嵌入在您的应用程序中的证书进行比较,并让它只信任该特定证书而不信任其他证书。这当然意味着如果您服务器上的证书过期或更改,您的客户端将无法再连接(直到您使用新证书重建和重新分发您的应用程序)。这也意味着,如果您的服务器的私钥被盗或泄露,您将无法撤销它并发布一个新的,并且 Bad Guys 将能够冒充您的服务器到任何尝试使用连接的客户端泄露的 key 。使用由受信任的根 CA 颁发的证书可以避免这两个问题,如果您确实需要服务器身份验证,仍然是推荐的方法。这样,您可以在需要时吊销证书,颁发新证书,一切仍然有效。

关于iOS 使用自签名 TLS/SSL 证书连接不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21992456/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap