【问题标题】:SSL Pinning with fingerprint in Alamofire在 Alamofire 中使用指纹进行 SSL 固定
【发布时间】:2016-05-10 03:34:49
【问题描述】:

有没有人看到用指纹而不是公钥固定 Alamofire 的方法?

对不起,如果这个问题已经回答了,我在任何地方都没有看到。

谢谢

【问题讨论】:

    标签: alamofire fingerprint pinning


    【解决方案1】:

    这最终变得非常简单。下面的代码可能并不完美,我的真实代码正在做一些额外的检查,但这是大部分。

    .SHA1Fingerprint 是 SecCertificate 上的扩展方法,可将其复制到 NSData,然后将其转换为 SHA1。我使用 RNCryptor 来做到这一点,但你可以做到这一点。

    isValidFingerprint 只是将结果与我的每个已知指纹进行比较。

    这一切都取决于我的静态 Alamofire.Manager。

    manager.delegate.sessionDidReceiveChallenge = { session, challenge in
            var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
            var credential: NSURLCredential?
    
            if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
                let host = challenge.protectionSpace.host
    
                if let serverTrust = challenge.protectionSpace.serverTrust {
    
                    let serverTrustPolicy = ServerTrustPolicy.PerformDefaultEvaluation(validateHost: true)
    
                    if serverTrustPolicy.evaluateServerTrust(serverTrust, isValidForHost: host) {
                        disposition = .UseCredential
                        credential = NSURLCredential(forTrust: serverTrust)
                    } else {
                        disposition = .CancelAuthenticationChallenge
                        return (disposition, credential)
                    }
    
                    for index in 0..<SecTrustGetCertificateCount(serverTrust) {
                        if let certificate = SecTrustGetCertificateAtIndex(serverTrust, index) {
                            if let fingerPrint = certificate.SHA1Fingerprint {
                                if isValidFingerprint(fingerPrint)  {
                                    return (disposition, credential)
                                }
                            }
                        }
                    }
                }
            }
            disposition = .CancelAuthenticationChallenge
            return (disposition, credential)
        }
    

    【讨论】:

    • 可以分享一下isValidFingerprint方法吗?
    • 请完整分享您的请求,requestsessionDidReceiveChallenge 从未致电,您知道我的问题是什么吗?
    【解决方案2】:

    斯威夫特 4

    我更改了 Bob 的答案,它对我有用,您可以根据您的要求更改验证算法,此代码只是检查固定证书之一是否有效。 this link 帮助我理解了我的问题

    private static var Manager : Alamofire.SessionManager = {
        let man = Alamofire.SessionManager()
        man.delegate.sessionDidReceiveChallenge = { session, challenge in
            var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
            var credential: URLCredential?
            if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
                let host = challenge.protectionSpace.host
    
                if let serverTrust = challenge.protectionSpace.serverTrust {
    
                    let serverTrustPolicy = ServerTrustPolicy.performDefaultEvaluation(validateHost: true)
                    if serverTrustPolicy.evaluate(serverTrust, forHost: host) {
                        disposition = .useCredential
                        credential = URLCredential(trust: serverTrust)
                    } else {
                        disposition = .cancelAuthenticationChallenge
                        return (disposition, credential)
                    }
                    let fingerPrints = [
                        "AJKSFGSGFR64563RFGY874FG43G784F48FG4F4GF74GF4F7G4FGF4F74F7GFF58Y".lowercased(),
                        "BJKSFGSGFR64563RFGY874FG43G784F48FG4F4GF74GF4F7G4FGF4F74F7GFF58Y".lowercased(),
                        "CJKSFGSGFR64563RFGY874FG43G784F48FG4F4GF74GF4F7G4FGF4F74F7GFF58Y".lowercased()
                    ]
    
                    for index in 0..<SecTrustGetCertificateCount(serverTrust) {
                        let cer = SecTrustGetCertificateAtIndex(serverTrust, index)
    
                        if let certificate = SecTrustGetCertificateAtIndex(serverTrust, index) {
                            let certData = certificate.data
                            let certHashByteArray = certData.sha256()
                            let certificateHexString = certHashByteArray.toHexString().lowercased()
    
                            if fingerPrints.contains(certificateHexString) {
                                return (disposition, credential)
                            }
                        }
                    }
                }
            }
            disposition = .cancelAuthenticationChallenge
            return (disposition, credential)
        }
        return man
    }()
    

    为了转换SecTrustGetCertificateAtIndex(serverTrust, index)(这一行let certData = certificate.data)使用这个扩展

    import Foundation
    public extension SecCertificate {
        public var data: Data {
            return SecCertificateCopyData(self) as Data
        }
    }
    

    这两行我用CryptoSwift library,你可以用sha1代替sha256,我用sha256指纹固定证书。

    let certHashByteArray = certData.sha256()
    let certificateHexString = certHashByteArray.toHexString().lowercased()
    

    【讨论】:

    • 感谢 Hamed 提供这么漂亮的代码。你能分享你的swift 5代码吗?因为在 swift 5 sessionDidReceiveChallenge 中已被删除。
    • sessionDidReceiveChallenge 适用于 Alamofire 4,如果您想使用此代码,您应该使用 Alamofire 4 而不是 5,我从未为 Alamofire 5 实现 ssl pinning,我会尽快尝试.
    • 感谢您的快速回复。实际上,我们将所有东西都迁移到了 swift 5,所以现在有必要了。让我们尽快尝试,我会等着看你的发现。
    • 对不起,我不能在不久的将来工作。
    【解决方案3】:

    我能问一下您为什么尝试固定指纹而不是公钥或证书吗?

    根据我的经验,固定的关键是将某些内容硬编码到您的程序中。

    仅供参考: https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning

    【讨论】:

    • 编辑:我有其他话,但刚刚读完你发送的链接。在散列部分,该文章实际上讨论了使用指纹而不是公钥固定的优点。非常感谢您的帮助和链接,这是一篇我还没有读过的好文章。
    • @Bob 哦,我明白了。感谢分享:)
    猜你喜欢
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 2018-01-17
    • 2021-09-15
    • 2018-09-18
    • 2021-09-14
    • 2017-01-06
    • 1970-01-01
    相关资源
    最近更新 更多