【发布时间】:2020-09-30 15:36:00
【问题描述】:
我有这段代码(可以在操场上运行):
import UIKit
import CryptoKit
let url: URL = URL(string: "https://apple.com")!
final class SSLExtractor: NSObject, URLSessionDelegate {
private var session: URLSession!
init(url: URL) {
super.init()
let session = URLSession.init(configuration: .default, delegate: self, delegateQueue: nil)
session.dataTask(with: url).resume()
}
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
let serverTrust = challenge.protectionSpace.serverTrust,
let publicKey = SecTrustCopyKey(serverTrust),
let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, nil)
else { return }
let publicKeyHash = SHA256.hash(data: publicKeyData as Data)
print("publicKey: \(publicKey)")
print("publicKey: \(publicKeyData)")
print("publicKey: \((publicKeyData as Data).base64EncodedString() )")
print(publicKeyHash)
}
}
let extractor = SSLExtractor(url: url)
据说最后的打印应该给我服务器的公钥:
SHA256 摘要:b0faa00170de7c1ac7994644efadb59f149656546394bd22c95527e78f1984b6
但是,当我使用 OpenSSL 时:
$ openssl s_client -connect apple.com:443 | openssl x509 -pubkey -noout | openssl rsa -pubin -outform der| openssl dgst -sha256
我得到一个不同的哈希:
1786e93d8e16512ea34ea1475e39597e77d7e39239ba1a97dcd71f97e64d6619
如何得到正确的哈希?
编辑:也尝试过
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0),
let certifKey = SecCertificateCopyKey(certificate),
let certifPubKey = SecKeyCopyPublicKey(certifKey),
let certifPubKeyData = SecKeyCopyExternalRepresentation(certifPubKey, nil)
但我得到了同样的结果
【问题讨论】:
-
我没有从 OpenSSL 获得相同的哈希值;你能展示你使用 OpenSSL 获得的 cert 吗? (在 PEM 中,因此不会丢失任何信息。)是的,
openssl x509 -pubkey在 PEM 中输出 SPKI;要转换为 OpenSSL 调用 DER 的二进制文件,请通过openssl rsa -pubin -outform der进行管道传输(然后从该管道传输到哈希)。或者,丢弃 BEGIN 和 END 行并对其余行进行 base64 解码。 -
@dave_thompson_085 这是
openssl s_client -connect apple.com:443的过去bin:pastebin.com/ic3u7gPi -
@dave_thompson_085 我更新了我的答案以正确散列公钥而不是 pem。然而,哈希仍然不正确。
-
It is the same cert, but I realized I did my test on Windows: that cert's SPKI in PEM with CRLF hashes to 93eacd62ace2ea5e7286b43ea12e3376583532f2794a77ec335ac3e0c46e3fc7 as I had, with LF to 58053494eb340ddc7d23608a5b4608d792f6777caa8782582ce246574980e230 as你以前有过,和现在一样 DER 1786e93d8e16512ea34ea1475e39597e77d7e39239ba1a97dcd71f97e64d6619。我不知道 Swift 以及它在此处的情况下做什么(或应该做什么),但我会查看“外部”publicKeyData 或 certifPubKeyData 以了解实际情况。
-
@dave_thompson_085 非常感谢您的帮助。事实证明,
der和pem格式都包含一些标题。 Swift 返回正确的值,没有标题。我不确定是否有一种 OpenSSL 方法可以删除der标头,但如果我这样做了,我会得到相同的哈希值。
标签: swift openssl nsurlsession