Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions ASN1Decoder/ASN1Decoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,8 @@ public class ASN1DERDecoder {


case .octetString:
do {
var subIterator = contentData.makeIterator()
asn1obj.sub = try parse(iterator: &subIterator)
} catch {
if let str = String(data: contentData, encoding: .utf8) {
asn1obj.value = str
}
else {
asn1obj.value = contentData
}
}

asn1obj.value = contentData


default:
print("unsupported tag: \(asn1obj.identifier!.tagNumber())")
Expand Down
16 changes: 16 additions & 0 deletions ASN1Decoder/ASN1Object.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,19 @@ public class ASN1Object : CustomStringConvertible {
"2.5.4.9" : "streetAddress"
]
}

public class ASN1GeneralNames {
var otherName:String?
var rfc822Name:String?
var URI:String?

init(asn1Object: ASN1Object) {

switch asn1Object.identifier?.tagNumber().rawValue {
case 6:
self.URI = asn1Object.value as? String
default: break

}
}
}
182 changes: 182 additions & 0 deletions ASN1Decoder/X509Certificate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ public class X509Certificate: CustomStringConvertible {
return asn1.reduce("") { $0 + "\($1.description)\n" }
}

public var encodedTBSCertificate:Data? {
var length = UInt16(self.block1.rawValue!.count).bigEndian
return Data([UInt8(0x30),UInt8(0x82)]) + Data(bytes: &length, count: 2) + (self.block1.rawValue ?? Data())
}

public var encodedCertificate:Data? {
var length = UInt16(self.asn1[0].rawValue!.count).bigEndian
return Data([UInt8(0x30),UInt8(0x82)]) + Data(bytes: &length, count: 2) + (self.asn1[0].rawValue ?? Data())
}


/// Checks that the given date is within the certificate's validity period.
public func checkValidity(_ date: Date = Date()) -> Bool {
if let notBefore = notBefore, let notAfter = notAfter {
Expand Down Expand Up @@ -201,6 +212,9 @@ public class X509Certificate: CustomStringConvertible {
return nil
}




/**
Gets a boolean array representing bits of the KeyUsage extension, (OID = 2.5.29.15).
```
Expand Down Expand Up @@ -280,6 +294,64 @@ public class X509Certificate: CustomStringConvertible {
.map(X509Extension.init)
}


public var basicConstraints:X509ExtBasicContraints {
return X509ExtBasicContraints(extObject:extensionObject(oid: "2.5.29.19"))
}

public var authorityKeyIdentifier:X509ExtAuthorityKeyIdentifier {
return X509ExtAuthorityKeyIdentifier(asn1Object:(extensionObject(oid: "2.5.29.35")?.block)!)
}

public var subjectKeyIdentifier:Data? {
return extensionObject(oid: "2.5.29.14")?.block.sub?.last?.sub?.first?.rawValue ?? nil
}

public var crlDistributionPoints: [X509ExtCrlDistributionPoint] {
var result: [X509ExtCrlDistributionPoint] = []

guard let crlDistPointsObject = extensionObject(oid: "2.5.29.31") else {
return result
}


// instance of class
guard ((crlDistPointsObject.block.sub?.last?.sub?.last?.sub?.last)?.subCount())! > 0 else {
return result
}

for crlDistPointObject in ((crlDistPointsObject.block.sub?.last?.sub?.last?.sub!)!) {

result.append(X509ExtCrlDistributionPoint(asn1Object: crlDistPointObject))
}

return result
}



public var certificatePolicies: [X509ExtCertficatePolicy] {
var result: [X509ExtCertficatePolicy] = []

guard let certficatePoliciesObject = extensionObject(oid: "2.5.29.32") else {
return result
}


// instance of class
guard ((certficatePoliciesObject.block.sub?.last?.sub?.last)?.subCount())! > 0 else {
return result
}

for certficatePolicyObject in ((certficatePoliciesObject.block.sub?.last?.sub?.last?.sub!)!) {

result.append(X509ExtCertficatePolicy(asn1Object: certficatePolicyObject))
}

return result
}


// Format subject/issuer information in RFC1779
private func blockDistinguishedName(block: ASN1Object) -> String {
var result = ""
Expand Down Expand Up @@ -359,3 +431,113 @@ extension ASN1Object {
return sub[index.rawValue]
}
}





public class X509ExtCrlDistributionPoint {

var fullName:ASN1GeneralNames?
var nameRelativeToCRLIssuer:String?
var reasons:[Bool]?
var crlIssuer:ASN1GeneralNames?

init(asn1Object: ASN1Object) {

self.fullName = ASN1GeneralNames(asn1Object: (asn1Object.sub?.last?.sub?.last?.sub?.last)!)

}



// if let oidBlock = block1.findOid(OID_KeyUsage) {
// let data = oidBlock.parent?.sub?.last?.sub(0)?.value as? Data
// let bits: UInt8 = data?.first ?? 0
// for i in 0...7 {
// let value = bits & UInt8(1 << i) != 0
// result.insert(value, at: 0)
// }
// }

}


public class X509ExtCertficatePolicy{

var identifier:String?
var qualifierInfo:X509ExtCertficatePolicyQualifierInfo?

init(asn1Object: ASN1Object) {

self.identifier = (asn1Object.sub?[0].value as! String)

guard asn1Object.subCount() > 1 else {
return
}

self.qualifierInfo = X509ExtCertficatePolicyQualifierInfo(asn1Object: (asn1Object.sub?[1])!)

}
}


public class X509ExtCertficatePolicyQualifierInfo {

var identifier:String?
var qualifier:String?

init(asn1Object: ASN1Object) {

self.identifier = (asn1Object.sub?.first?.sub?.first?.value as! String)
self.qualifier = (asn1Object.sub?.first?.sub?.last?.value as! String)

}
}





public class X509ExtBasicContraints {

var isCA:Bool? = false
var pathLengthConstraint:Int? = nil



init(extObject: X509Extension?) {

if let cAValue = extObject?.valueAsBlock?.sub?.first?.sub?.first?.value {
self.isCA = (cAValue as! Bool)
}

if let pathValue = extObject?.valueAsBlock?.sub?.first?.sub?.last?.value {
self.pathLengthConstraint = (pathValue as! Int)
}
}
}


public class X509ExtAuthorityKeyIdentifier{

var identifier:Data?
var issuer:ASN1GeneralNames?
var serialNumber:String?

init(asn1Object: ASN1Object) {


guard asn1Object.subCount() > 1 else {
return
}

self.identifier = (asn1Object.sub?[1].sub?.first?.sub?.first?.value as! Data)

guard (asn1Object.sub?[1].sub?.first?.subCount())! > 1 else {
return
}
self.issuer = ASN1GeneralNames(asn1Object: (asn1Object.sub?[1].sub?.first?.sub?[1])!)

}
}
45 changes: 39 additions & 6 deletions ASN1Decoder/X509Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,17 @@ public class X509Extension {

let block: ASN1Object

init(block: ASN1Object) {
init(block: ASN1Object) {

do {
let extBlock = try ASN1DERDecoder.decode(data: block.sub?.last?.rawValue ?? Data())
extBlock[0].parent = block.sub?.last
block.sub?.last?.sub = extBlock
}
catch {

}

self.block = block
}

Expand Down Expand Up @@ -56,14 +66,37 @@ public class X509Extension {
var valueAsBlock: ASN1Object? {
return block.sub?.last
}

var valueAsStrings: [String] {
var result: [String] = []
for item in block.sub?.last?.sub?.last?.sub ?? [] {
if let name = item.value as? String {
result.append(name)
var result: [String] = []
for item in block.sub?.last?.sub?.last?.sub ?? [] {
if let name = item.value as? String {
result.append(name)
}
}
return result
}

var values: [Any] {
return self.findLeafs(asn1object: self.valueAsBlock)
}

public func findLeafs(asn1object:ASN1Object?) -> [Any] {

var result:[Any] = []
for child in asn1object?.sub ?? [] {
if let value = child.value {
result.append(value)
}
else {
result = result+(findLeafs(asn1object: child))
}
}
return result
}

}




66 changes: 65 additions & 1 deletion ASN1Decoder/X509PublicKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,42 @@ public class X509PublicKey {
private let OID_ECPublicKey = "1.2.840.10045.2.1"
private let OID_RSAEncryption = "1.2.840.113549.1.1.1"

private static let beginPemBlock = "-----BEGIN PUBLIC KEY-----"
private static let endPemBlock = "-----END PUBLIC KEY-----"

var asn1:[ASN1Object]
var pkBlock: ASN1Object!

init(pkBlock: ASN1Object) {
init(pkBlock: ASN1Object) {
self.asn1 = [pkBlock]
self.pkBlock = pkBlock
}

public convenience init(data: Data) throws {
if String(data: data, encoding: .utf8)?.contains(X509PublicKey.beginPemBlock) ?? false {
try self.init(pem: data)
} else {
try self.init(der: data)
}
}

public init(der: Data) throws {
asn1 = try ASN1DERDecoder.decode(data: der)
guard asn1.count > 0,
let pkBlock = asn1.first?.sub(1) else {
throw ASN1Error.parseError
}
self.pkBlock = pkBlock
}

public convenience init(pem: Data) throws {
guard let derData = X509PublicKey.decodeToDER(pem: pem) else {
throw ASN1Error.parseError
}

try self.init(der: derData)
}

public var algOid: String? {
return pkBlock.sub(0)?.sub(0)?.value as? String
}
Expand Down Expand Up @@ -70,4 +100,38 @@ public class X509PublicKey {
return nil
}
}

func encodedKey() -> Data? {
let keyData = self.asn1.first?.rawValue
var length = UInt16(keyData!.count).bigEndian
return Data([UInt8(0x30),UInt8(0x82)]) + Data(bytes: &length, count: 2) + (keyData!)
}

// read possibile PEM encoding
private static func decodeToDER(pem pemData: Data) -> Data? {
if
let pem = String(data: pemData, encoding: .ascii),
pem.contains(beginPemBlock) {

let lines = pem.components(separatedBy: .newlines)
var base64buffer = ""
var certLine = false
for line in lines {
if line == endPemBlock {
certLine = false
}
if certLine {
base64buffer.append(line)
}
if line == beginPemBlock {
certLine = true
}
}
if let derDataDecoded = Data(base64Encoded: base64buffer) {
return derDataDecoded
}
}

return nil
}
}
Loading