Can I please have some assistance on how to properly setup an NWParameters extension to accept a base64Encoded public certificate and then use it to correctly secure connections?
I have this so far
extension NWParameters {
convenience init(base64EncodedCert: String) throws {
// Create QUIC parameters with the TLS options
let quicOptions = NWProtocolQUIC.Options(alpn: ["h3"])
// Convert the base64 string to a string to handle PEM format
guard let pemData = Data(base64Encoded: base64EncodedCert),
let pemString = String(data: pemData, encoding: .utf8)
else {
print("Failed to decode initial base64 string")
throw CertificateError.invalidBase64String
}
// Extract the certificate content between the PEM markers
let lines = pemString.components(separatedBy: .newlines)
let certificateLines = lines.filter { line in
!line.contains("BEGIN CERTIFICATE") && !line.contains("END CERTIFICATE") && !line.isEmpty
}
// Join the lines and create certificate data
let certificateString = certificateLines.joined()
guard let certificateData = Data(base64Encoded: certificateString) else {
print("Failed to decode certificate content")
throw CertificateError.invalidBase64String
}
print("Successfully decoded certificate content, data length: \(certificateData.count)")
// Try to create certificate
guard let certificate = SecCertificateCreateWithData(nil, certificateData as CFData) else {
print("Failed to create certificate from data")
throw CertificateError.certificateCreationFailed
}
sec_protocol_options_set_min_tls_protocol_version(quicOptions.securityProtocolOptions, .TLSv13)
sec_protocol_options_set_max_tls_protocol_version(quicOptions.securityProtocolOptions, .TLSv13)
print("Successfully created certificate")
// Get certificate summary for verification
let certificateSummary = SecCertificateCopySubjectSummary(certificate) as? String
print("Certificate Summary: \(certificateSummary ?? "No summary available")")
// Create identity from certificate
sec_protocol_options_set_verify_block(quicOptions.securityProtocolOptions, { _, sec_trust, sec_protocol_verify_complete in
// Get the certificates from the trust object
let trust = sec_trust_copy_ref(sec_trust).takeRetainedValue()
// Get the certificate chain
guard let certificates = SecTrustCopyCertificateChain(trust) as? [SecCertificate],
let peerCertificate = certificates.first
else {
print("Failed to get peer certificate from chain")
sec_protocol_verify_complete(false)
return
}
// Compare the peer's certificate with our pinned certificate
let peerCertificateData = SecCertificateCopyData(peerCertificate) as Data
let pinnedCertificateData = SecCertificateCopyData(certificate) as Data
// Verify the certificates match
let certificatesMatch = peerCertificateData == pinnedCertificateData
print("Certificate verification result: \(certificatesMatch)")
sec_protocol_verify_complete(certificatesMatch)
}, DispatchQueue(label: "com.example.certificate.verification"))
self.init(quic: quicOptions)
}
}
I am seeing "Certificate Summary: " printed to the console but I am getting the following errors
Connection state changed to: failed(-9858: handshake failed)
Connection failed: -9858: handshake failed