ios, alamofire5: ต้องการ curl --key foo.key --cert foo, pem --location --request GET 'https: //bar.baz/foo "
ฉันมีคีย์ส่วนตัวนอกเหนือจากคีย์สาธารณะเพื่อปักหมุดใบรับรอง
จะตรวจสอบความถูกต้องกับเซิร์ฟเวอร์อย่างไร?
$ file *
foo.der: data
foo.private.der: data
มาพร้อมกับ openssl จาก
foo.key: PEM RSA private key
foo.pem: PEM certificate
สิ่งที่ฉันต้องการคืออะลาโมไฟร์เทียบเท่าสิ่งนี้:
curl --key foo.key --cert foo.pem --location --request GET 'https: // somhostofmine / v1 / welcome /'
$ curl --key ./client_key.pem --cert ./client.pem --location --request GET 'https: // someurl' "สวัสดีครับ!"
ได้ผล
$ curl --cert ./client.pem --location --request GET 'https: // someurl / v1 / welcome /' curl: (58) ไม่สามารถตั้งค่าไฟล์คีย์ส่วนตัว: "./client.pem 'พิมพ์ PEM
ไม่
ดังนั้นคำแนะนำในการใช้ใบรับรองเองโดยไม่มีคีย์ส่วนตัวจึงไม่ได้ผล
เรากำลังจัดการกับใบรับรองที่ตรึงไว้ที่นี่หรือได้รับคีย์ส่วนตัวนี่เป็นอย่างอื่นไปที่นี่ ???
คำตอบ
คุณสามารถสร้างServerTrustManagerพารามิเตอร์การส่งผ่านเป็นผู้ประเมินของคุณต่อชื่อโฮสต์ สำหรับการตรึงคีย์สาธารณะให้ใช้PublicKeysTrustEvaluatorดังนี้:
let evaluators: [String : ServerTrustEvaluating] = [
"your.host.com": PublicKeysTrustEvaluator(performDefaultValidation: false, validateHost: false)
]
let serverTrustManager = ServerTrustManager(evaluators: evaluators)
สำหรับการตรึงใบรับรองให้ใช้PinnedCertificatesTrustEvaluatorดังนี้:
let evaluators: [String : ServerTrustEvaluating] = [
"your.host.com": PinnedCertificatesTrustEvaluator(
acceptSelfSignedCertificates: true,
performDefaultValidation: false,
validateHost: false
)
]
let serverTrustManager = ServerTrustManager(evaluators: evaluators)
ทั้งสองวิธีนี้จำเป็นต้องมีใบรับรองของคุณรวมอยู่ในบันเดิลเป็น.cerหรือ.derไฟล์
หลังจากสร้างServerTrustManagerรหัสผ่านไปยังSessionอินสแตนซ์และใช้สิ่งนี้สำหรับคำขอของคุณ:
let session = Session(serverTrustManager: serverTrustManager)
หากคุณต้องการมีตรรกะที่ซับซ้อนมากขึ้นในการตรวจสอบเซิร์ฟเวอร์ของคุณหรือคุณต้องใช้สัญลักษณ์แทนในโดเมนของคุณคุณต้องมีคลาสย่อยServerTrustManagerและแทนที่serverTrustEvaluator(forHost:)ฟังก์ชัน:
class MyServerTrustManager: ServerTrustManager {
init() {
super.init(evaluators: [:])
}
override func serverTrustEvaluator(forHost host: String) throws -> ServerTrustEvaluating? {
guard host.hasSuffix(".host.com") else {
return try super.serverTrustEvaluator(forHost: host)
}
return PublicKeysTrustEvaluator(performDefaultValidation: false, validateHost: false)
}
}
- บรรจุคีย์ส่วนตัวและสาธารณะลงในคอนเทนเนอร์ p12 ด้วย openssl
- นี่คือคีย์Alamofire ที่ไม่มีการประเมินและการส่งใบรับรองไคลเอ็นต์
สร้างอินสแตนซ์ PKCS512 () และสร้าง URLCredential โดยใช้ (โค้ดในลิงค์ด้านบน) ใน alamofire สิ่งที่คุณต้องการจากลิงค์ด้านบนคือคลาส PKCS12 และส่วนขยาย URLCredential
public class PKCS12 {
let label:String?
let keyID:NSData?
let trust:SecTrust?
let certChain:[SecTrust]?
let identity:SecIdentity?
public init(PKCS12Data:NSData,password:String)
{
let importPasswordOption:NSDictionary = [kSecImportExportPassphrase as NSString:password]
var items : CFArray?
let secError:OSStatus = SecPKCS12Import(PKCS12Data, importPasswordOption, &items)
guard secError == errSecSuccess else {
if secError == errSecAuthFailed {
NSLog("ERROR: SecPKCS12Import returned errSecAuthFailed. Incorrect password?")
}
fatalError("SecPKCS12Import returned an error trying to import PKCS12 data")
}
guard let theItemsCFArray = items else { fatalError() }
let theItemsNSArray:NSArray = theItemsCFArray as NSArray
guard let dictArray = theItemsNSArray as? [[String:AnyObject]] else { fatalError() }
func f<T>(key:CFString) -> T? {
for d in dictArray {
if let v = d[key as String] as? T {
return v
}
}
return nil
}
self.label = f(key: kSecImportItemLabel)
self.keyID = f(key: kSecImportItemKeyID)
self.trust = f(key: kSecImportItemTrust)
self.certChain = f(key: kSecImportItemCertChain)
self.identity = f(key: kSecImportItemIdentity)
}
}
extension URLCredential {
public convenience init?(PKCS12 thePKCS12:PKCS12) {
if let identity = thePKCS12.identity {
self.init(
identity: identity,
certificates: thePKCS12.certChain,
persistence: URLCredential.Persistence.forSession)
}
else { return nil }
}
}
- ป้อนข้อมูลรับรองนั้นเพื่อพิสูจน์ตัวตน (with: urlCredential) ต่อMissing sessionDidReceiveChallenge ใน Alamofire 5 delegate
และนั่นก็คือ
รหัสผ่านฮาร์ดโค้ดในตัวสร้าง p12 นั้นน่าเกลียดมาก ฉันคิดว่าสิ่งที่สำคัญคือการเบเกอรี่ base64 ใน p12 เป็นรหัสแทนที่จะเป็นไฟล์ที่มีแนวโน้มที่จะแนบ ipa patcher