问题
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