SSL Pinning with fingerprint in Alamofire

痞子三分冷 提交于 2019-12-23 13:32:55

问题


Has anyone seen a way to do pinning with Alamofire with the fingerprint instead of the public key?

Sorry if this has been answered, I haven't seen it anywhere.

Thanks


回答1:


This ended up being pretty straight forward. The code below might not be perfect, my real code is doing some addtional checks, but this is most of it.

The .SHA1Fingerprint is an extension method on SecCertificate that copies it into NSData and then converts it to a SHA1. I use RNCryptor to do that, but you can do it however.

The isValidFingerprint just compares the result to each of my known fingerprint(s).

This all hangs off my static 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)
    }



回答2:


Swift 4

I changed Bob answer and it's worked for me, you can change your validation algorithm according to your requirement, this code just check one of pinned certificates is valid or not. this link helped me for understanding my problem

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
}()

For converting SecTrustGetCertificateAtIndex(serverTrust, index) (this line let certData = certificate.data) use this extension

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

for these two line I used CryptoSwift library, you can use sha1 instead of sha256, I pinned certificate with sha256 finger print.

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



回答3:


Can I ask the reason why you try to pin the fingerprint instead of the public key or the certificate?

In my experience, the key point of pinning is to hardcode something into your program.

FYI: https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning



来源:https://stackoverflow.com/questions/37128831/ssl-pinning-with-fingerprint-in-alamofire

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!