diff --git a/CryptoLoadExternalCertificate.xcodeproj/project.pbxproj b/CryptoLoadExternalCertificate.xcodeproj/project.pbxproj index 98337f8..6dc6c93 100644 --- a/CryptoLoadExternalCertificate.xcodeproj/project.pbxproj +++ b/CryptoLoadExternalCertificate.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 53; objects = { /* Begin PBXBuildFile section */ @@ -155,7 +155,8 @@ 668B94CC1BC3D19F00913B83 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0800; + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = "Ignacio Nieto Carvajal"; TargetAttributes = { 668B94D31BC3D19F00913B83 = { @@ -172,7 +173,7 @@ }; buildConfigurationList = 668B94CF1BC3D19F00913B83 /* Build configuration list for PBXProject "CryptoLoadExternalCertificate" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -246,14 +247,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 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_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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -276,7 +286,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -292,14 +302,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 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_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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -316,10 +335,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -331,10 +351,13 @@ CODE_SIGN_ENTITLEMENTS = CryptoLoadExternalCertificate/CryptoLoadExternalCertificate.entitlements; DEVELOPMENT_TEAM = 97P9DZHP78; INFOPLIST_FILE = CryptoLoadExternalCertificate/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "com.Ignacio-Nieto-Carvajal.CryptoLoadExternalCertificate"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -345,10 +368,13 @@ CODE_SIGN_ENTITLEMENTS = CryptoLoadExternalCertificate/CryptoLoadExternalCertificate.entitlements; DEVELOPMENT_TEAM = 97P9DZHP78; INFOPLIST_FILE = CryptoLoadExternalCertificate/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "com.Ignacio-Nieto-Carvajal.CryptoLoadExternalCertificate"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/CryptoLoadExternalCertificate.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/CryptoLoadExternalCertificate.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/CryptoLoadExternalCertificate.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/CryptoLoadExternalCertificate/AppDelegate.swift b/CryptoLoadExternalCertificate/AppDelegate.swift index 5909dea..5aa7604 100644 --- a/CryptoLoadExternalCertificate/AppDelegate.swift +++ b/CryptoLoadExternalCertificate/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } diff --git a/CryptoLoadExternalCertificate/CryptoExportImportManager.swift b/CryptoLoadExternalCertificate/CryptoExportImportManager.swift index febebb7..cbed136 100644 --- a/CryptoLoadExternalCertificate/CryptoExportImportManager.swift +++ b/CryptoLoadExternalCertificate/CryptoExportImportManager.swift @@ -3,88 +3,92 @@ // CryptoExportImportManager // // Created by Ignacio Nieto Carvajal on 6/10/15. +// Adopted by Nikolay Kapsutin on 6/29/23 // Copyright © 2015 Ignacio Nieto Carvajal. All rights reserved. // -import UIKit +import Foundation +import Security -/* +/** This file originated from https://github.com/DigitalLeaves/CryptoExportImportManager/tree/master **/ -EC keys: http://www.opensource.apple.com/source/security_certtool/security_certtool-55103/src/dumpasn1.cfg +/** + * This class exists due to the easy and intuitive way of using public keys generated outside iOS in + * the Security framework and CommonCrypto tools (yes, I'm being sarcastic here). + * CryptoCertificateImportManager is in charge of importing a certificate and obtaining a valid key + * reference to use in any of SecKey operations (SecKeyEncrypt, SecKeyRawVerify...). + * As far as I know, any other way of importing and using public keys from the outside is not + * advised: https://devforums.apple.com/message/301532#301532 + */ +enum CryptoExportImportManager { + /* -EC param 1 -OID = 06 07 2A 86 48 CE 3D 02 01 -Comment = ANSI X9.62 public key type -Description = ecPublicKey (1 2 840 10045 2 1) + EC keys: http://www.opensource.apple.com/source/security_certtool/security_certtool-55103/src/dumpasn1.cfg -EC param 2 -OID = 06 08 2A 86 48 CE 3D 03 01 07 -Comment = ANSI X9.62 named elliptic curve -Description = ansiX9p256r1 (1 2 840 10045 3 1 7) + EC param 1 + OID = 06 07 2A 86 48 CE 3D 02 01 + Comment = ANSI X9.62 public key type + Description = ecPublicKey (1 2 840 10045 2 1) -OID = 06 05 2B 81 04 00 22 -Comment = SECG (Certicom) named elliptic curve -Description = secp384r1 (1 3 132 0 34) + EC param 2 + OID = 06 08 2A 86 48 CE 3D 03 01 07 + Comment = ANSI X9.62 named elliptic curve + Description = ansiX9p256r1 (1 2 840 10045 3 1 7) -OID = 06 05 2B 81 04 00 23 -Comment = SECG (Certicom) named elliptic curve -Description = secp521r1 (1 3 132 0 35) + OID = 06 05 2B 81 04 00 22 + Comment = SECG (Certicom) named elliptic curve + Description = secp384r1 (1 3 132 0 34) -EC params sequence: public key + curve 256r1 -30 13 06 07 2A 86 48 CE 3D 02 01 06 08 2A 86 48 CE 3D 03 01 07 -*/ + OID = 06 05 2B 81 04 00 23 + Comment = SECG (Certicom) named elliptic curve + Description = secp521r1 (1 3 132 0 35) -// SECP256R1 EC public key header (length + EC params (sequence) + bitstring -private let kCryptoExportImportManagerSecp256r1CurveLen = 256 -private let kCryptoExportImportManagerSecp256r1header: [UInt8] = [0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00] -private let kCryptoExportImportManagerSecp256r1headerLen = 26 + EC params sequence: public key + curve 256r1 + 30 13 06 07 2A 86 48 CE 3D 02 01 06 08 2A 86 48 CE 3D 03 01 07 + */ -private let kCryptoExportImportManagerSecp384r1CurveLen = 384 -private let kCryptoExportImportManagerSecp384r1header: [UInt8] = [0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00] -private let kCryptoExportImportManagerSecp384r1headerLen = 23 + // SECP256R1 EC public key header (length + EC params (sequence) + bitstring + private static let kCryptoExportImportManagerSecp256r1CurveLen = 256 + private static let kCryptoExportImportManagerSecp256r1header: [UInt8] = [0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00] + private static let kCryptoExportImportManagerSecp256r1headerLen = 26 -private let kCryptoExportImportManagerSecp521r1CurveLen = 521 -private let kCryptoExportImportManagerSecp521r1header: [UInt8] = [0x30, 0x81, 0x9B, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86, 0x00] -private let kCryptoExportImportManagerSecp521r1headerLen = 25 + private static let kCryptoExportImportManagerSecp384r1CurveLen = 384 + private static let kCryptoExportImportManagerSecp384r1header: [UInt8] = [0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00] + private static let kCryptoExportImportManagerSecp384r1headerLen = 23 -/* + private static let kCryptoExportImportManagerSecp521r1CurveLen = 521 + private static let kCryptoExportImportManagerSecp521r1header: [UInt8] = [0x30, 0x81, 0x9B, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86, 0x00] + private static let kCryptoExportImportManagerSecp521r1headerLen = 25 -RSA keys: http://www.opensource.apple.com/source/security_certtool/security_certtool-55103/src/dumpasn1.cfg + /* -OID = 06 09 2A 86 48 86 F7 0D 01 01 01 -Comment = PKCS #1 -Description = rsaEncryption (1 2 840 113549 1 1 1) + RSA keys: http://www.opensource.apple.com/source/security_certtool/security_certtool-55103/src/dumpasn1.cfg -NULL byte: 05 00 -*/ + OID = 06 09 2A 86 48 86 F7 0D 01 01 01 + Comment = PKCS #1 + Description = rsaEncryption (1 2 840 113549 1 1 1) -// RSA OID header -private let kCryptoExportImportManagerRSAOIDHeader: [UInt8] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00] -private let kCryptoExportImportManagerRSAOIDHeaderLength = 15 + NULL byte: 05 00 + */ -// ASN.1 encoding parameters. -private let kCryptoExportImportManagerASNHeaderSequenceMark: UInt8 = 48 // 0x30 -private let kCryptoExportImportManagerASNHeaderIntegerMark: UInt8 = 02 // 0x32 -private let kCryptoExportImportManagerASNHeaderBitstringMark: UInt8 = 03 //0x03 -private let kCryptoExportImportManagerASNHeaderNullMark: UInt8 = 05 //0x05 -private let kCryptoExportImportManagerASNHeaderRSAEncryptionObjectMark: UInt8 = 06 //0x06 -private let kCryptoExportImportManagerExtendedLengthMark: UInt8 = 128 // 0x80 -private let kCryptoExportImportManagerASNHeaderLengthForRSA = 15 + // RSA OID header + private static let kCryptoExportImportManagerRSAOIDHeader: [UInt8] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00] + private static let kCryptoExportImportManagerRSAOIDHeaderLength = 15 -// PEM encoding constants -private let kCryptoExportImportManagerPublicKeyInitialTag = "-----BEGIN PUBLIC KEY-----\n" -private let kCryptoExportImportManagerPublicKeyFinalTag = "-----END PUBLIC KEY-----" -private let kCryptoExportImportManagerPublicNumberOfCharactersInALine = 64 + // ASN.1 encoding parameters. + private static let kCryptoExportImportManagerASNHeaderSequenceMark: UInt8 = 48 // 0x30 + private static let kCryptoExportImportManagerASNHeaderIntegerMark: UInt8 = 02 // 0x32 + private static let kCryptoExportImportManagerASNHeaderBitstringMark: UInt8 = 03 //0x03 + private static let kCryptoExportImportManagerASNHeaderNullMark: UInt8 = 05 //0x05 + private static let kCryptoExportImportManagerASNHeaderRSAEncryptionObjectMark: UInt8 = 06 //0x06 + private static let kCryptoExportImportManagerExtendedLengthMark: UInt8 = 128 // 0x80 + private static let kCryptoExportImportManagerASNHeaderLengthForRSA = 15 + + // PEM encoding constants + private static let kCryptoExportImportManagerPublicKeyInitialTag = "-----BEGIN PUBLIC KEY-----\n" + private static let kCryptoExportImportManagerPublicKeyFinalTag = "-----END PUBLIC KEY-----" + private static let kCryptoExportImportManagerPublicNumberOfCharactersInALine = 64 -/** - * This class exists due to the easy and intuitive way of using public keys generated outside iOS in - * the Security framework and CommonCrypto tools (yes, I'm being sarcastic here). - * CryptoCertificateImportManager is in charge of importing a certificate and obtaining a valid key - * reference to use in any of SecKey operations (SecKeyEncrypt, SecKeyRawVerify...). - * As far as I know, any other way of importing and using public keys from the outside is not - * advised: https://devforums.apple.com/message/301532#301532 - */ -class CryptoExportImportManager: NSObject { // MARK: - Import methods. /** @@ -92,7 +96,7 @@ class CryptoExportImportManager: NSObject { * used in any of SecKey operations (SecKeyEncrypt, SecKeyRawVerify...). * Receives the certificate data in DER format. */ - func importPublicKeyReferenceFromDERCertificate(_ certData: Data) -> SecKey? { + static func importPublicKeyReferenceFromDERCertificate(_ certData: Data) -> SecKey? { // first we create the certificate reference guard let certRef = SecCertificateCreateWithData(nil, certData as CFData) else { return nil } print("Successfully generated a valid certificate reference from the data.") @@ -102,15 +106,31 @@ class CryptoExportImportManager: NSObject { let secTrustStatus = SecTrustCreateWithCertificates(certRef, nil, &secTrust) print("Generating a SecTrust reference from the certificate: \(secTrustStatus)") if secTrustStatus != errSecSuccess { return nil } + guard let secTrust = secTrust else {return nil} // now evaluate the certificate. var resultType: SecTrustResultType = SecTrustResultType(rawValue: UInt32(0))! // result will be ignored. - let evaluateStatus = SecTrustEvaluate(secTrust!, &resultType) - print("Evaluating the obtained SecTrust reference: \(evaluateStatus)") - if evaluateStatus != errSecSuccess { return nil } + + if #available(iOS 14, *) { + if SecTrustEvaluateWithError(secTrust, nil) == false { + print("Evaluating the obtained SecTrust reference has been failed!") + return nil + } + } + else { + let evaluateStatus = SecTrustEvaluate(secTrust, &resultType) + print("Evaluating the obtained SecTrust reference: \(evaluateStatus)") + if evaluateStatus != errSecSuccess { return nil } + } // lastly, once evaluated, we can export the public key from the certificate leaf. - let publicKeyRef = SecTrustCopyPublicKey(secTrust!) + let publicKeyRef:SecKey? + if #available(iOS 14, *) { + publicKeyRef = SecTrustCopyKey(secTrust) + } + else { + publicKeyRef = SecTrustCopyPublicKey(secTrust) + } print("Got public key reference: \(String(describing: publicKeyRef))") return publicKeyRef } @@ -121,7 +141,7 @@ class CryptoExportImportManager: NSObject { * Exports a key retrieved from the keychain so it can be used outside iOS (i.e: in OpenSSL). * Returns a DER representation of the key. */ - func exportPublicKeyToDER(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> Data? { + static func exportPublicKeyToDER(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> Data? { if keyType == kSecAttrKeyTypeEC as String { return exportECPublicKeyToDER(rawPublicKeyBytes, keyType: keyType, keySize: keySize) } else if keyType == kSecAttrKeyTypeRSA as String { @@ -135,7 +155,7 @@ class CryptoExportImportManager: NSObject { * Exports a key retrieved from the keychain so it can be used outside iOS (i.e: in OpenSSL). * Returns a PEM representation of the key. */ - func exportPublicKeyToPEM(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> String? { + static func exportPublicKeyToPEM(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> String? { if keyType == kSecAttrKeyTypeEC as String { return exportECPublicKeyToPEM(rawPublicKeyBytes, keyType: keyType, keySize: keySize) } else if keyType == kSecAttrKeyTypeRSA as String { @@ -151,7 +171,7 @@ class CryptoExportImportManager: NSObject { * keys in a very raw format. If we want to use it on OpenSSL, PHP or almost anywhere outside iOS, we * need to remove add the full PKCS#1 ASN.1 wrapping. Returns a DER representation of the key. */ - func exportRSAPublicKeyToDER(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> Data { + static func exportRSAPublicKeyToDER(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> Data { // first we create the space for the ASN.1 header and decide about its length let bitstringEncodingLength = bytesNeededForRepresentingInteger(rawPublicKeyBytes.count) @@ -186,7 +206,7 @@ class CryptoExportImportManager: NSObject { * keys in a very raw format. If we want to use it on OpenSSL, PHP or almost anywhere outside iOS, we * need to remove add the full PKCS#1 ASN.1 wrapping. Returns a DER representation of the key. */ - func exportRSAPublicKeyToPEM(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> String { + static func exportRSAPublicKeyToPEM(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> String { return PEMKeyFromDERKey(exportRSAPublicKeyToDER(rawPublicKeyBytes, keyType: keyType, keySize: keySize)) } @@ -194,7 +214,7 @@ class CryptoExportImportManager: NSObject { /** * Returns the number of bytes needed to represent an integer. */ - func bytesNeededForRepresentingInteger(_ number: Int) -> Int { + static func bytesNeededForRepresentingInteger(_ number: Int) -> Int { if number <= 0 { return 0 } var i = 1 while (i < 8 && number >= (1 << (i * 8))) { i += 1 } @@ -206,7 +226,7 @@ class CryptoExportImportManager: NSObject { * writing the ASN.1 sequence. The memory of buffer must be initialized (i.e: from an NSData). * Returns the number of bytes used to write the sequence. */ - func encodeASN1LengthParameter(_ length: Int, buffer: UnsafeMutablePointer) -> Int { + static func encodeASN1LengthParameter(_ length: Int, buffer: UnsafeMutablePointer) -> Int { if length < Int(kCryptoExportImportManagerExtendedLengthMark) { buffer[0] = UInt8(length) return 1 // just one byte was used, no need for length starting mark (0x80). @@ -230,7 +250,7 @@ class CryptoExportImportManager: NSObject { * header and codifies the result as valid base64 string, 64 characters split. * Returns a DER representation of the key. */ - func exportECPublicKeyToDER(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> Data { + static func exportECPublicKeyToDER(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> Data { print("Exporting EC raw key: \(rawPublicKeyBytes)") // first retrieve the header with the OID for the proper key curve. let curveOIDHeader: [UInt8] @@ -262,7 +282,7 @@ class CryptoExportImportManager: NSObject { * header and codifies the result as valid base64 string, 64 characters split. * Returns a DER representation of the key. */ - func exportECPublicKeyToPEM(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> String { + static func exportECPublicKeyToPEM(_ rawPublicKeyBytes: Data, keyType: String, keySize: Int) -> String { return PEMKeyFromDERKey(exportECPublicKeyToDER(rawPublicKeyBytes, keyType: keyType, keySize: keySize)) } @@ -271,7 +291,7 @@ class CryptoExportImportManager: NSObject { * the key and then splits this base64 string in 64 character chunks. Then it wraps it in * BEGIN and END key tags. */ - func PEMKeyFromDERKey(_ data: Data) -> String { + static func PEMKeyFromDERKey(_ data: Data) -> String { // base64 encode the result let base64EncodedString = data.base64EncodedString(options: []) diff --git a/CryptoLoadExternalCertificate/ExportViewController.swift b/CryptoLoadExternalCertificate/ExportViewController.swift index 9a378d0..39b9f3c 100644 --- a/CryptoLoadExternalCertificate/ExportViewController.swift +++ b/CryptoLoadExternalCertificate/ExportViewController.swift @@ -66,11 +66,10 @@ class ExportViewController: UIViewController { func exportKeyFromRawBytesAndShowInTextView(_ rawBytes: Data) { let keyType = getKeyTypeFromSegmentedControl() let keySize = getKeyLengthFromSegmentedControl() - let exportImportManager = CryptoExportImportManager() - if let exportableDERKey = exportImportManager.exportPublicKeyToDER(rawBytes, keyType: keyType, keySize: keySize) { + if let exportableDERKey = CryptoExportImportManager.exportPublicKeyToDER(rawBytes, keyType: keyType, keySize: keySize) { self.textView.text = self.textView.text + "Exportable key in DER format:\n\(exportableDERKey.hexDescription)\n\n" print("Exportable key in DER format:\n\(exportableDERKey.hexDescription)\n") - let exportablePEMKey = exportImportManager.PEMKeyFromDERKey(exportableDERKey) + let exportablePEMKey = CryptoExportImportManager.PEMKeyFromDERKey(exportableDERKey) self.textView.text = self.textView.text + "Exportable key in PEM format:\n\(exportablePEMKey)\n\n" print("Exportable key in PEM format:\n\(exportablePEMKey)\n") } else { @@ -112,7 +111,7 @@ class ExportViewController: UIViewController { DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async { () -> Void in var pubKey, privKey: SecKey? let status = SecKeyGeneratePair(parameters as CFDictionary, &pubKey, &privKey) - if status == errSecSuccess { + if status == errSecSuccess, let privKey = privKey, let pubKey = pubKey { DispatchQueue.main.async(execute: { print("Successfully generated keypair!\nPrivate key: \(privKey)\nPublic key: \(pubKey)") let publicKeyData = self.getPublicKeyData(kExportKeyTag + self.getKeyTypeFromSegmentedControl()) diff --git a/CryptoLoadExternalCertificate/ImportViewController.swift b/CryptoLoadExternalCertificate/ImportViewController.swift index 3fe2ac3..55e17fa 100644 --- a/CryptoLoadExternalCertificate/ImportViewController.swift +++ b/CryptoLoadExternalCertificate/ImportViewController.swift @@ -38,8 +38,7 @@ class ImportViewController: UIViewController { } // if we got the certificate data, let's extract the public key reference. - let importExportManager = CryptoExportImportManager() - if let publicKeyRef = importExportManager.importPublicKeyReferenceFromDERCertificate(certData) { + if let publicKeyRef = CryptoExportImportManager.importPublicKeyReferenceFromDERCertificate(certData) { textView.text = "Successfully extracted public key from certificate:\n\(publicKeyRef)\n" } else { textView.text = "Oups! I was unable to retrieve a public key from the certificate."