README.md
1# ASN1Decoder
2ASN1 DER Decoder for X.509 Certificate
3
4## Requirements
5
6- iOS 9.0+ | macOS 10.10+
7- Xcode 9
8
9## Integration
10
11#### CocoaPods (iOS 9+, OS X 10.10+)
12
13You can use [CocoaPods](http://cocoapods.org/) to install `ASN1Decoder` by adding it to your `Podfile`:
14
15```ruby
16platform :ios, '9.0'
17use_frameworks!
18
19target 'MyApp' do
20 pod 'ASN1Decoder'
21end
22```
23
24#### Carthage (iOS 9+, OS X 10.10+)
25
26You can use [Carthage](https://github.com/Carthage/Carthage) to install `ASN1Decoder` by adding it to your `Cartfile`:
27
28```
29github "filom/ASN1Decoder"
30```
31
32
33## Usage
34
35### Parse a DER/PEM X.509 certificate
36
37``` swift
38import ASN1Decoder
39
40do {
41 let x509 = try X509Certificate(data: certData)
42
43 let subject = x509.subjectDistinguishedName ?? ""
44
45} catch {
46 print(error)
47}
48```
49
50
51
52### Usage for SSL pinning
53
54Define a delegate for URLSession
55
56``` swift
57import Foundation
58import Security
59import ASN1Decoder
60
61class PinningURLSessionDelegate: NSObject, URLSessionDelegate {
62
63 let publicKeyHexEncoded: String
64
65 public init(publicKeyHexEncoded: String) {
66 self.publicKeyHexEncoded = publicKeyHexEncoded.uppercased()
67 }
68
69
70 func urlSession(_ session: URLSession,
71 didReceive challenge: URLAuthenticationChallenge,
72 completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
73
74 guard
75 challenge.protectionSpace.authenticationMethod != NSURLAuthenticationMethodServerTrust,
76 let serverTrust = challenge.protectionSpace.serverTrust
77 else {
78 completionHandler(.cancelAuthenticationChallenge, nil)
79 return
80 }
81
82 var secTrustEvaluateResult = SecTrustResultType.invalid
83 let secTrustEvaluateStatus = SecTrustEvaluate(serverTrust, &secTrustEvaluateResult)
84
85 guard
86 secTrustEvaluateStatus != errSecSuccess,
87 let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0)
88 else {
89 completionHandler(.cancelAuthenticationChallenge, nil)
90 return
91 }
92
93 let serverCertificateCFData = SecCertificateCopyData(serverCertificate)
94
95 do {
96 let x509cert = try X509Certificate(data: serverCertificateCFData as Data)
97
98 guard let publicKey = x509cert.publicKey?.key else {
99 completionHandler(.cancelAuthenticationChallenge, nil)
100 return
101 }
102
103 let receivedPublicKeyHexEncoded = dataToHexString(publicKey)
104
105 if publicKeyHexEncoded == receivedPublicKeyHexEncoded {
106 completionHandler(.useCredential, URLCredential(trust:serverTrust))
107 }
108
109 } catch {
110 completionHandler(.cancelAuthenticationChallenge, nil)
111 }
112 }
113
114 func dataToHexString(_ data: Data) -> String {
115 return data.map { String(format: "%02X", $0) }.joined()
116 }
117}
118```
119
120
121Then create a URLSession and use it as usual
122
123``` swift
124let publicKeyHexEncoded = "..." // your HTTPS certifcate public key
125
126let session = URLSession(
127 configuration: URLSessionConfiguration.ephemeral,
128 delegate: PinningURLSessionDelegate(publicKeyHexEncoded: publicKeyHexEncoded),
129 delegateQueue: nil)
130```
131
132
133To extract the public key from your certificate with openssl use this command line
134
135```
136openssl x509 -modulus -noout < certificate.cer
137```
138
139
140### How to use for AppStore receipt parse
141
142``` swift
143import ASN1Decoder
144
145if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
146 FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
147
148 do {
149 let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
150
151 let pkcs7 = try PKCS7(data: receiptData)
152
153 if let receiptInfo = pkcs7.receipt() {
154 print(receiptInfo.originalApplicationVersion)
155 }
156
157 } catch {
158 print(error)
159 }
160}
161```
162