Skip to content

Commit

Permalink
Fix of public key data extraction
Browse files Browse the repository at this point in the history
  • Loading branch information
filom committed Apr 5, 2018
1 parent 9f4a34c commit 394b406
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 33 deletions.
2 changes: 1 addition & 1 deletion ASN1Decoder.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "ASN1Decoder"
s.version = "1.1"
s.version = "1.2"
s.summary = "ASN1 DER Decoder for X.509 certificate"
s.description = "ASN1 DER Decoder to parse X.509 certificate"
s.homepage = "https://github.com/filom/ASN1Decoder"
Expand Down
6 changes: 5 additions & 1 deletion ASN1Decoder.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 0920;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = "Filippo Maguolo";
TargetAttributes = {
412A9E371F55C6500099110C = {
Expand Down Expand Up @@ -261,13 +261,15 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
Expand Down Expand Up @@ -321,13 +323,15 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand All @@ -26,7 +26,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
Expand Down Expand Up @@ -56,7 +55,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
Expand Down
31 changes: 22 additions & 9 deletions ASN1Decoder/X509Certificate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -380,18 +380,31 @@ public class PublicKey {
}

public var key: Data? {
if let keyBlock = pkBlock.sub?.last {
if let keyBlockValue = firstLeafValue(block: keyBlock) as? Data {
do {
let asn1PkBlock = try ASN1DERDecoder.decode(data: keyBlockValue)
return firstLeafValue(block: asn1PkBlock[0]) as? Data
} catch {
return keyBlockValue
}
guard let algOid = algOid, let keyData = pkBlock.sub(1)?.value as? Data else {
return nil
}

switch algOid {

case OID_ECPublicKey:
return keyData

case OID_RSAEncryption:
guard let publicKeyAsn1Objects = (try? ASN1DERDecoder.decode(data: keyData)) else {
return nil
}
guard let publicKeyModulus = publicKeyAsn1Objects.first?.sub(0)?.value as? Data else {
return nil
}
return publicKeyModulus

default:
return nil
}
return nil
}

private let OID_ECPublicKey = "1.2.840.10045.2.1"
private let OID_RSAEncryption = "1.2.840.113549.1.1.1"
}


Expand Down
62 changes: 43 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ ASN1 DER Decoder for X.509 Certificate

## Requirements

- iOS 8.0+ | macOS 10.10+
- Xcode 8
- iOS 9.0+ | macOS 10.10+
- Xcode 9

## Integration

Expand Down Expand Up @@ -39,17 +39,17 @@ import ASN1Decoder

do {
let x509 = try X509Certificate(data: certData)

let subject = x509.subjectDistinguishedName ?? ""

} catch {
print(error)
}
```



### Usage for SSL pinning
### Usage for SSL pinning

Define a delegate for URLSession

Expand All @@ -58,53 +58,53 @@ import Security
import ASN1Decoder

class PinningURLSessionDelegate: NSObject, URLSessionDelegate {

var publicKeyHexEncoded: String!

public init(publicKeyHexEncoded: String) {
self.publicKeyHexEncoded = publicKeyHexEncoded.uppercased()
}

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {

if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
if let serverTrust = challenge.protectionSpace.serverTrust {
var secresult = SecTrustResultType.invalid
let status = SecTrustEvaluate(serverTrust, &secresult)

if status == errSecSuccess {

if let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) {

let serverCertificateCFData = SecCertificateCopyData(serverCertificate)
let data = CFDataGetBytePtr(serverCertificateCFData)
let size = CFDataGetLength(serverCertificateCFData)
let certData = NSData(bytes: data, length: size)

do {
let x509cert = try X509Certificate(data: certData as Data)

if let pk = x509cert.publicKey?.key {

let serverPkHexEncoded = dataToHexString(pk)

if publicKeyHexEncoded == serverPkHexEncoded {
completionHandler(.useCredential, URLCredential(trust:serverTrust))
return
}
}

} catch {
print(error)
}
}
}
}
}

completionHandler(.cancelAuthenticationChallenge, nil)
}

func dataToHexString(_ data: Data) -> String {
return data.map { String(format: "%02X", $0) }.joined()
}
Expand All @@ -129,3 +129,27 @@ To extract the public key from your certificate with openssl use this command li
```
openssl x509 -modulus -noout < certificate.cer
```


### How to use for AppStore receipt parse

``` swift
import ASN1Decoder

if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {

do {
let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)

let pkcs7 = try PKCS7(data: receiptData)

if let receiptInfo = pkcs7.receipt() {
print(receiptInfo.originalApplicationVersion)
}

} catch {
print(error)
}
}
```

0 comments on commit 394b406

Please sign in to comment.