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
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftCertificates open source project
//
// Copyright (c) 2023 Apple Inc. and the SwiftCertificates project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftCertificates project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import XCTest
import SwiftASN1
import Crypto
import _CryptoExtras
@testable import X509
private protocol Key {
associatedtype Wrapped: WrappedKey
init(derRepresentation: some DataProtocol) throws
init(pemRepresentation: String) throws
var pemRepresentation: String { get }
var wrapped: Wrapped { get }
}
extension Key {
var pemDiscriminator: String {
get throws {
try PEMDocument(pemString: pemRepresentation).discriminator
}
}
}
// MARK: Private Keys
extension Crypto.P256.Signing.PrivateKey: Key {
var wrapped: Certificate.PrivateKey { .init(self) }
}
extension Crypto.P384.Signing.PrivateKey: Key {
var wrapped: Certificate.PrivateKey { .init(self) }
}
extension Crypto.P521.Signing.PrivateKey: Key {
var wrapped: Certificate.PrivateKey { .init(self) }
}
extension _CryptoExtras._RSA.Signing.PrivateKey: Key {
var wrapped: Certificate.PrivateKey { .init(self) }
}
// MARK: Public Keys
extension Crypto.P256.Signing.PublicKey: Key {
var wrapped: Certificate.PublicKey { .init(self) }
}
extension Crypto.P384.Signing.PublicKey: Key {
var wrapped: Certificate.PublicKey { .init(self) }
}
extension Crypto.P521.Signing.PublicKey: Key {
var wrapped: Certificate.PublicKey { .init(self) }
}
extension _CryptoExtras._RSA.Signing.PublicKey: Key {
var wrapped: Certificate.PublicKey { .init(self) }
}
private protocol WrappedKey: Equatable {
init(pemEncoded: String) throws
func serializeAsPEM() throws -> PEMDocument
}
extension Certificate.PublicKey: WrappedKey {}
extension Certificate.PrivateKey: WrappedKey {}
final class PEMTests: XCTestCase {
fileprivate func assertPEMRoundtrip(key: some Key, file: StaticString = #filePath, line: UInt = #line) throws {
let initialPEMString = key.pemRepresentation
let wrapped = try type(of: key).Wrapped(pemEncoded: initialPEMString)
XCTAssertEqual(key.wrapped, wrapped, "Wrapper mismatch after one roundtrip for \(key)", file: file, line: line)
let pemDocument = try key.wrapped.serializeAsPEM()
let initialPEMDocument = try PEMDocument(pemString: initialPEMString)
XCTAssertEqual(
pemDocument.discriminator,
initialPEMDocument.discriminator,
"PEM discriminator mismatch after one roundtrip for \(key)",
file: file,
line: line
)
XCTAssertEqual(
pemDocument.pemString,
initialPEMDocument.pemString,
"PEM string mismatch after one roundtrip for \(key)",
file: file,
line: line
)
}
func testPublicKeys() throws {
try assertPEMRoundtrip(key: P256.Signing.PrivateKey().publicKey)
try assertPEMRoundtrip(key: P384.Signing.PrivateKey().publicKey)
try assertPEMRoundtrip(key: P521.Signing.PrivateKey().publicKey)
try assertPEMRoundtrip(key: _RSA.Signing.PrivateKey(keySize: .bits2048).publicKey)
}
func testPrivateKeys() throws {
try assertPEMRoundtrip(key: P256.Signing.PrivateKey())
try assertPEMRoundtrip(key: P384.Signing.PrivateKey())
try assertPEMRoundtrip(key: P521.Signing.PrivateKey())
try assertPEMRoundtrip(key: _RSA.Signing.PrivateKey(keySize: .bits2048))
}
func testRSAPrivateKey() throws {
// generated with "openssl genpkey -algorithm rsa"
let rsaKey = try String(
contentsOf: XCTUnwrap(Bundle.module.url(forResource: "PEMTestRSACertificate", withExtension: "pem"))
)
let privateKey = try Certificate.PrivateKey(pemEncoded: rsaKey)
guard case .rsa = privateKey.backing else {
XCTFail("parsed as wrong key type \(privateKey)")
return
}
let privateKeyAfterRoundtrip = try Certificate.PrivateKey(pemDocument: privateKey.serializeAsPEM())
XCTAssertEqual(privateKey, privateKeyAfterRoundtrip)
}
}
|