在 Alamofire 中使用指纹进行 SSL 固定
SSL Pinning with fingerprint in Alamofire
有没有人见过用指纹而不是 public 键来固定 Alamofire 的方法?
很抱歉,如果有人回答了这个问题,我还没有在任何地方看到它。
谢谢
请问您尝试固定指纹而不是 public 密钥或证书的原因?
根据我的经验,固定的关键点是将某些内容硬编码到您的程序中。
仅供参考:
https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning
结果非常简单。下面的代码可能并不完美,我的真实代码正在做一些额外的检查,但这是大部分。
.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)
}
Swift 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()
有没有人见过用指纹而不是 public 键来固定 Alamofire 的方法?
很抱歉,如果有人回答了这个问题,我还没有在任何地方看到它。
谢谢
请问您尝试固定指纹而不是 public 密钥或证书的原因?
根据我的经验,固定的关键点是将某些内容硬编码到您的程序中。
仅供参考: https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning
结果非常简单。下面的代码可能并不完美,我的真实代码正在做一些额外的检查,但这是大部分。
.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)
}
Swift 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()