cbaker6 / CertificateSigningRequest

@@ -48,7 +48,7 @@
Loading
48 48
let sequenceObjectSHA512WithECEncryption: [UInt8] =
49 49
    [0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04]
50 50
51 -
//Enums
51 +
// Enums
52 52
public enum KeyAlgorithm {
53 53
    // swiftlint:disable:next identifier_name
54 54
    case rsa(signatureType: Signature), ec(signatureType: Signature)

@@ -34,63 +34,122 @@
Loading
34 34
import Security
35 35
#endif
36 36
37 +
public enum SubjectItem {
38 +
    case commonName(String), organizationName(String), organizationUnitName(String),
39 +
         countryName(String), stateOrProvinceName(String), serialNumber(String),
40 +
         localityName(String), description(String), emailAddress(String)
41 +
42 +
    func getObjectKey() -> [UInt8] {
43 +
        switch self {
44 +
        case .commonName:
45 +
            return [0x06, 0x03, 0x55, 0x04, 0x03]
46 +
        case .organizationName:
47 +
            return [0x06, 0x03, 0x55, 0x04, 0x0A]
48 +
        case .organizationUnitName:
49 +
            return [0x06, 0x03, 0x55, 0x04, 0x0B]
50 +
        case .countryName:
51 +
            return [0x06, 0x03, 0x55, 0x04, 0x06]
52 +
        case .stateOrProvinceName:
53 +
            return [0x06, 0x03, 0x55, 0x04, 0x08]
54 +
        case .serialNumber:
55 +
            return [0x06, 0x03, 0x55, 0x04, 0x05]
56 +
        case .localityName:
57 +
            return [0x06, 0x03, 0x55, 0x04, 0x07]
58 +
        case .description:
59 +
            return [0x06, 0x03, 0x55, 0x04, 0x0D]
60 +
        case .emailAddress:
61 +
            return [0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01]
62 +
        }
63 +
    }
64 +
65 +
    func getValue() -> String {
66 +
        switch self {
67 +
        case .commonName(let value):
68 +
            return value
69 +
        case .organizationName(let value):
70 +
            return value
71 +
        case .organizationUnitName(let value):
72 +
            return value
73 +
        case .countryName(let value):
74 +
            return value
75 +
        case .stateOrProvinceName(let value):
76 +
            return value
77 +
        case .serialNumber(let value):
78 +
            return value
79 +
        case .localityName(let value):
80 +
            return value
81 +
        case .description(let value):
82 +
            return value
83 +
        case .emailAddress(let value):
84 +
            return value
85 +
        }
86 +
    }
87 +
}
88 +
37 89
// swiftlint:disable:next type_body_length
38 90
public class CertificateSigningRequest: NSObject {
39 -
    private let objectCommonName: [UInt8] = [0x06, 0x03, 0x55, 0x04, 0x03]
40 -
    private let objectCountryName: [UInt8] = [0x06, 0x03, 0x55, 0x04, 0x06]
41 -
    private let objectDescription: [UInt8] = [0x06, 0x03, 0x55, 0x04, 0x0D]
42 -
    private let objectEmailAddress: [UInt8] = [0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01]
43 -
    private let objectLocalityName: [UInt8] = [0x06, 0x03, 0x55, 0x04, 0x07]
44 -
    private let objectOrganizationName: [UInt8] = [0x06, 0x03, 0x55, 0x04, 0x0A]
45 -
    private let objectOrganizationalUnitName: [UInt8] = [0x06, 0x03, 0x55, 0x04, 0x0B]
46 -
    private let objectStateOrProvinceName: [UInt8] = [0x06, 0x03, 0x55, 0x04, 0x08]
47 -
    private let objectSerialNumber: [UInt8] = [0x06, 0x03, 0x55, 0x04, 0x05]
48 91
    private let sequenceTag: UInt8 = 0x30
49 92
    private let setTag: UInt8 = 0x31
50 -
    private let commonName: String?
51 -
    private let countryName: String?
52 -
    private let emailAddress: String?
53 -
    private let csrDescription: String?
54 -
    private let localityName: String?
55 -
    private let organizationName: String?
56 -
    private let organizationUnitName: String?
57 -
    private let stateOrProvinceName: String?
58 -
    private let serialNumber: String?
59 -
    private var keyAlgorithm: KeyAlgorithm!
93 +
    private var subjectItems: [SubjectItem] = []
94 +
    private let keyAlgorithm: KeyAlgorithm
60 95
    private var subjectDER: Data?
61 96
62 -
    public init(commonName: String? = nil, organizationName: String? = nil,
63 -
                organizationUnitName: String? = nil, countryName: String? = nil,
64 -
                stateOrProvinceName: String? = nil, localityName: String? = nil,
65 -
                serialNumber: String? = nil, emailAddress: String? = nil,
66 -
                description: String? = nil, keyAlgorithm: KeyAlgorithm) {
67 -
        self.commonName = commonName
68 -
        self.organizationName = organizationName
69 -
        self.organizationUnitName = organizationUnitName
70 -
        self.countryName = countryName
71 -
        self.stateOrProvinceName = stateOrProvinceName
72 -
        self.serialNumber = serialNumber
73 -
        self.localityName = localityName
74 -
        self.emailAddress = emailAddress
75 -
        self.csrDescription = description
97 +
    public init(keyAlgorithm: KeyAlgorithm) {
76 98
        self.keyAlgorithm = keyAlgorithm
77 99
        super.init()
78 100
    }
79 101
80 102
    public convenience override init() {
81 -
        self.init(commonName: nil, organizationName: nil, organizationUnitName: nil,
82 -
                  countryName: nil, stateOrProvinceName: nil, localityName: nil,
83 -
                  serialNumber: nil, keyAlgorithm: KeyAlgorithm.rsa(signatureType: .sha512))
103 +
        self.init(keyAlgorithm: KeyAlgorithm.rsa(signatureType: .sha512))
104 +
    }
105 +
106 +
    public convenience init(commonName: String? = nil,
107 +
                            organizationName: String? = nil,
108 +
                            organizationUnitName: String? = nil,
109 +
                            countryName: String? = nil,
110 +
                            stateOrProvinceName: String? = nil,
111 +
                            localityName: String? = nil,
112 +
                            serialNumber: String? = nil,
113 +
                            emailAddress: String? = nil,
114 +
                            description: String? = nil,
115 +
                            keyAlgorithm: KeyAlgorithm) {
116 +
        self.init(keyAlgorithm: keyAlgorithm)
117 +
118 +
        if let commonName = commonName {
119 +
            self.addSubjectItem(.commonName(commonName))
120 +
        }
121 +
        if let organizationName = organizationName {
122 +
            self.addSubjectItem(.organizationName(organizationName))
123 +
        }
124 +
        if let organizationUnitName = organizationUnitName {
125 +
            self.addSubjectItem(.organizationUnitName(organizationUnitName))
126 +
        }
127 +
        if let countryName = countryName {
128 +
            self.addSubjectItem(.countryName(countryName))
129 +
        }
130 +
        if let stateOrProvinceName = stateOrProvinceName {
131 +
            self.addSubjectItem(.stateOrProvinceName(stateOrProvinceName))
132 +
        }
133 +
        if let localityName = localityName {
134 +
            self.addSubjectItem(.localityName(localityName))
135 +
        }
136 +
        if let emailAddress = emailAddress {
137 +
            self.addSubjectItem(.emailAddress(emailAddress))
138 +
        }
139 +
        if let description = description {
140 +
            self.addSubjectItem(.description(description))
141 +
        }
142 +
        if let serialNumber = serialNumber {
143 +
            self.addSubjectItem(.serialNumber(serialNumber))
144 +
        }
84 145
    }
85 146
86 -
    public convenience init(keyAlgorithm: KeyAlgorithm) {
87 -
        self.init(commonName: nil, organizationName: nil, organizationUnitName: nil,
88 -
                  countryName: nil, stateOrProvinceName: nil, localityName: nil,
89 -
                  serialNumber: nil, keyAlgorithm: keyAlgorithm)
147 +
    public func addSubjectItem(_ subjectItem: SubjectItem) {
148 +
        subjectItems.append(subjectItem)
90 149
    }
91 150
92 151
    public func build(_ publicKeyBits: Data, privateKey: SecKey, publicKey: SecKey?=nil) -> Data? {
93 -
        let certificationRequestInfo = buldCertificationRequestInfo(publicKeyBits)
152 +
        let certificationRequestInfo = buildCertificationRequestInfo(publicKeyBits)
94 153
        var signature = [UInt8](repeating: 0, count: 256)
95 154
        var signatureLen: Int = signature.count
96 155
@@ -129,16 +188,15 @@
Loading
129 188
        return certificationRequest
130 189
    }
131 190
132 -
    public func buildAndEncodeDataAsString(_ publicKeyBits: Data, privateKey: SecKey,
191 +
    public func buildAndEncodeDataAsString(_ publicKeyBits: Data,
192 +
                                           privateKey: SecKey,
133 193
                                           publicKey: SecKey?=nil) -> String? {
134 -
135 194
        guard let buildData = self.build(publicKeyBits, privateKey: privateKey, publicKey: publicKey) else {
136 195
            return nil
137 196
        }
138 197
139 198
        return buildData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
140 199
            .addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
141 -
142 200
    }
143 201
144 202
    public func buildCSRAndReturnString(_ publicKeyBits: Data, privateKey: SecKey, publicKey: SecKey?=nil) -> String? {
@@ -176,7 +234,7 @@
Loading
176 234
        return newCSRString
177 235
    }
178 236
179 -
    func buldCertificationRequestInfo(_ publicKeyBits: Data) -> Data {
237 +
    func buildCertificationRequestInfo(_ publicKeyBits: Data) -> Data {
180 238
        var certificationRequestInfo = Data(capacity: 256)
181 239
182 240
        // Add version
@@ -186,40 +244,13 @@
Loading
186 244
        // Add subject
187 245
        var subject = Data(capacity: 256)
188 246
189 -
        if let countryName = countryName {
190 -
            appendSubjectItem(objectCountryName, value: countryName, into: &subject)
191 -
        }
192 -
193 -
        if let stateOrProvinceName = stateOrProvinceName {
194 -
            appendSubjectItem(objectStateOrProvinceName, value: stateOrProvinceName, into: &subject)
195 -
        }
196 -
197 -
        if let localityName = localityName {
198 -
            appendSubjectItem(objectLocalityName, value: localityName, into: &subject)
199 -
        }
200 -
201 -
        if let organizationName = organizationName {
202 -
            appendSubjectItem(objectOrganizationName, value: organizationName, into: &subject)
203 -
        }
204 -
205 -
        if let organizationUnitName = organizationUnitName {
206 -
            appendSubjectItem(objectOrganizationalUnitName, value: organizationUnitName, into: &subject)
207 -
        }
208 -
209 -
        if let commonName = commonName {
210 -
            appendSubjectItem(objectCommonName, value: commonName, into: &subject)
211 -
        }
212 -
213 -
        if let emailAddress = emailAddress {
214 -
            appendSubjectItemEmail(objectEmailAddress, value: emailAddress, into: &subject)
215 -
        }
216 -
217 -
        if let description = csrDescription {
218 -
            appendSubjectItem(objectDescription, value: description, into: &subject)
219 -
        }
220 -
        
221 -
        if let serialNumber = serialNumber {
222 -
            appendSubjectItem(objectSerialNumber, value: serialNumber, into: &subject)
247 +
        for subjectItem in subjectItems {
248 +
            switch subjectItem {
249 +
            case let .emailAddress(emailAddress):
250 +
                appendSubjectItemEmail(subjectItem.getObjectKey(), value: emailAddress, into: &subject)
251 +
            default:
252 +
                appendSubjectItem(subjectItem.getObjectKey(), value: subjectItem.getValue(), into: &subject)
253 +
            }
223 254
        }
224 255
225 256
        enclose(&subject, by: sequenceTag)// Enclose into SEQUENCE
@@ -243,7 +274,7 @@
Loading
243 274
244 275
        var publicKeyInfo = Data(capacity: 390)
245 276
246 -
        switch keyAlgorithm! {
277 +
        switch keyAlgorithm {
247 278
        case .rsa:
248 279
            publicKeyInfo.append(objectRSAEncryptionNULL, count: objectRSAEncryptionNULL.count)
249 280
        case .ec:
@@ -254,7 +285,7 @@
Loading
254 285
        enclose(&publicKeyInfo, by: sequenceTag) // Enclose into SEQUENCE
255 286
256 287
        var publicKeyASN = Data(capacity: 260)
257 -
        switch keyAlgorithm! {
288 +
        switch keyAlgorithm {
258 289
        case .ec:
259 290
            let key = getPublicKey(publicKeyBits)
260 291
            publicKeyASN.append(key)
Files Coverage
Sources/CertificateSigningRequest 91.99%
Project Totals (2 files) 91.99%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading