1 // swiftlint:disable all
2 //
3 //  ASN1Encoder.swift
4 //  ASN1Decoder
5 //
6 //  Copyright © 2020 Filippo Maguolo.
7 //
8 //  Permission is hereby granted, free of charge, to any person obtaining a copy
9 //  of this software and associated documentation files (the "Software"), to deal
10 //  in the Software without restriction, including without limitation the rights
11 //  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 //  copies of the Software, and to permit persons to whom the Software is
13 //  furnished to do so, subject to the following conditions:
14 //
15 //  The above copyright notice and this permission notice shall be included in all
16 //  copies or substantial portions of the Software.
17 //
18 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 //  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 //  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 //  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 //  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 //  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 //  SOFTWARE.
25 
26 import Foundation
27 
28 public class ASN1DEREncoder {
29 
encodeSequencenull30     public static func encodeSequence(content: Data) -> Data {
31         var encoded = Data()
32         encoded.append(ASN1Identifier.constructedTag | ASN1Identifier.TagNumber.sequence.rawValue)
33         encoded.append(contentLength(of: content.count))
34         encoded.append(content)
35         return encoded
36     }
37 
contentLengthnull38     private static func contentLength(of size: Int) -> Data {
39         if size >= 128 {
40             var lenBytes = byteArray(from: size)
41             while lenBytes.first == 0 { lenBytes.removeFirst() }
42             let len: UInt8 = 0x80 | UInt8(lenBytes.count)
43             return Data([len] + lenBytes)
44         } else {
45             return Data([UInt8(size)])
46         }
47     }
48 
byteArray<T>null49     private static func byteArray<T>(from value: T) -> [UInt8] where T: FixedWidthInteger {
50         return withUnsafeBytes(of: value.bigEndian, Array.init)
51     }
52 
53 }
54 
55 extension Data {
56     public var derEncodedSequence: Data {
57         return ASN1DEREncoder.encodeSequence(content: self)
58     }
59 }
60 // swiftlint:enable all
61