diff --git a/keychain-kit.xcodeproj/project.pbxproj b/keychain-kit.xcodeproj/project.pbxproj new file mode 100644 index 0000000..f862347 --- /dev/null +++ b/keychain-kit.xcodeproj/project.pbxproj @@ -0,0 +1,362 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 4B08E1FC23E73380003504E1 /* keychain_kit.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B08E1FA23E73380003504E1 /* keychain_kit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B08E20823E73CAF003504E1 /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B08E20723E73CAF003504E1 /* Keychain.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 4B08E1F723E73380003504E1 /* KeychainKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KeychainKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B08E1FA23E73380003504E1 /* keychain_kit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keychain_kit.h; sourceTree = ""; }; + 4B08E1FB23E73380003504E1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 4B08E20323E733CD003504E1 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = ""; }; + 4B08E20423E733F3003504E1 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + 4B08E20523E733F9003504E1 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 4B08E20723E73CAF003504E1 /* Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keychain.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4B08E1F423E73380003504E1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4B08E1ED23E7337F003504E1 = { + isa = PBXGroup; + children = ( + 4B08E1F923E73380003504E1 /* keychain-kit */, + 4B08E1F823E73380003504E1 /* Products */, + ); + sourceTree = ""; + }; + 4B08E1F823E73380003504E1 /* Products */ = { + isa = PBXGroup; + children = ( + 4B08E1F723E73380003504E1 /* KeychainKit.framework */, + ); + name = Products; + sourceTree = ""; + }; + 4B08E1F923E73380003504E1 /* keychain-kit */ = { + isa = PBXGroup; + children = ( + 4B08E20623E73C92003504E1 /* Sources */, + 4B08E20223E733BF003504E1 /* Support Files */, + ); + path = "keychain-kit"; + sourceTree = ""; + }; + 4B08E20223E733BF003504E1 /* Support Files */ = { + isa = PBXGroup; + children = ( + 4B08E1FA23E73380003504E1 /* keychain_kit.h */, + 4B08E1FB23E73380003504E1 /* Info.plist */, + 4B08E20323E733CD003504E1 /* Config.xcconfig */, + 4B08E20423E733F3003504E1 /* Debug.xcconfig */, + 4B08E20523E733F9003504E1 /* Release.xcconfig */, + ); + path = "Support Files"; + sourceTree = ""; + }; + 4B08E20623E73C92003504E1 /* Sources */ = { + isa = PBXGroup; + children = ( + 4B08E20723E73CAF003504E1 /* Keychain.swift */, + ); + path = Sources; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4B08E1F223E73380003504E1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B08E1FC23E73380003504E1 /* keychain_kit.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4B08E1F623E73380003504E1 /* keychain-kit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B08E1FF23E73380003504E1 /* Build configuration list for PBXNativeTarget "keychain-kit" */; + buildPhases = ( + 4B08E1F223E73380003504E1 /* Headers */, + 4B08E1F323E73380003504E1 /* Sources */, + 4B08E1F423E73380003504E1 /* Frameworks */, + 4B08E1F523E73380003504E1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "keychain-kit"; + productName = "keychain-kit"; + productReference = 4B08E1F723E73380003504E1 /* KeychainKit.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4B08E1EE23E73380003504E1 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = mr.noone; + TargetAttributes = { + 4B08E1F623E73380003504E1 = { + CreatedOnToolsVersion = 11.3.1; + LastSwiftMigration = 1130; + }; + }; + }; + buildConfigurationList = 4B08E1F123E73380003504E1 /* Build configuration list for PBXProject "keychain-kit" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 4B08E1ED23E7337F003504E1; + productRefGroup = 4B08E1F823E73380003504E1 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4B08E1F623E73380003504E1 /* keychain-kit */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4B08E1F523E73380003504E1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4B08E1F323E73380003504E1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B08E20823E73CAF003504E1 /* Keychain.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4B08E1FD23E73380003504E1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4B08E20423E733F3003504E1 /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = 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_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; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 4B08E1FE23E73380003504E1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4B08E20523E733F9003504E1 /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = 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_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; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 4B08E20023E73380003504E1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 84Z2AMFMF3; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.mr-noone.keychain-kit"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 4B08E20123E73380003504E1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 84Z2AMFMF3; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.mr-noone.keychain-kit"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4B08E1F123E73380003504E1 /* Build configuration list for PBXProject "keychain-kit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B08E1FD23E73380003504E1 /* Debug */, + 4B08E1FE23E73380003504E1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4B08E1FF23E73380003504E1 /* Build configuration list for PBXNativeTarget "keychain-kit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B08E20023E73380003504E1 /* Debug */, + 4B08E20123E73380003504E1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4B08E1EE23E73380003504E1 /* Project object */; +} diff --git a/keychain-kit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/keychain-kit.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..2cbedfd --- /dev/null +++ b/keychain-kit.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/keychain-kit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/keychain-kit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/keychain-kit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/keychain-kit/Sources/Keychain.swift b/keychain-kit/Sources/Keychain.swift new file mode 100644 index 0000000..4e50e64 --- /dev/null +++ b/keychain-kit/Sources/Keychain.swift @@ -0,0 +1,88 @@ +// +// Keychain.swift +// keychain-kit +// +// Created by Aleksey Zgurskiy on 02.02.2020. +// Copyright © 2020 mr.noone. All rights reserved. +// + +import Foundation + +public struct Keychain { + public enum Error: Swift.Error { + case noData + case unexpectedData + case unexpected(code: OSStatus) + } + + // MARK: - Inits + + public init() {} + + // MARK: - Public methods + + public func get(_ key: String) throws -> Data { + let query: [CFString : AnyObject] = [ + kSecClass : kSecClassGenericPassword, + kSecAttrAccount : key as AnyObject, + kSecMatchLimit : kSecMatchLimitOne, + kSecReturnData : kCFBooleanTrue + ] + + var queryResult: AnyObject? + let status = withUnsafeMutablePointer(to: &queryResult) { + SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) + } + + guard status != errSecItemNotFound else { throw Error.noData } + guard status == noErr else { throw Error.unexpected(code: status) } + + guard + let item = queryResult as? [CFString : AnyObject], + let data = item[kSecValueData] as? Data + else { throw Error.noData } + + return data + } + + public func get(_ key: String) throws -> String { + return String(data: try get(key), encoding: .utf8)! + } + + public func get(_ key: String, decoder: JSONDecoder = JSONDecoder()) throws -> T where T: Decodable { + return try decoder.decode(T.self, from: get(key)) + } + + public func set(_ data: Data, for key: String) throws { + try delete(key) + + let query: [CFString : AnyObject] = [ + kSecClass : kSecClassGenericPassword, + kSecAttrAccount : key as AnyObject, + kSecValueData : data as AnyObject + ] + + let status = SecItemAdd(query as CFDictionary, nil) + guard status == noErr else { throw Error.unexpected(code: status) } + } + + public func set(_ value: String, for key: String) throws { + try set(value.data(using: .utf8)!, for: key) + } + + public func set(_ value: T, for key: String, encoder: JSONEncoder = JSONEncoder()) throws where T: Encodable { + try set(encoder.encode(value), for: key) + } + + public func delete(_ key: String) throws { + let query: [CFString : AnyObject] = [ + kSecClass : kSecClassGenericPassword, + kSecAttrAccount : key as AnyObject + ] + + let status = SecItemDelete(query as CFDictionary) + guard status == noErr || status == errSecItemNotFound else { + throw Error.unexpected(code: status) + } + } +} diff --git a/keychain-kit/Support Files/Config.xcconfig b/keychain-kit/Support Files/Config.xcconfig new file mode 100644 index 0000000..ae8eefd --- /dev/null +++ b/keychain-kit/Support Files/Config.xcconfig @@ -0,0 +1,13 @@ +// +// Config.xcconfig +// keychain-kit +// +// Created by Aleksey Zgurskiy on 02.02.2020. +// Copyright © 2020 mr.noone. All rights reserved. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +INFOPLIST_FILE = keychain-kit/Support Files/Info.plist +PRODUCT_NAME = KeychainKit // $(TARGET_NAME:c99extidentifier) diff --git a/keychain-kit/Support Files/Debug.xcconfig b/keychain-kit/Support Files/Debug.xcconfig new file mode 100644 index 0000000..a30dcfa --- /dev/null +++ b/keychain-kit/Support Files/Debug.xcconfig @@ -0,0 +1,12 @@ +// +// Debug.xcconfig +// keychain-kit +// +// Created by Aleksey Zgurskiy on 02.02.2020. +// Copyright © 2020 mr.noone. All rights reserved. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +#include "Config.xcconfig" diff --git a/keychain-kit/Support Files/Info.plist b/keychain-kit/Support Files/Info.plist new file mode 100644 index 0000000..c0701c6 --- /dev/null +++ b/keychain-kit/Support Files/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/keychain-kit/Support Files/Release.xcconfig b/keychain-kit/Support Files/Release.xcconfig new file mode 100644 index 0000000..f8da04d --- /dev/null +++ b/keychain-kit/Support Files/Release.xcconfig @@ -0,0 +1,12 @@ +// +// Release.xcconfig +// keychain-kit +// +// Created by Aleksey Zgurskiy on 02.02.2020. +// Copyright © 2020 mr.noone. All rights reserved. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +#include "Config.xcconfig" diff --git a/keychain-kit/Support Files/keychain_kit.h b/keychain-kit/Support Files/keychain_kit.h new file mode 100644 index 0000000..bae651a --- /dev/null +++ b/keychain-kit/Support Files/keychain_kit.h @@ -0,0 +1,19 @@ +// +// keychain_kit.h +// keychain-kit +// +// Created by Aleksey Zgurskiy on 02.02.2020. +// Copyright © 2020 mr.noone. All rights reserved. +// + +#import + +//! Project version number for keychain_kit. +FOUNDATION_EXPORT double keychain_kitVersionNumber; + +//! Project version string for keychain_kit. +FOUNDATION_EXPORT const unsigned char keychain_kitVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + +