Skip to content

Commit 0d95324

Browse files
committed
Un-namespace the extensions.
We've received API review feedback that is critical of us having the extensions inside a namespace. This patch extracts them from that namespace.
1 parent aaafa59 commit 0d95324

19 files changed

+802
-818
lines changed

Sources/X509/CryptographicMessageSyntax/CMSSignerIdentifier.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ enum CMSSignerIdentifier: DERParseable, DERSerializable, Hashable {
2525
private static let skiIdentifier = ASN1Identifier(tagWithNumber: 0, tagClass: .contextSpecific)
2626

2727
case issuerAndSerialNumber(CMSIssuerAndSerialNumber)
28-
case subjectKeyIdentifier(Certificate.Extensions.SubjectKeyIdentifier)
28+
case subjectKeyIdentifier(SubjectKeyIdentifier)
2929

3030
init(derEncoded node: ASN1Node) throws {
3131
switch node.identifier {

Sources/X509/Docs.docc/Creating Certificates.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ We can use the helpful builder syntax for this:
9494
```swift
9595
let extensions = try Certificate.Extensions {
9696
Critical(
97-
Certificate.Extensions.BasicConstraints.isCertificateAuthority(maxPathLength: nil)
97+
BasicConstraints.isCertificateAuthority(maxPathLength: nil)
9898
)
9999
Critical(
100-
Certificate.Extensions.KeyUsage(digitalSignature: true, keyCertSign: true)
100+
KeyUsage(digitalSignature: true, keyCertSign: true)
101101
)
102-
Certificate.Extensions.SubjectAlternativeNames([.dNSName("localhost")])
102+
SubjectAlternativeNames([.dNSName("localhost")])
103103
}
104104
```
105105

@@ -152,12 +152,12 @@ let now = Date()
152152

153153
let extensions = try Certificate.Extensions {
154154
Critical(
155-
Certificate.Extensions.BasicConstraints.isCertificateAuthority(maxPathLength: nil)
155+
BasicConstraints.isCertificateAuthority(maxPathLength: nil)
156156
)
157157
Critical(
158-
Certificate.Extensions.KeyUsage(keyCertSign: true)
158+
KeyUsage(keyCertSign: true)
159159
)
160-
Certificate.Extensions.SubjectAlternativeNames([.dNSName("localhost")])
160+
SubjectAlternativeNames([.dNSName("localhost")])
161161
}
162162

163163
let certificate = try Certificate(

Sources/X509/Docs.docc/Examining Certificates.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ for the ``Certificate/Extensions-swift.struct/SubjectAlternativeNames-swift.stru
114114
```swift
115115
let opaqueSANExtension = certificate.extensions.first(where: { $0.oid == .X509ExtensionID.subjectAlternativeName })
116116
if let opaqueSanExtension {
117-
let unwrappedSanExtension = try Certificate.Extensions.SubjectAlternativeName(opaqueSanExtension)
117+
let unwrappedSanExtension = try SubjectAlternativeName(opaqueSanExtension)
118118
}
119119
```
120120

@@ -123,7 +123,7 @@ to search for a specific extension. The above code could be replaced by:
123123

124124
```swift
125125
if let opaqueSanExtension = certificate.extensions[oid: .X509ExtensionID.subjectAlternativeName] {
126-
let unwrappedSanExtension = try Certificate.Extensions.SubjectAlternativeName(opaqueSanExtension)
126+
let unwrappedSanExtension = try SubjectAlternativeName(opaqueSanExtension)
127127
}
128128
```
129129

Sources/X509/Extension Types/AuthorityInformationAccess.swift

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,53 @@
1414

1515
import SwiftASN1
1616

17-
extension Certificate.Extensions {
18-
/// Provides details on how to access information about the certificate issuer.
19-
///
20-
/// This extension behaves as a collection of ``Certificate/Extensions-swift.struct/AuthorityInformationAccess-swift.struct/AccessDescription`` objects.
17+
/// Provides details on how to access information about the certificate issuer.
18+
///
19+
/// This extension behaves as a collection of ``Certificate/Extensions-swift.struct/AuthorityInformationAccess-swift.struct/AccessDescription`` objects.
20+
///
21+
/// In practice this most commonly contains OCSP servers and links to the issuing CA certificate.
22+
public struct AuthorityInformationAccess {
23+
@usableFromInline
24+
var descriptions: [AccessDescription]
25+
26+
/// Create a new ``Certificate/Extensions-swift.struct/AuthorityInformationAccess-swift.struct/`` object
27+
/// containing specific access descriptions.
2128
///
22-
/// In practice this most commonly contains OCSP servers and links to the issuing CA certificate.
23-
public struct AuthorityInformationAccess {
24-
@usableFromInline
25-
var descriptions: [AccessDescription]
29+
/// - Parameter descriptions: The descriptions to include in the AIA extension.
30+
@inlinable
31+
public init<Descriptions: Sequence>(_ descriptions: Descriptions) where Descriptions.Element == AccessDescription {
32+
self.descriptions = Array(descriptions)
33+
}
2634

27-
/// Create a new ``Certificate/Extensions-swift.struct/AuthorityInformationAccess-swift.struct/`` object
28-
/// containing specific access descriptions.
29-
///
30-
/// - Parameter descriptions: The descriptions to include in the AIA extension.
31-
@inlinable
32-
public init<Descriptions: Sequence>(_ descriptions: Descriptions) where Descriptions.Element == AccessDescription {
33-
self.descriptions = Array(descriptions)
35+
/// Create a new ``Certificate/Extensions-swift.struct/AuthorityInformationAccess-swift.struct`` object
36+
/// by unwrapping a ``Certificate/Extension``.
37+
///
38+
/// - Parameter ext: The ``Certificate/Extension`` to unwrap
39+
/// - Throws: if the ``Certificate/Extension/oid`` is not equal to
40+
/// `ASN1ObjectIdentifier.X509ExtensionID.authorityInformationAccess`.
41+
@inlinable
42+
public init(_ ext: Certificate.Extension) throws {
43+
guard ext.oid == .X509ExtensionID.authorityInformationAccess else {
44+
throw CertificateError.incorrectOIDForExtension(reason: "Expected \(ASN1ObjectIdentifier.X509ExtensionID.authorityInformationAccess), got \(ext.oid)")
3445
}
3546

36-
/// Create a new ``Certificate/Extensions-swift.struct/AuthorityInformationAccess-swift.struct`` object
37-
/// by unwrapping a ``Certificate/Extension``.
38-
///
39-
/// - Parameter ext: The ``Certificate/Extension`` to unwrap
40-
/// - Throws: if the ``Certificate/Extension/oid`` is not equal to
41-
/// `ASN1ObjectIdentifier.X509ExtensionID.authorityInformationAccess`.
42-
@inlinable
43-
public init(_ ext: Certificate.Extension) throws {
44-
guard ext.oid == .X509ExtensionID.authorityInformationAccess else {
45-
throw CertificateError.incorrectOIDForExtension(reason: "Expected \(ASN1ObjectIdentifier.X509ExtensionID.authorityInformationAccess), got \(ext.oid)")
46-
}
47-
48-
let aiaSyntax = try AuthorityInfoAccessSyntax(derEncoded: ext.value)
49-
self.descriptions = aiaSyntax.descriptions.map { AccessDescription($0) }
50-
}
47+
let aiaSyntax = try AuthorityInfoAccessSyntax(derEncoded: ext.value)
48+
self.descriptions = aiaSyntax.descriptions.map { AccessDescription($0) }
5149
}
5250
}
5351

54-
extension Certificate.Extensions.AuthorityInformationAccess: Hashable { }
52+
extension AuthorityInformationAccess: Hashable { }
5553

56-
extension Certificate.Extensions.AuthorityInformationAccess: Sendable { }
54+
extension AuthorityInformationAccess: Sendable { }
5755

58-
extension Certificate.Extensions.AuthorityInformationAccess: CustomStringConvertible {
56+
extension AuthorityInformationAccess: CustomStringConvertible {
5957
public var description: String {
6058
return self.map { String(describing: $0) }.joined(separator: ", ")
6159
}
6260
}
6361

6462
// TODO(cory): Probably also RangeReplaceableCollection, even though it's kinda crap.
65-
extension Certificate.Extensions.AuthorityInformationAccess: RandomAccessCollection {
63+
extension AuthorityInformationAccess: RandomAccessCollection {
6664
@inlinable
6765
public var startIndex: Int {
6866
self.descriptions.startIndex
@@ -85,7 +83,7 @@ extension Certificate.Extensions.AuthorityInformationAccess: RandomAccessCollect
8583
}
8684
}
8785

88-
extension Certificate.Extensions.AuthorityInformationAccess {
86+
extension AuthorityInformationAccess {
8987
/// Describes the location and format of additional information provided
9088
/// by the issuer of a given certificate.
9189
public struct AccessDescription {
@@ -110,17 +108,17 @@ extension Certificate.Extensions.AuthorityInformationAccess {
110108
}
111109
}
112110

113-
extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription: Hashable { }
111+
extension AuthorityInformationAccess.AccessDescription: Hashable { }
114112

115-
extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription: Sendable { }
113+
extension AuthorityInformationAccess.AccessDescription: Sendable { }
116114

117-
extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription: CustomStringConvertible {
115+
extension AuthorityInformationAccess.AccessDescription: CustomStringConvertible {
118116
public var description: String {
119117
return "\(self.method): \(self.location)"
120118
}
121119
}
122120

123-
extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription {
121+
extension AuthorityInformationAccess.AccessDescription {
124122
/// The format and meaning of the information included in a single
125123
/// ``Certificate/Extensions-swift.struct/AuthorityInformationAccess-swift.struct/AccessDescription``
126124
/// object.
@@ -160,11 +158,11 @@ extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription {
160158
}
161159
}
162160

163-
extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription.AccessMethod: Hashable { }
161+
extension AuthorityInformationAccess.AccessDescription.AccessMethod: Hashable { }
164162

165-
extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription.AccessMethod: Sendable { }
163+
extension AuthorityInformationAccess.AccessDescription.AccessMethod: Sendable { }
166164

167-
extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription.AccessMethod: CustomStringConvertible {
165+
extension AuthorityInformationAccess.AccessDescription.AccessMethod: CustomStringConvertible {
168166
@inlinable
169167
public var description: String {
170168
switch self.backing {
@@ -178,9 +176,9 @@ extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription.Ac
178176
}
179177
}
180178

181-
extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription.AccessMethod.Backing: Hashable { }
179+
extension AuthorityInformationAccess.AccessDescription.AccessMethod.Backing: Hashable { }
182180

183-
extension Certificate.Extensions.AuthorityInformationAccess.AccessDescription.AccessMethod.Backing: Sendable { }
181+
extension AuthorityInformationAccess.AccessDescription.AccessMethod.Backing: Sendable { }
184182

185183
extension Certificate.Extension {
186184
/// Construct an opaque ``Certificate/Extension`` from this AIA extension.
@@ -189,15 +187,15 @@ extension Certificate.Extension {
189187
/// - aia: The extension to wrap
190188
/// - critical: Whether this extension should have the critical bit set.
191189
@inlinable
192-
public init(_ aia: Certificate.Extensions.AuthorityInformationAccess, critical: Bool) throws {
190+
public init(_ aia: AuthorityInformationAccess, critical: Bool) throws {
193191
let asn1Representation = AuthorityInfoAccessSyntax(aia)
194192
var serializer = DER.Serializer()
195193
try serializer.serialize(asn1Representation)
196194
self.init(oid: .X509ExtensionID.authorityInformationAccess, critical: critical, value: serializer.serializedBytes[...])
197195
}
198196
}
199197

200-
extension Certificate.Extensions.AuthorityInformationAccess: CertificateExtensionConvertible {
198+
extension AuthorityInformationAccess: CertificateExtensionConvertible {
201199
public func makeCertificateExtension() throws -> Certificate.Extension {
202200
return try .init(self, critical: false)
203201
}
@@ -222,7 +220,7 @@ struct AuthorityInfoAccessSyntax: DERImplicitlyTaggable {
222220
var descriptions: [AIAAccessDescription]
223221

224222
@inlinable
225-
init(_ aia: Certificate.Extensions.AuthorityInformationAccess) {
223+
init(_ aia: AuthorityInformationAccess) {
226224
self.descriptions = aia.descriptions.map { .init($0) }
227225
}
228226

@@ -261,7 +259,7 @@ struct AIAAccessDescription: DERImplicitlyTaggable {
261259
}
262260

263261
@inlinable
264-
init(_ description: Certificate.Extensions.AuthorityInformationAccess.AccessDescription) {
262+
init(_ description: AuthorityInformationAccess.AccessDescription) {
265263
self.accessMethod = ASN1ObjectIdentifier(accessMethod: description.method)
266264
self.accessLocation = description.location
267265
}
@@ -295,7 +293,7 @@ extension ASN1ObjectIdentifier {
295293
}
296294

297295
@inlinable
298-
public init(accessMethod: Certificate.Extensions.AuthorityInformationAccess.AccessDescription.AccessMethod) {
296+
public init(accessMethod: AuthorityInformationAccess.AccessDescription.AccessMethod) {
299297
switch accessMethod.backing {
300298
case .ocspServer:
301299
self = .AccessMethodIdentifiers.ocspServer

Sources/X509/Extension Types/AuthorityKeyIdentifier.swift

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -14,60 +14,58 @@
1414

1515
import SwiftASN1
1616

17-
extension Certificate.Extensions {
18-
/// Provides information about the public key corresponding to the private key that was
19-
/// used to sign a specific certificate.
20-
public struct AuthorityKeyIdentifier {
21-
/// An opaque sequence of bytes uniquely derived from the public key of the issuing
22-
/// CA.
23-
///
24-
/// This is commonly a hash of the subject public key info from the issuing certificate.
25-
public var keyIdentifier: ArraySlice<UInt8>?
26-
27-
/// The name of the issuer of the issuing cert.
28-
public var authorityCertIssuer: [GeneralName]?
29-
30-
/// The serial number of the issuing cert.
31-
public var authorityCertSerialNumber: Certificate.SerialNumber?
32-
33-
/// Create a new ``Certificate/Extensions-swift.struct/AuthorityKeyIdentifier-swift.struct`` extension value.
34-
///
35-
/// - Parameters:
36-
/// - keyIdentifier: An opaque sequence of bytes uniquely derived from the public key of the issuing CA.
37-
/// - authorityCertIssuer: The name of the issuer of the issuing cert.
38-
/// - authorityCertSerialNumber: The serial number of the issuing cert.
39-
@inlinable
40-
public init(keyIdentifier: ArraySlice<UInt8>? = nil, authorityCertIssuer: [GeneralName]? = nil, authorityCertSerialNumber: Certificate.SerialNumber? = nil) {
41-
self.keyIdentifier = keyIdentifier
42-
self.authorityCertIssuer = authorityCertIssuer
43-
self.authorityCertSerialNumber = authorityCertSerialNumber
44-
}
17+
/// Provides information about the public key corresponding to the private key that was
18+
/// used to sign a specific certificate.
19+
public struct AuthorityKeyIdentifier {
20+
/// An opaque sequence of bytes uniquely derived from the public key of the issuing
21+
/// CA.
22+
///
23+
/// This is commonly a hash of the subject public key info from the issuing certificate.
24+
public var keyIdentifier: ArraySlice<UInt8>?
25+
26+
/// The name of the issuer of the issuing cert.
27+
public var authorityCertIssuer: [GeneralName]?
28+
29+
/// The serial number of the issuing cert.
30+
public var authorityCertSerialNumber: Certificate.SerialNumber?
4531

46-
/// Create a new ``Certificate/Extensions-swift.struct/AuthorityKeyIdentifier-swift.struct`` object
47-
/// by unwrapping a ``Certificate/Extension``.
48-
///
49-
/// - Parameter ext: The ``Certificate/Extension`` to unwrap
50-
/// - Throws: if the ``Certificate/Extension/oid`` is not equal to
51-
/// `ASN1ObjectIdentifier.X509ExtensionID.authorityKeyIdentifier`.
52-
@inlinable
53-
public init(_ ext: Certificate.Extension) throws {
54-
guard ext.oid == .X509ExtensionID.authorityKeyIdentifier else {
55-
throw CertificateError.incorrectOIDForExtension(reason: "Expected \(ASN1ObjectIdentifier.X509ExtensionID.authorityKeyIdentifier), got \(ext.oid)")
56-
}
57-
58-
let asn1KeyIdentifier = try AuthorityKeyIdentifierValue(derEncoded: ext.value)
59-
self.keyIdentifier = asn1KeyIdentifier.keyIdentifier.map { $0.bytes }
60-
self.authorityCertIssuer = asn1KeyIdentifier.authorityCertIssuer
61-
self.authorityCertSerialNumber = asn1KeyIdentifier.authorityCertSerialNumber.map { Certificate.SerialNumber(bytes: $0) }
32+
/// Create a new ``Certificate/Extensions-swift.struct/AuthorityKeyIdentifier-swift.struct`` extension value.
33+
///
34+
/// - Parameters:
35+
/// - keyIdentifier: An opaque sequence of bytes uniquely derived from the public key of the issuing CA.
36+
/// - authorityCertIssuer: The name of the issuer of the issuing cert.
37+
/// - authorityCertSerialNumber: The serial number of the issuing cert.
38+
@inlinable
39+
public init(keyIdentifier: ArraySlice<UInt8>? = nil, authorityCertIssuer: [GeneralName]? = nil, authorityCertSerialNumber: Certificate.SerialNumber? = nil) {
40+
self.keyIdentifier = keyIdentifier
41+
self.authorityCertIssuer = authorityCertIssuer
42+
self.authorityCertSerialNumber = authorityCertSerialNumber
43+
}
44+
45+
/// Create a new ``Certificate/Extensions-swift.struct/AuthorityKeyIdentifier-swift.struct`` object
46+
/// by unwrapping a ``Certificate/Extension``.
47+
///
48+
/// - Parameter ext: The ``Certificate/Extension`` to unwrap
49+
/// - Throws: if the ``Certificate/Extension/oid`` is not equal to
50+
/// `ASN1ObjectIdentifier.X509ExtensionID.authorityKeyIdentifier`.
51+
@inlinable
52+
public init(_ ext: Certificate.Extension) throws {
53+
guard ext.oid == .X509ExtensionID.authorityKeyIdentifier else {
54+
throw CertificateError.incorrectOIDForExtension(reason: "Expected \(ASN1ObjectIdentifier.X509ExtensionID.authorityKeyIdentifier), got \(ext.oid)")
6255
}
56+
57+
let asn1KeyIdentifier = try AuthorityKeyIdentifierValue(derEncoded: ext.value)
58+
self.keyIdentifier = asn1KeyIdentifier.keyIdentifier.map { $0.bytes }
59+
self.authorityCertIssuer = asn1KeyIdentifier.authorityCertIssuer
60+
self.authorityCertSerialNumber = asn1KeyIdentifier.authorityCertSerialNumber.map { Certificate.SerialNumber(bytes: $0) }
6361
}
6462
}
6563

66-
extension Certificate.Extensions.AuthorityKeyIdentifier: Hashable { }
64+
extension AuthorityKeyIdentifier: Hashable { }
6765

68-
extension Certificate.Extensions.AuthorityKeyIdentifier: Sendable { }
66+
extension AuthorityKeyIdentifier: Sendable { }
6967

70-
extension Certificate.Extensions.AuthorityKeyIdentifier: CustomStringConvertible {
68+
extension AuthorityKeyIdentifier: CustomStringConvertible {
7169
public var description: String {
7270
var elements: [String] = []
7371

@@ -94,15 +92,15 @@ extension Certificate.Extension {
9492
/// - aki: The extension to wrap
9593
/// - critical: Whether this extension should have the critical bit set.
9694
@inlinable
97-
public init(_ aki: Certificate.Extensions.AuthorityKeyIdentifier, critical: Bool) throws {
95+
public init(_ aki: AuthorityKeyIdentifier, critical: Bool) throws {
9896
let asn1Representation = AuthorityKeyIdentifierValue(aki)
9997
var serializer = DER.Serializer()
10098
try serializer.serialize(asn1Representation)
10199
self.init(oid: .X509ExtensionID.authorityKeyIdentifier, critical: critical, value: serializer.serializedBytes[...])
102100
}
103101
}
104102

105-
extension Certificate.Extensions.AuthorityKeyIdentifier: CertificateExtensionConvertible {
103+
extension AuthorityKeyIdentifier: CertificateExtensionConvertible {
106104
public func makeCertificateExtension() throws -> Certificate.Extension {
107105
return try .init(self, critical: false)
108106
}
@@ -133,7 +131,7 @@ struct AuthorityKeyIdentifierValue: DERImplicitlyTaggable {
133131
}
134132

135133
@inlinable
136-
init(_ aki: Certificate.Extensions.AuthorityKeyIdentifier) {
134+
init(_ aki: AuthorityKeyIdentifier) {
137135
self.keyIdentifier = aki.keyIdentifier.map { ASN1OctetString(contentBytes: $0) }
138136
self.authorityCertIssuer = aki.authorityCertIssuer
139137
self.authorityCertSerialNumber = aki.authorityCertSerialNumber.map { $0.bytes }

0 commit comments

Comments
 (0)