Mam kod PIN do klucza publicznego w mojej aplikacji Swift iOS, która działa świetnie.Jak uzyskać programistyczną wartość niezerowej wartości serweraTrust podczas tworzenia obiektu URLAuthenticationChallenge?
Pracuję teraz nad budowaniem testów jednostkowych, które przetestują kod PIN klucza publicznego bez potrzeby połączenia sieciowego/serwera rzeczywistego. Mam to prawie działa, ale nie mogę dowiedzieć się, jak programowo utworzyć URLAuthenticationChallenge, który ma zerowy serverTrust? Cała dokumentacja Apple stwierdza, że powinno to być zero, jeśli twoja metoda uwierzytelniania to NSURLAuthenticationMethodServerTrust. Używam plików p12 i cer generowanych z mojego komputera lokalnego do budowania URLCredential w poniższym przykładzie. Bez względu na to, co robię, challenge.protectionSpace.serverTrust zawsze wraca do zera.
let protectionSpace = URLProtectionSpace(host: "mockSession",
port: 0,
protocol: "https",
realm: nil,
authenticationMethod: NSURLAuthenticationMethodServerTrust)
var urlCredential:URLCredential?
if let p12Data = try? Data(contentsOf: URL(fileURLWithPath: Bundle.init(for: type(of: self)).path(forResource: "cm7justindomnit", ofType: "p12") ?? "")),
let cerData = try? Data(contentsOf: URL(fileURLWithPath: Bundle.init(for: type(of: self)).path(forResource: "cm7justindomnit", ofType: "cer") ?? "")){
let options: NSDictionary = [kSecImportExportPassphrase:"password"]
var items: CFArray?
let _ = SecPKCS12Import(p12Data as CFData, options, &items)
if let items = items {
let objectsData = Data.init(from: CFArrayGetValueAtIndex(items, 0))
let objects = objectsData.toArray(type: CFDictionary.self).first
let secIdentityData = Data.init(from: CFDictionaryGetValue(objects, Unmanaged.passUnretained(kSecImportItemIdentity).toOpaque()))
if let secIdentity = secIdentityData.toArray(type: SecIdentity.self).first {
if let secCertifiate = SecCertificateCreateWithData(kCFAllocatorDefault, cerData as CFData) {
urlCredential = URLCredential(identity: secIdentity, certificates: [secCertifiate], persistence: .forSession)
}
}
}
}
let challenge = URLAuthenticationChallenge(protectionSpace: protectionSpace,
proposedCredential: urlCredential,
previousFailureCount: 0,
failureResponse: nil,
error: nil,
sender: self)
Mam rozszerzenie danych do obsługi UnsafeBufferPointers.
extension Data {
init<T>(from value: T) {
var value = value
self.init(buffer: UnsafeBufferPointer(start: &value, count: 1))
}
func to<T>(type: T.Type) -> T {
return self.withUnsafeBytes { $0.pointee }
}
func toArray<T>(type: T.Type) -> [T] {
return self.withUnsafeBytes {
[T](UnsafeBufferPointer(start: $0, count: self.count/MemoryLayout<T>.stride))
}
}
}
T Hank za odpowiedź, ale Twoja sugestia nadal nie pozwala mi przetestować kod wykonujący ekstrakcję certyfikatu i porównanie. Właśnie to próbuję przetestować. Kiedy dojdę do linii, na których wywołuję SecTrustEvaluate i SecTrustGetCertificateAtIndex (nie pokazany jako zastrzeżony kod), potrzebuję niezerowego serweraTrust, aby móc zbadać certyfikaty listkowe. Jeszcze raz dziękuję! –
@JustinDomnitz zaktualizowano. Słuchaj, nie musisz używać tylko certyfikatu, aby połączyć dwie klasy razem. Konieczne jest używanie protokołów, aby można było zastąpić go próbkami w testach jednostkowych. – Astoria
Dzięki za kontynuację. Muszę pomieszać twoją odpowiedź, żeby sprawdzić, czy to mi pomoże. Zaraz zrobię więcej notatek, gdy już to zrobię. W międzyczasie przyznałem ci nagrodę. Dziękuję Ci! –