1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import Foundation
import XCTest
import NIO
@testable import NIOSSL
let multiSanCert = """
-----BEGIN CERTIFICATE-----
MIIDEzCCAfugAwIBAgIURiMaUmhI1Xr0mZ4p+JmI0XjZTaIwDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTE3MTAzMDEyMDUwMFoXDTQwMDEw
MTAwMDAwMFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA26DcKAxqdWivhS/J3Klf+cEnrT2cDzLhmVRCHuQZXiIr
tqr5401KDbRTVOg8v2qIyd8x4+YbpE47JP3fBrcMey70UK/Er8nu28RY3z7gZLLi
Yf+obHdDFCK5JaCGmM61I0c0vp7aMXsyv7h3vjEzTuBMlKR8p37ftaXSUAe3Qk/D
/fzA3k02E2e3ap0Sapd/wUu/0n/MFyy9HkkeykivAzLaaFhhvp3hATdFYC4FLld8
OMB60bC2S13CAljpMlpjU/XLLOUbaPgnNUqE1nFqFBoTl6kV6+ii8Dd5ENVvE7pE
SoNoyGLDUkDRJJMNUHAo0zbxyhd7WOtyZ7B4YBbPswIDAQABo10wWzBLBgNVHREE
RDBCgglsb2NhbGhvc3SCC2V4YW1wbGUuY29tgRB1c2VyQGV4YW1wbGUuY29thwTA
qAABhxAgAQ24AAAAAAAAAAAAAAABMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEL
BQADggEBACYBArIoL9ZzVX3M+WmTD5epmGEffrH7diRJZsfpVXi86brBPrbvpTBx
Fa+ZKxBAchPnWn4rxoWVJmTm4WYqZljek7oQKzidu88rMTbsxHA+/qyVPVlQ898I
hgnW4h3FFapKOFqq5Hj2gKKItFIcGoVY2oLTBFkyfAx0ofromGQp3fh58KlPhC0W
GX1nFCea74mGyq60X86aEWiyecYYj5AEcaDrTnGg3HLGTsD3mh8SUZPAda13rO4+
RGtGsA1C9Yovlu9a6pWLgephYJ73XYPmRIGgM64fkUbSuvXNJMYbWnzpoCdW6hka
IEaDUul/WnIkn/JZx8n+wgoWtyQa4EA=
-----END CERTIFICATE-----
"""
let multiCNCert = """
-----BEGIN CERTIFICATE-----
MIIDLjCCAhagAwIBAgIUR6eOMdEFZAqorykK6u6rwPGfsh0wDQYJKoZIhvcNAQEL
BQAwSDELMAkGA1UEBhMCVVMxEjAQBgNVBAMMCUlnbm9yZSBtZTERMA8GA1UECAwI
TmVicmFza2ExEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNzExMDIxMzM5MjRaFw00
MDAxMDEwMDAwMDBaMEgxCzAJBgNVBAYTAlVTMRIwEAYDVQQDDAlJZ25vcmUgbWUx
ETAPBgNVBAgMCE5lYnJhc2thMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCb/wE6/pF40KmF4bgtrlInWIojsDma08q7
cK9LpzifjYNTrlTv7+8tR3TRkWwThW4sMGckq9u1Bty9aF50sazBZaLDZYoamuHS
43T7hj4aX++lEq+inlXaNX3WmKkq0y0ANLBsXaLC+8J+xemlXErBsacK1Lz8Yz//
lVOwD85LG6UN87j8L/L5+t922HyGhQRVTvcbmXa05JovMXILXnoUeEvNteZZtLa0
zcpO+9pN/VwmxVOnQncxTG81FV6Qypx7YFf16QyEDVkXrt7/l6k+I+sAzBHIn28Y
cPq/HfcAbWPU+gMiCLCplDi5NCyL7yyiG7bEjxR0oiWhzZG1abgjAgMBAAGjEDAO
MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAFAknMMePElmNsuzEUWO
m2a6n/cHEaJzDEVLbFifcCUNU2U6o2bgXrJIBjFudISYPjpG+gmnuAwdfu6CA63M
wiuLaLQASz6W12pRqlIriUazDn4JnIHu8wCHj8QkYTV7HunhtGJjX7xT89dRS5Y/
IJv0Q9J2CZ16d3ETCzWp2Djq1IPggkBrsgKalJmwsiWi8UkH/GeMA+YQ1p8r9Bvp
+Jd1VitqxJFG5tgT68dq1LxlsNb4L1Cm15m8LdhY5BgSO2AG9G4gBbO0ixZJwHbn
TLiPC0Jd3x5tf9qeSv1eWHuhQd9R908EhZdC6rgN8fZfMux2tQxNbIsNPYAQhmsB
/nc=
-----END CERTIFICATE-----
"""
let noCNCert = """
-----BEGIN CERTIFICATE-----
MIIC3jCCAcagAwIBAgIUeB9gFXDDe/kTcsPGlHIZ4M+SpyYwDQYJKoZIhvcNAQEL
BQAwIDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5lYnJhc2thMB4XDTE3MTEwMjEz
NDIwMFoXDTQwMDEwMTAwMDAwMFowIDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5l
YnJhc2thMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2DqRr+tIXVXz
4VZA5dSJo4pPgC+lNngg8Bpk9pedmOj8GSdvbIkRmXPRqOIw33vurfGVqcYiX3DH
HcVKS6ZF/ylE4dDH7JmGvCYpJTK6+02nkpdz3CzoX8lIRHBSJAJwny/UK20QBhsU
OWm/mD0uCRfgfp9FasKqA56OBFGNYAOTAM33RHuXQNSSfV5FmSmNkWsiM1S+EUgH
PptKQlXUfiSUFBCuyy9iItSg2fOew3C6/dXJ47T4mFi5qD/WKmI3uSNqBKNPcHI8
EGZX4r8w0Hvq2hV13t+hexaLkS6VeZWb1kTrdgDPnjcl43txePPP7tEGRlZFO+bI
V2j0pGb/iwIDAQABoxAwDjAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IB
AQC27ElJn7TWhr2WcPsdXxGNUpepFgXEsEAVnoiJPI9XqXdOZCFWTUmRXrQICPUn
8HnVfYTFl/WZnTYhf8Ky5RB1W3X0Juo7MGge7mx6D6m8yJVBecQxPasVienTvdDg
UZI2oodxnS7egFwlvFM2ZUmPLVvq0B7VQBSa2Ix3FChNtJ1u5yfHyoDUMRfYl0bF
0B3poAgLDW3FUQ7QoErMvslUJrFxmJXUKKdhg9z6jQTdcmZ6Dr8sFZQkRADbJRzm
AYqSreeyevxdoNwQrpZMAGm61nc7OS8i0Q0JRe3FpGD29BMS0ystlzDeNnUpf+yJ
u9dFQrCkq8MilGSO1L2bZsqY
-----END CERTIFICATE-----
"""
let unicodeCNCert = """
-----BEGIN CERTIFICATE-----
MIICyjCCAbKgAwIBAgIUeK7KUVK7tcUhxVnkSWEsqHj07TEwDQYJKoZIhvcNAQEL
BQAwFjEUMBIGA1UEAwwLc3RyYcOfZS5vcmcwHhcNMTcxMTAyMTM0NzQxWhcNNDAw
MTAxMDAwMDAwWjAWMRQwEgYDVQQDDAtzdHJhw59lLm9yZzCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAO0Anpw+WpM897YXUNHI4oTr4BUxIcOC2A7LQiQ0
briNXLIaIN8irwaa4TwCqvjg2B09GGO7EWvi0EX050X0jFFiSDdGhSZGMLL34nfk
/HW14XjTCW+LkYcFAyOD8Kf3nGGLagIdtnPWQ3Atf6rTf5A35K75+penURN226xB
t0vKqtngYTFu0n6B/+Ip6FI/Bq8yyGtPN74yR79KG3WL7mvrEHxv+TnZkb2F6f2j
cJALEJPx8wFug154EnRDOURZMX5gmHRR/Xm9jP1R7Rch+4Ue2Fy38C1a35p0Saap
JDKSmxr2430bQ5S41BTT5Q3N6eBD7f+cqaQyoa0u+qvl+gcCAwEAAaMQMA4wDAYD
VR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAM7x+J+A2UN+RCKEjJUc9rM3S
G9AxfhKO3VN1mrPRs6JG1ED7t/9e2xdjLRRl84Rz9jnaKVTS2sQ8yKYejWGUbXDq
WO6KNlrjzspL3M8EIoi7QNwtRktviCkkxxwhzDfuH9N6ncjq0qod0vxGq0nqxrAo
VJto6NnrshZEQHGF8uipOFPNTDAR0SpzyzXaK59oqSPJ5VrZiQ3p8izVuRE9r1u2
i5PCcPYi39q101UIxV/WokS0mqHx/XuTYTwhWYd/C49OnM8MLZOUJd8w0VvS0ItY
/wAv4vk0ScS4KmXTJBBGSiBqLdroaM9VKcA1p7TN0vzlut2E/nKmBhgzQJFKZA==
-----END CERTIFICATE-----
"""
func makeTemporaryFile(fileExtension: String = "") -> String {
let template = "\(FileManager.default.temporaryDirectory.path)/niotestXXXXXXX\(fileExtension)"
var templateBytes = template.utf8 + [0]
let fd = templateBytes.withUnsafeMutableBufferPointer { ptr in
ptr.baseAddress!.withMemoryRebound(to: Int8.self, capacity: ptr.count) { (ptr: UnsafeMutablePointer<Int8>) in
return mkstemps(ptr, CInt(fileExtension.utf8.count))
}
}
close(fd)
templateBytes.removeLast()
return String(decoding: templateBytes, as: UTF8.self)
}
internal func dumpToFile(data: Data, fileExtension: String = "") throws -> String {
let filename = makeTemporaryFile(fileExtension: fileExtension)
try data.write(to: URL(fileURLWithPath: filename))
return filename
}
internal func dumpToFile(text: String, fileExtension: String = "") throws -> String {
return try dumpToFile(data: text.data(using: .utf8)!, fileExtension: fileExtension)
}
class SSLCertificateTest: XCTestCase {
static var pemCertFilePath: String! = nil
static var pemCertsFilePath: String! = nil
static var derCertFilePath: String! = nil
static var dynamicallyGeneratedCert: NIOSSLCertificate! = nil
override class func setUp() {
SSLCertificateTest.pemCertFilePath = try! dumpToFile(text: samplePemCert)
SSLCertificateTest.pemCertsFilePath = try! dumpToFile(text: samplePemCerts)
SSLCertificateTest.derCertFilePath = try! dumpToFile(data: sampleDerCert)
let (cert, _) = generateSelfSignedCert()
SSLCertificateTest.dynamicallyGeneratedCert = cert
}
override class func tearDown() {
_ = SSLCertificateTest.pemCertFilePath.withCString {
unlink($0)
}
_ = SSLCertificateTest.pemCertsFilePath.withCString {
unlink($0)
}
_ = SSLCertificateTest.derCertFilePath.withCString {
unlink($0)
}
}
private func dateFromComponents(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int) -> Date {
var date = DateComponents()
date.calendar = Calendar(identifier: .gregorian)
date.year = year
date.month = month
date.day = day
date.hour = hour
date.minute = minute
date.second = second
date.timeZone = TimeZone(abbreviation: "UTC")
return date.date!
}
func testLoadingPemCertFromFile() throws {
let cert1 = try NIOSSLCertificate(file: SSLCertificateTest.pemCertFilePath, format: .pem)
let cert2 = try NIOSSLCertificate(file: SSLCertificateTest.pemCertFilePath, format: .pem)
XCTAssertEqual(cert1, cert2)
XCTAssertEqual(cert1.hashValue, cert2.hashValue)
XCTAssertNotEqual(cert1, SSLCertificateTest.dynamicallyGeneratedCert)
XCTAssertNotEqual(cert1.hashValue, SSLCertificateTest.dynamicallyGeneratedCert.hashValue)
}
func testLoadingDerCertFromFile() throws {
let cert1 = try NIOSSLCertificate(file: SSLCertificateTest.derCertFilePath, format: .der)
let cert2 = try NIOSSLCertificate(file: SSLCertificateTest.derCertFilePath, format: .der)
XCTAssertEqual(cert1, cert2)
XCTAssertEqual(cert1.hashValue, cert2.hashValue)
XCTAssertNotEqual(cert1, SSLCertificateTest.dynamicallyGeneratedCert)
XCTAssertNotEqual(cert1.hashValue, SSLCertificateTest.dynamicallyGeneratedCert.hashValue)
}
func testDerAndPemAreIdentical() throws {
let cert1 = try NIOSSLCertificate(file: SSLCertificateTest.pemCertFilePath, format: .pem)
let cert2 = try NIOSSLCertificate(file: SSLCertificateTest.derCertFilePath, format: .der)
XCTAssertEqual(cert1, cert2)
XCTAssertEqual(cert1.hashValue, cert2.hashValue)
}
func testLoadingPemCertFromMemory() throws {
let cert1 = try NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem)
let cert2 = try NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem)
XCTAssertEqual(cert1, cert2)
XCTAssertEqual(cert1.hashValue, cert2.hashValue)
}
func testPemLoadingMechanismsAreIdentical() throws {
let cert11 = try NIOSSLCertificate.fromPEMBytes(.init(samplePemCert.utf8))
let cert12 = try NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem)
XCTAssertEqual(cert11, [cert12])
XCTAssertEqual(cert11.map { $0.hashValue }, [cert12.hashValue])
}
func testLoadingPemCertsFromMemory() throws {
let certs1 = try NIOSSLCertificate.fromPEMBytes(.init(samplePemCerts.utf8))
let certs2 = try NIOSSLCertificate.fromPEMBytes(.init(samplePemCerts.utf8))
XCTAssertEqual(certs1.count, 2)
XCTAssertEqual(certs1, certs2)
XCTAssertEqual(certs1.map { $0.hashValue }, certs2.map { $0.hashValue })
}
func testLoadingPemCertsFromFile() throws {
let certs1 = try NIOSSLCertificate.fromPEMFile(SSLCertificateTest.pemCertsFilePath)
let certs2 = try NIOSSLCertificate.fromPEMFile(SSLCertificateTest.pemCertsFilePath)
XCTAssertEqual(certs1.count, 2)
XCTAssertEqual(certs1, certs2)
XCTAssertEqual(certs1.map { $0.hashValue }, certs2.map { $0.hashValue })
}
func testLoadingDerCertFromMemory() throws {
let certBytes = [UInt8](sampleDerCert)
let cert1 = try NIOSSLCertificate(bytes: certBytes, format: .der)
let cert2 = try NIOSSLCertificate(bytes: certBytes, format: .der)
XCTAssertEqual(cert1, cert2)
XCTAssertEqual(cert1.hashValue, cert2.hashValue)
}
func testLoadingGibberishFromMemoryAsPemFails() throws {
let keyBytes: [UInt8] = [1, 2, 3]
XCTAssertThrowsError(try NIOSSLCertificate(bytes: keyBytes, format: .pem)) {error in
XCTAssertEqual(.failedToLoadCertificate, error as? NIOSSLError)
}
}
func testLoadingGibberishFromPEMBufferFails() throws {
let keyBytes: [UInt8] = [1, 2, 3]
XCTAssertThrowsError(try NIOSSLCertificate.fromPEMBytes(keyBytes)) {error in
XCTAssertEqual(.failedToLoadCertificate, error as? NIOSSLError)
}
}
func testLoadingGibberishFromMemoryAsDerFails() throws {
let keyBytes: [UInt8] = [1, 2, 3]
XCTAssertThrowsError(try NIOSSLCertificate(bytes: keyBytes, format: .der)) {error in
XCTAssertEqual(.failedToLoadCertificate, error as? NIOSSLError)
}
}
func testLoadingGibberishFromFileAsPemFails() throws {
let tempFile = try dumpToFile(text: "hello")
defer {
_ = tempFile.withCString { unlink($0) }
}
XCTAssertThrowsError(try NIOSSLCertificate(file: tempFile, format: .pem)) {error in
XCTAssertEqual(.failedToLoadCertificate, error as? NIOSSLError)
}
}
func testLoadingGibberishFromPEMFileFails() throws {
let tempFile = try dumpToFile(text: "hello")
defer {
_ = tempFile.withCString { unlink($0) }
}
XCTAssertThrowsError(try NIOSSLCertificate.fromPEMFile(tempFile)) {error in
XCTAssertEqual(.failedToLoadCertificate, error as? NIOSSLError)
}
}
func testLoadingGibberishFromFileAsDerFails() throws {
let tempFile = try dumpToFile(text: "hello")
defer {
_ = tempFile.withCString { unlink($0) }
}
XCTAssertThrowsError(try NIOSSLCertificate(file: tempFile, format: .der)) {error in
XCTAssertEqual(.failedToLoadCertificate, error as? NIOSSLError)
}
}
func testLoadingNonexistentFileAsPem() throws {
XCTAssertThrowsError(try NIOSSLCertificate(file: "/nonexistent/path", format: .pem)) {error in
XCTAssertEqual(ENOENT, (error as? IOError).map { $0.errnoCode })
}
}
func testLoadingNonexistentPEMFile() throws {
XCTAssertThrowsError(try NIOSSLCertificate.fromPEMFile("/nonexistent/path")) {error in
XCTAssertEqual(.failedToLoadCertificate, error as? NIOSSLError)
}
}
func testLoadingNonexistentFileAsDer() throws {
XCTAssertThrowsError(try NIOSSLCertificate(file: "/nonexistent/path", format: .der)) {error in
XCTAssertEqual(ENOENT, (error as? IOError).map { $0.errnoCode })
}
}
func testEnumeratingSanFields() throws {
var v4addr = in_addr()
var v6addr = in6_addr()
precondition(inet_pton(AF_INET, "192.168.0.1", &v4addr) == 1)
precondition(inet_pton(AF_INET6, "2001:db8::1", &v6addr) == 1)
let expectedSanFields: [NIOSSLCertificate.AlternativeName] = [
.dnsName(Array("localhost".utf8)),
.dnsName(Array("example.com".utf8)),
.ipAddress(.ipv4(v4addr)),
.ipAddress(.ipv6(v6addr)),
]
let cert = try NIOSSLCertificate(bytes: .init(multiSanCert.utf8), format: .pem)
let sans = [NIOSSLCertificate.AlternativeName](cert.subjectAlternativeNames()!)
XCTAssertEqual(sans.count, expectedSanFields.count)
for index in 0..<sans.count {
switch (sans[index], expectedSanFields[index]) {
case (.dnsName(let actualName), .dnsName(let expectedName)):
XCTAssertEqual(actualName, expectedName)
case (.ipAddress(.ipv4(var actualAddr)), .ipAddress(.ipv4(var expectedAddr))):
XCTAssertEqual(memcmp(&actualAddr, &expectedAddr, MemoryLayout<in_addr>.size), 0)
case (.ipAddress(.ipv6(var actualAddr)), .ipAddress(.ipv6(var expectedAddr))):
XCTAssertEqual(memcmp(&actualAddr, &expectedAddr, MemoryLayout<in6_addr>.size), 0)
default:
XCTFail("Invalid entry in sans.")
}
}
}
func testNonexistentSan() throws {
let cert = try NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem)
XCTAssertNil(cert.subjectAlternativeNames())
}
func testCommonName() throws {
let cert = try NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem)
XCTAssertEqual([UInt8]("robots.sanfransokyo.edu".utf8), cert.commonName()!)
}
func testCommonNameForGeneratedCert() throws {
XCTAssertEqual([UInt8]("localhost".utf8), SSLCertificateTest.dynamicallyGeneratedCert.commonName()!)
}
func testMultipleCommonNames() throws {
let cert = try NIOSSLCertificate(bytes: .init(multiCNCert.utf8), format: .pem)
XCTAssertEqual([UInt8]("localhost".utf8), cert.commonName()!)
}
func testNoCommonName() throws {
let cert = try NIOSSLCertificate(bytes: .init(noCNCert.utf8), format: .pem)
XCTAssertNil(cert.commonName())
}
func testUnicodeCommonName() throws {
let cert = try NIOSSLCertificate(bytes: .init(unicodeCNCert.utf8), format: .pem)
XCTAssertEqual([UInt8]("straße.org".utf8), cert.commonName()!)
}
func testExtractingPublicKey() throws {
let cert = try assertNoThrowWithValue(NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem))
let publicKey = try assertNoThrowWithValue(cert.extractPublicKey())
let spkiBytes = try assertNoThrowWithValue(publicKey.toSPKIBytes())
XCTAssertEqual(spkiBytes, sampleDerCertSPKI)
}
func testDumpingPEMCert() throws {
let expectedCertBytes = [UInt8](sampleDerCert)
let cert = try assertNoThrowWithValue(NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem))
let certBytes = try assertNoThrowWithValue(cert.toDERBytes())
XCTAssertEqual(certBytes, expectedCertBytes)
}
func testDumpingDERCert() throws {
let expectedCertBytes = [UInt8](sampleDerCert)
let cert = try assertNoThrowWithValue(NIOSSLCertificate(bytes: expectedCertBytes, format: .der))
let certBytes = try assertNoThrowWithValue(cert.toDERBytes())
XCTAssertEqual(certBytes, expectedCertBytes)
}
func testPrintingDebugDetailsNoAlternativeNames() throws {
let expectedDebugDescription = "<NIOSSLCertificate;serial_number=9fd7d05a34ca7984;common_name=robots.sanfransokyo.edu>"
let cert = try assertNoThrowWithValue(NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem))
let debugString = String(describing: cert)
XCTAssertEqual(debugString, expectedDebugDescription)
}
func testPrintingDebugDetailsWithAlternativeNames() throws {
let expectedDebugDescription = "<NIOSSLCertificate;serial_number=46231a526848d57af4999e29f89988d178d94da2;common_name=localhost;alternative_names=localhost,example.com,192.168.0.1,2001:db8::1>"
let cert = try assertNoThrowWithValue(NIOSSLCertificate(bytes: .init(multiSanCert.utf8), format: .pem))
let debugString = String(describing: cert)
XCTAssertEqual(debugString, expectedDebugDescription)
}
func testNotValidBefore() throws {
let cert = try NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem)
let notValidBeforeSeconds = cert.notValidBefore
let expectedDate = self.dateFromComponents(year: 2017, month: 10, day: 16, hour: 21, minute: 01, second: 02)
let expectedSeconds = time_t(expectedDate.timeIntervalSince1970)
XCTAssertEqual(notValidBeforeSeconds, expectedSeconds)
}
func testNotValidAfter() throws {
let cert = try NIOSSLCertificate(bytes: .init(samplePemCert.utf8), format: .pem)
let notValidBeforeSeconds = cert.notValidAfter
let expectedDate = self.dateFromComponents(year: 2047, month: 10, day: 9, hour: 21, minute: 01, second: 02)
let expectedSeconds = time_t(expectedDate.timeIntervalSince1970)
XCTAssertEqual(notValidBeforeSeconds, expectedSeconds)
}
func testNotBeforeAfterGeneratedCert() throws {
let notBefore = SSLCertificateTest.dynamicallyGeneratedCert.notValidBefore
let notAfter = SSLCertificateTest.dynamicallyGeneratedCert.notValidAfter
// Clock movement is tricky so we can't necessarily assert what the delta is in
// the notBefore and now, but we know now has to be between the two values, and
// that the two values are 1 hour apart.
let secondsNow = time_t(Date().timeIntervalSince1970)
XCTAssertTrue((notBefore..<notAfter).contains(secondsNow))
XCTAssertEqual(notAfter - notBefore, 60 * 60)
}
}
|