├── .gitignore ├── E3Kit iOS Swift Sample.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── cardoso.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── cardoso.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── E3Kit iOS Swift Sample.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── cardoso.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── E3Kit iOS Swift Sample ├── AppDelegate.swift ├── AppError.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Device.swift ├── Info.plist ├── TimeInMs.swift └── ViewController.swift ├── Podfile ├── Podfile.lock └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/macos,swift,xcode,cocoapods,objective-c 3 | 4 | ### macOS ### 5 | *.DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | # Thumbnails 13 | ._* 14 | 15 | # Files that might appear in the root of a volume 16 | .DocumentRevisions-V100 17 | .fseventsd 18 | .Spotlight-V100 19 | .TemporaryItems 20 | .Trashes 21 | .VolumeIcon.icns 22 | .com.apple.timemachine.donotpresent 23 | 24 | # Directories potentially created on remote AFP share 25 | .AppleDB 26 | .AppleDesktop 27 | Network Trash Folder 28 | Temporary Items 29 | .apdisk 30 | 31 | ### Objective-C ### 32 | # Xcode 33 | # 34 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 35 | 36 | ## Build generated 37 | build/ 38 | DerivedData/ 39 | ReduxMovieDB.xcworkspace/xcshareddata/ 40 | 41 | ## Various settings 42 | *.pbxuser 43 | !default.pbxuser 44 | *.mode1v3 45 | !default.mode1v3 46 | *.mode2v3 47 | !default.mode2v3 48 | *.perspectivev3 49 | !default.perspectivev3 50 | xcuserdata/ 51 | 52 | ## Other 53 | *.moved-aside 54 | *.xccheckout 55 | *.xcscmblueprint 56 | 57 | ## Obj-C/Swift specific 58 | *.hmap 59 | *.ipa 60 | *.dSYM.zip 61 | *.dSYM 62 | 63 | # Carthage - Refactored to standalone file 64 | 65 | # fastlane 66 | # 67 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 68 | # screenshots whenever they are needed. 69 | # For more information about the recommended setup visit: 70 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 71 | 72 | fastlane/report.xml 73 | fastlane/Preview.html 74 | fastlane/screenshots 75 | fastlane/test_output 76 | xcov_output 77 | 78 | # Code Injection 79 | # 80 | # After new code Injection tools there's a generated folder /iOSInjectionProject 81 | # https://github.com/johnno1962/injectionforxcode 82 | 83 | iOSInjectionProject/ 84 | 85 | ### Objective-C Patch ### 86 | 87 | ### Swift ### 88 | # Xcode 89 | # 90 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 91 | 92 | ## Build generated 93 | 94 | ## Various settings 95 | 96 | ## Other 97 | 98 | ## Obj-C/Swift specific 99 | 100 | ## Playgrounds 101 | timeline.xctimeline 102 | playground.xcworkspace 103 | 104 | # Swift Package Manager 105 | # 106 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 107 | # Packages/ 108 | # Package.pins 109 | .build/ 110 | 111 | # CocoaPods - Refactored to standalone file 112 | 113 | # Carthage - Refactored to standalone file 114 | Pods/ 115 | 116 | # fastlane 117 | # 118 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 119 | # screenshots whenever they are needed. 120 | # For more information about the recommended setup visit: 121 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 122 | 123 | 124 | ### Xcode ### 125 | # Xcode 126 | # 127 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 128 | 129 | ## Build generated 130 | 131 | ## Various settings 132 | 133 | ## Other 134 | 135 | ### Xcode Patch ### 136 | *.xcodeproj/* 137 | !*.xcodeproj/project.pbxproj 138 | !*.xcodeproj/xcshareddata/ 139 | !*.xcworkspace/contents.xcworkspacedata 140 | /*.gcno 141 | 142 | 143 | # End of https://www.gitignore.io/api/macos,swift,xcode,cocoapods,objective-c 144 | 145 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 80A3DDF022CE227200E73510 /* AppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A3DDEF22CE227200E73510 /* AppError.swift */; }; 11 | 80AAFC3123215D68007A5D51 /* TimeInMs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80AAFC3023215D68007A5D51 /* TimeInMs.swift */; }; 12 | 80AFBA8ADCCDBCC6B4E4C80E /* Pods_E3Kit_iOS_Swift_Sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 512D8943D895699BBF906A4C /* Pods_E3Kit_iOS_Swift_Sample.framework */; }; 13 | 80ED28F42268DD70009AB395 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80ED28F32268DD70009AB395 /* AppDelegate.swift */; }; 14 | 80ED28F62268DD70009AB395 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80ED28F52268DD70009AB395 /* ViewController.swift */; }; 15 | 80ED28F92268DD70009AB395 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 80ED28F72268DD70009AB395 /* Main.storyboard */; }; 16 | 80ED28FB2268DD72009AB395 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 80ED28FA2268DD72009AB395 /* Assets.xcassets */; }; 17 | 80ED28FE2268DD72009AB395 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 80ED28FC2268DD72009AB395 /* LaunchScreen.storyboard */; }; 18 | 80ED29062268DE38009AB395 /* Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80ED29052268DE38009AB395 /* Device.swift */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 512D8943D895699BBF906A4C /* Pods_E3Kit_iOS_Swift_Sample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_E3Kit_iOS_Swift_Sample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 80A3DDEF22CE227200E73510 /* AppError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppError.swift; sourceTree = ""; }; 24 | 80AAFC3023215D68007A5D51 /* TimeInMs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeInMs.swift; sourceTree = ""; }; 25 | 80ED28F02268DD70009AB395 /* E3Kit iOS Swift Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "E3Kit iOS Swift Sample.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | 80ED28F32268DD70009AB395 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 27 | 80ED28F52268DD70009AB395 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 28 | 80ED28F82268DD70009AB395 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29 | 80ED28FA2268DD72009AB395 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 80ED28FD2268DD72009AB395 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 31 | 80ED28FF2268DD72009AB395 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 80ED29052268DE38009AB395 /* Device.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Device.swift; sourceTree = ""; }; 33 | B48D972C20541C53A8DB4D4A /* Pods-E3Kit iOS Swift Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-E3Kit iOS Swift Sample.debug.xcconfig"; path = "Target Support Files/Pods-E3Kit iOS Swift Sample/Pods-E3Kit iOS Swift Sample.debug.xcconfig"; sourceTree = ""; }; 34 | DA5E3EE9AC7EAF6860141565 /* Pods-E3Kit iOS Swift Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-E3Kit iOS Swift Sample.release.xcconfig"; path = "Target Support Files/Pods-E3Kit iOS Swift Sample/Pods-E3Kit iOS Swift Sample.release.xcconfig"; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 80ED28ED2268DD70009AB395 /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | 80AFBA8ADCCDBCC6B4E4C80E /* Pods_E3Kit_iOS_Swift_Sample.framework in Frameworks */, 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXFrameworksBuildPhase section */ 47 | 48 | /* Begin PBXGroup section */ 49 | 20DC513F1785875B936D6A7B /* Pods */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | B48D972C20541C53A8DB4D4A /* Pods-E3Kit iOS Swift Sample.debug.xcconfig */, 53 | DA5E3EE9AC7EAF6860141565 /* Pods-E3Kit iOS Swift Sample.release.xcconfig */, 54 | ); 55 | path = Pods; 56 | sourceTree = ""; 57 | }; 58 | 80ED28E72268DD70009AB395 = { 59 | isa = PBXGroup; 60 | children = ( 61 | 80ED28F22268DD70009AB395 /* E3Kit iOS Swift Sample */, 62 | 80ED28F12268DD70009AB395 /* Products */, 63 | 20DC513F1785875B936D6A7B /* Pods */, 64 | C5AAAD28776E98B591B8D026 /* Frameworks */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | 80ED28F12268DD70009AB395 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 80ED28F02268DD70009AB395 /* E3Kit iOS Swift Sample.app */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | 80ED28F22268DD70009AB395 /* E3Kit iOS Swift Sample */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 80ED28F32268DD70009AB395 /* AppDelegate.swift */, 80 | 80ED28F52268DD70009AB395 /* ViewController.swift */, 81 | 80ED29052268DE38009AB395 /* Device.swift */, 82 | 80AAFC3023215D68007A5D51 /* TimeInMs.swift */, 83 | 80A3DDEF22CE227200E73510 /* AppError.swift */, 84 | 80ED28F72268DD70009AB395 /* Main.storyboard */, 85 | 80ED28FA2268DD72009AB395 /* Assets.xcassets */, 86 | 80ED28FC2268DD72009AB395 /* LaunchScreen.storyboard */, 87 | 80ED28FF2268DD72009AB395 /* Info.plist */, 88 | ); 89 | path = "E3Kit iOS Swift Sample"; 90 | sourceTree = ""; 91 | }; 92 | C5AAAD28776E98B591B8D026 /* Frameworks */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 512D8943D895699BBF906A4C /* Pods_E3Kit_iOS_Swift_Sample.framework */, 96 | ); 97 | name = Frameworks; 98 | sourceTree = ""; 99 | }; 100 | /* End PBXGroup section */ 101 | 102 | /* Begin PBXNativeTarget section */ 103 | 80ED28EF2268DD70009AB395 /* E3Kit iOS Swift Sample */ = { 104 | isa = PBXNativeTarget; 105 | buildConfigurationList = 80ED29022268DD72009AB395 /* Build configuration list for PBXNativeTarget "E3Kit iOS Swift Sample" */; 106 | buildPhases = ( 107 | D04D2EF663A3BC1CBED95D64 /* [CP] Check Pods Manifest.lock */, 108 | 80ED28EC2268DD70009AB395 /* Sources */, 109 | 80ED28ED2268DD70009AB395 /* Frameworks */, 110 | 80ED28EE2268DD70009AB395 /* Resources */, 111 | 3B249DAF1FBD1CBD64162B8B /* [CP] Embed Pods Frameworks */, 112 | ); 113 | buildRules = ( 114 | ); 115 | dependencies = ( 116 | ); 117 | name = "E3Kit iOS Swift Sample"; 118 | productName = "E3Kit iOS Swift Sample"; 119 | productReference = 80ED28F02268DD70009AB395 /* E3Kit iOS Swift Sample.app */; 120 | productType = "com.apple.product-type.application"; 121 | }; 122 | /* End PBXNativeTarget section */ 123 | 124 | /* Begin PBXProject section */ 125 | 80ED28E82268DD70009AB395 /* Project object */ = { 126 | isa = PBXProject; 127 | attributes = { 128 | LastSwiftUpdateCheck = 1010; 129 | LastUpgradeCheck = 1010; 130 | ORGANIZATIONNAME = cardoso; 131 | TargetAttributes = { 132 | 80ED28EF2268DD70009AB395 = { 133 | CreatedOnToolsVersion = 10.1; 134 | LastSwiftMigration = 1020; 135 | }; 136 | }; 137 | }; 138 | buildConfigurationList = 80ED28EB2268DD70009AB395 /* Build configuration list for PBXProject "E3Kit iOS Swift Sample" */; 139 | compatibilityVersion = "Xcode 9.3"; 140 | developmentRegion = en; 141 | hasScannedForEncodings = 0; 142 | knownRegions = ( 143 | en, 144 | Base, 145 | ); 146 | mainGroup = 80ED28E72268DD70009AB395; 147 | productRefGroup = 80ED28F12268DD70009AB395 /* Products */; 148 | projectDirPath = ""; 149 | projectRoot = ""; 150 | targets = ( 151 | 80ED28EF2268DD70009AB395 /* E3Kit iOS Swift Sample */, 152 | ); 153 | }; 154 | /* End PBXProject section */ 155 | 156 | /* Begin PBXResourcesBuildPhase section */ 157 | 80ED28EE2268DD70009AB395 /* Resources */ = { 158 | isa = PBXResourcesBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | 80ED28FE2268DD72009AB395 /* LaunchScreen.storyboard in Resources */, 162 | 80ED28FB2268DD72009AB395 /* Assets.xcassets in Resources */, 163 | 80ED28F92268DD70009AB395 /* Main.storyboard in Resources */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXResourcesBuildPhase section */ 168 | 169 | /* Begin PBXShellScriptBuildPhase section */ 170 | 3B249DAF1FBD1CBD64162B8B /* [CP] Embed Pods Frameworks */ = { 171 | isa = PBXShellScriptBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | ); 175 | inputFileListPaths = ( 176 | "${PODS_ROOT}/Target Support Files/Pods-E3Kit iOS Swift Sample/Pods-E3Kit iOS Swift Sample-frameworks-${CONFIGURATION}-input-files.xcfilelist", 177 | ); 178 | name = "[CP] Embed Pods Frameworks"; 179 | outputFileListPaths = ( 180 | "${PODS_ROOT}/Target Support Files/Pods-E3Kit iOS Swift Sample/Pods-E3Kit iOS Swift Sample-frameworks-${CONFIGURATION}-output-files.xcfilelist", 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-E3Kit iOS Swift Sample/Pods-E3Kit iOS Swift Sample-frameworks.sh\"\n"; 185 | showEnvVarsInLog = 0; 186 | }; 187 | D04D2EF663A3BC1CBED95D64 /* [CP] Check Pods Manifest.lock */ = { 188 | isa = PBXShellScriptBuildPhase; 189 | buildActionMask = 2147483647; 190 | files = ( 191 | ); 192 | inputFileListPaths = ( 193 | ); 194 | inputPaths = ( 195 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 196 | "${PODS_ROOT}/Manifest.lock", 197 | ); 198 | name = "[CP] Check Pods Manifest.lock"; 199 | outputFileListPaths = ( 200 | ); 201 | outputPaths = ( 202 | "$(DERIVED_FILE_DIR)/Pods-E3Kit iOS Swift Sample-checkManifestLockResult.txt", 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | shellPath = /bin/sh; 206 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 207 | showEnvVarsInLog = 0; 208 | }; 209 | /* End PBXShellScriptBuildPhase section */ 210 | 211 | /* Begin PBXSourcesBuildPhase section */ 212 | 80ED28EC2268DD70009AB395 /* Sources */ = { 213 | isa = PBXSourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | 80A3DDF022CE227200E73510 /* AppError.swift in Sources */, 217 | 80ED29062268DE38009AB395 /* Device.swift in Sources */, 218 | 80ED28F62268DD70009AB395 /* ViewController.swift in Sources */, 219 | 80ED28F42268DD70009AB395 /* AppDelegate.swift in Sources */, 220 | 80AAFC3123215D68007A5D51 /* TimeInMs.swift in Sources */, 221 | ); 222 | runOnlyForDeploymentPostprocessing = 0; 223 | }; 224 | /* End PBXSourcesBuildPhase section */ 225 | 226 | /* Begin PBXVariantGroup section */ 227 | 80ED28F72268DD70009AB395 /* Main.storyboard */ = { 228 | isa = PBXVariantGroup; 229 | children = ( 230 | 80ED28F82268DD70009AB395 /* Base */, 231 | ); 232 | name = Main.storyboard; 233 | sourceTree = ""; 234 | }; 235 | 80ED28FC2268DD72009AB395 /* LaunchScreen.storyboard */ = { 236 | isa = PBXVariantGroup; 237 | children = ( 238 | 80ED28FD2268DD72009AB395 /* Base */, 239 | ); 240 | name = LaunchScreen.storyboard; 241 | sourceTree = ""; 242 | }; 243 | /* End PBXVariantGroup section */ 244 | 245 | /* Begin XCBuildConfiguration section */ 246 | 80ED29002268DD72009AB395 /* Debug */ = { 247 | isa = XCBuildConfiguration; 248 | buildSettings = { 249 | ALWAYS_SEARCH_USER_PATHS = NO; 250 | CLANG_ANALYZER_NONNULL = YES; 251 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 252 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 253 | CLANG_CXX_LIBRARY = "libc++"; 254 | CLANG_ENABLE_MODULES = YES; 255 | CLANG_ENABLE_OBJC_ARC = YES; 256 | CLANG_ENABLE_OBJC_WEAK = YES; 257 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 258 | CLANG_WARN_BOOL_CONVERSION = YES; 259 | CLANG_WARN_COMMA = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 262 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 263 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 264 | CLANG_WARN_EMPTY_BODY = YES; 265 | CLANG_WARN_ENUM_CONVERSION = YES; 266 | CLANG_WARN_INFINITE_RECURSION = YES; 267 | CLANG_WARN_INT_CONVERSION = YES; 268 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 269 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 270 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 271 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 272 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 273 | CLANG_WARN_STRICT_PROTOTYPES = YES; 274 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 275 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 276 | CLANG_WARN_UNREACHABLE_CODE = YES; 277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 278 | CODE_SIGN_IDENTITY = "iPhone Developer"; 279 | COPY_PHASE_STRIP = NO; 280 | DEBUG_INFORMATION_FORMAT = dwarf; 281 | ENABLE_STRICT_OBJC_MSGSEND = YES; 282 | ENABLE_TESTABILITY = YES; 283 | GCC_C_LANGUAGE_STANDARD = gnu11; 284 | GCC_DYNAMIC_NO_PIC = NO; 285 | GCC_NO_COMMON_BLOCKS = YES; 286 | GCC_OPTIMIZATION_LEVEL = 0; 287 | GCC_PREPROCESSOR_DEFINITIONS = ( 288 | "DEBUG=1", 289 | "$(inherited)", 290 | ); 291 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 292 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 293 | GCC_WARN_UNDECLARED_SELECTOR = YES; 294 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 295 | GCC_WARN_UNUSED_FUNCTION = YES; 296 | GCC_WARN_UNUSED_VARIABLE = YES; 297 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 298 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 299 | MTL_FAST_MATH = YES; 300 | ONLY_ACTIVE_ARCH = YES; 301 | SDKROOT = iphoneos; 302 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 303 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 304 | }; 305 | name = Debug; 306 | }; 307 | 80ED29012268DD72009AB395 /* Release */ = { 308 | isa = XCBuildConfiguration; 309 | buildSettings = { 310 | ALWAYS_SEARCH_USER_PATHS = NO; 311 | CLANG_ANALYZER_NONNULL = YES; 312 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 313 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 314 | CLANG_CXX_LIBRARY = "libc++"; 315 | CLANG_ENABLE_MODULES = YES; 316 | CLANG_ENABLE_OBJC_ARC = YES; 317 | CLANG_ENABLE_OBJC_WEAK = YES; 318 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 319 | CLANG_WARN_BOOL_CONVERSION = YES; 320 | CLANG_WARN_COMMA = YES; 321 | CLANG_WARN_CONSTANT_CONVERSION = YES; 322 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 323 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 324 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 325 | CLANG_WARN_EMPTY_BODY = YES; 326 | CLANG_WARN_ENUM_CONVERSION = YES; 327 | CLANG_WARN_INFINITE_RECURSION = YES; 328 | CLANG_WARN_INT_CONVERSION = YES; 329 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 330 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 331 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 332 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 333 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 334 | CLANG_WARN_STRICT_PROTOTYPES = YES; 335 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 336 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 337 | CLANG_WARN_UNREACHABLE_CODE = YES; 338 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 339 | CODE_SIGN_IDENTITY = "iPhone Developer"; 340 | COPY_PHASE_STRIP = NO; 341 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 342 | ENABLE_NS_ASSERTIONS = NO; 343 | ENABLE_STRICT_OBJC_MSGSEND = YES; 344 | GCC_C_LANGUAGE_STANDARD = gnu11; 345 | GCC_NO_COMMON_BLOCKS = YES; 346 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 347 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 348 | GCC_WARN_UNDECLARED_SELECTOR = YES; 349 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 350 | GCC_WARN_UNUSED_FUNCTION = YES; 351 | GCC_WARN_UNUSED_VARIABLE = YES; 352 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 353 | MTL_ENABLE_DEBUG_INFO = NO; 354 | MTL_FAST_MATH = YES; 355 | SDKROOT = iphoneos; 356 | SWIFT_COMPILATION_MODE = wholemodule; 357 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 358 | VALIDATE_PRODUCT = YES; 359 | }; 360 | name = Release; 361 | }; 362 | 80ED29032268DD72009AB395 /* Debug */ = { 363 | isa = XCBuildConfiguration; 364 | baseConfigurationReference = B48D972C20541C53A8DB4D4A /* Pods-E3Kit iOS Swift Sample.debug.xcconfig */; 365 | buildSettings = { 366 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 367 | CODE_SIGN_STYLE = Automatic; 368 | DEVELOPMENT_TEAM = FWD9V5VYJ2; 369 | INFOPLIST_FILE = "E3Kit iOS Swift Sample/Info.plist"; 370 | LD_RUNPATH_SEARCH_PATHS = ( 371 | "$(inherited)", 372 | "@executable_path/Frameworks", 373 | ); 374 | PRODUCT_BUNDLE_IDENTIFIER = "cardoso.E3Kit-iOS-Swift-Sample"; 375 | PRODUCT_NAME = "$(TARGET_NAME)"; 376 | SWIFT_VERSION = 5.0; 377 | TARGETED_DEVICE_FAMILY = "1,2"; 378 | }; 379 | name = Debug; 380 | }; 381 | 80ED29042268DD72009AB395 /* Release */ = { 382 | isa = XCBuildConfiguration; 383 | baseConfigurationReference = DA5E3EE9AC7EAF6860141565 /* Pods-E3Kit iOS Swift Sample.release.xcconfig */; 384 | buildSettings = { 385 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 386 | CODE_SIGN_STYLE = Automatic; 387 | DEVELOPMENT_TEAM = FWD9V5VYJ2; 388 | INFOPLIST_FILE = "E3Kit iOS Swift Sample/Info.plist"; 389 | LD_RUNPATH_SEARCH_PATHS = ( 390 | "$(inherited)", 391 | "@executable_path/Frameworks", 392 | ); 393 | PRODUCT_BUNDLE_IDENTIFIER = "cardoso.E3Kit-iOS-Swift-Sample"; 394 | PRODUCT_NAME = "$(TARGET_NAME)"; 395 | SWIFT_VERSION = 5.0; 396 | TARGETED_DEVICE_FAMILY = "1,2"; 397 | }; 398 | name = Release; 399 | }; 400 | /* End XCBuildConfiguration section */ 401 | 402 | /* Begin XCConfigurationList section */ 403 | 80ED28EB2268DD70009AB395 /* Build configuration list for PBXProject "E3Kit iOS Swift Sample" */ = { 404 | isa = XCConfigurationList; 405 | buildConfigurations = ( 406 | 80ED29002268DD72009AB395 /* Debug */, 407 | 80ED29012268DD72009AB395 /* Release */, 408 | ); 409 | defaultConfigurationIsVisible = 0; 410 | defaultConfigurationName = Release; 411 | }; 412 | 80ED29022268DD72009AB395 /* Build configuration list for PBXNativeTarget "E3Kit iOS Swift Sample" */ = { 413 | isa = XCConfigurationList; 414 | buildConfigurations = ( 415 | 80ED29032268DD72009AB395 /* Debug */, 416 | 80ED29042268DD72009AB395 /* Release */, 417 | ); 418 | defaultConfigurationIsVisible = 0; 419 | defaultConfigurationName = Release; 420 | }; 421 | /* End XCConfigurationList section */ 422 | }; 423 | rootObject = 80ED28E82268DD70009AB395 /* Project object */; 424 | } 425 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample.xcodeproj/project.xcworkspace/xcuserdata/cardoso.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/demo-e3kit-ios/c2c59f31f36d3a7d1e7ee4807114478373bf3b32/E3Kit iOS Swift Sample.xcodeproj/project.xcworkspace/xcuserdata/cardoso.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample.xcodeproj/xcuserdata/cardoso.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | E3Kit iOS Swift Sample.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 10 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample.xcworkspace/xcuserdata/cardoso.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/demo-e3kit-ios/c2c59f31f36d3a7d1e7ee4807114478373bf3b32/E3Kit iOS Swift Sample.xcworkspace/xcuserdata/cardoso.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // E3Kit iOS Swift Sample 4 | // 5 | // Created by Matheus Cardoso on 4/18/19. 6 | // Copyright © 2019 cardoso. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/AppError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppError.swift 3 | // E3Kit iOS Swift Sample 4 | // 5 | // Created by Matheus Cardoso on 6/26/19. 6 | // Copyright © 2019 cardoso. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum AppError: Error { 12 | case gettingJwtFailed 13 | case gettingChannelsListFailed 14 | case notAuthenticated 15 | case eThreeNotInitialized 16 | case invalidUrl 17 | case messagingNotInitialized 18 | case invalidResponse 19 | } 20 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/Device.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Device.swift 3 | // E3Kit iOS Swift Sample 4 | // 5 | // Created by Matheus Cardoso on 4/18/19. 6 | // Developer Relations Engineer @ Virgil Security 7 | // 8 | 9 | //# start of snippet: e3kit_imports 10 | import VirgilE3Kit 11 | import VirgilSDK 12 | import VirgilCrypto 13 | //# end of snippet: e3kit_imports 14 | 15 | typealias Completion = () -> Void 16 | typealias FailableCompletion = (Error?) -> Void 17 | typealias ResultCompletion = (Swift.Result) -> Void 18 | 19 | class Device: NSObject { 20 | let identity: String 21 | var eThree: EThree? 22 | var authToken: String? 23 | 24 | // setting this to true can cause a momentary hang in the app 25 | // because encryption and decryption will be ran 100x each. 26 | let benchmarking = false 27 | 28 | init(withIdentity identity: String) { 29 | self.identity = identity 30 | } 31 | 32 | func _log(_ text: Any) { 33 | log("[\(identity)] \(text)") 34 | } 35 | 36 | // First step in e3kit flow is to initialize the SDK (eThree instance) 37 | func initialize(_ completion: FailableCompletion? = nil) { 38 | let identity = self.identity 39 | 40 | //# start of snippet: e3kit_authenticate 41 | let authCallback = { () -> String? in 42 | let connection = HttpConnection() 43 | 44 | guard let url = URL(string: "http://localhost:3000/authenticate") else { 45 | return nil 46 | } 47 | 48 | let headers = ["Content-Type": "application/json"] 49 | let params = ["identity": identity] 50 | 51 | guard let requestBody = try? JSONSerialization.data(withJSONObject: params, options: []) else { 52 | return nil 53 | } 54 | 55 | let request = Request(url: url, method: .post, headers: headers, body: requestBody) 56 | 57 | guard 58 | let response = try? connection.send(request).startSync().get(), 59 | let body = response.body 60 | else { 61 | return nil 62 | } 63 | 64 | guard let json = try? JSONSerialization.jsonObject(with: body, options: []) as? [String: Any] else { 65 | return nil 66 | } 67 | 68 | return json["authToken"] as? String 69 | } 70 | 71 | authToken = authCallback() 72 | //# end of snippet: e3kit_authenticate 73 | 74 | //# start of snippet: e3kit_jwt_callback 75 | let tokenCallback: EThree.RenewJwtCallback = { completion in 76 | guard let url = URL(string: "http://localhost:3000/virgil-jwt") else { 77 | return completion(nil, AppError.invalidUrl) 78 | } 79 | 80 | guard let authToken = self.authToken else { 81 | return completion(nil, AppError.notAuthenticated) 82 | } 83 | 84 | let headers = [ 85 | "Content-Type": "application/json", 86 | "Authorization": "Bearer " + authToken 87 | ] 88 | 89 | let request = Request(url: url, method: .get, headers: headers) 90 | 91 | let connection = HttpConnection() 92 | 93 | guard 94 | let response = try? connection.send(request).startSync().get(), 95 | let body = response.body, 96 | let json = try? JSONSerialization.jsonObject(with: body, options: []) as? [String: Any], 97 | let jwtString = json["virgilToken"] as? String 98 | else { 99 | return completion(nil, AppError.gettingJwtFailed) 100 | } 101 | 102 | completion(jwtString, nil) 103 | } 104 | //# end of snippet: e3kit_jwt_callback 105 | 106 | //# start of snippet: e3kit_initialize 107 | do { 108 | eThree = try EThree(identity: identity, tokenCallback: tokenCallback) 109 | self._log("Initialized") 110 | completion?(nil) 111 | } catch let error { 112 | self._log("Failed initializing: \(error.localizedDescription)") 113 | completion?(error) 114 | } 115 | //# end of snippet: e3kit_initialize 116 | } 117 | 118 | func register(_ completion: FailableCompletion? = nil) { 119 | guard let eThree = eThree else { 120 | completion?(AppError.eThreeNotInitialized) 121 | return 122 | } 123 | 124 | //# start of snippet: e3kit_has_local_private_key 125 | if (try? eThree.hasLocalPrivateKey()) == true { 126 | try? eThree.cleanUp() 127 | } 128 | //# end of snippet: e3kit_has_local_private_key 129 | 130 | //# start of snippet: e3kit_register 131 | eThree.register { error in 132 | if let error = error { 133 | self._log("Failed registering: \(error.localizedDescription)") 134 | } 135 | 136 | if error as? EThreeError == .userIsAlreadyRegistered { 137 | eThree.rotatePrivateKey { error in 138 | self._log("Rotated private key instead") 139 | completion?(error) 140 | } 141 | 142 | return 143 | } 144 | 145 | self._log("Registered") 146 | 147 | completion?(error) 148 | } 149 | //# end of snippet: e3kit_register 150 | } 151 | 152 | func findUsers(with identities: [String], completion: ResultCompletion?) { 153 | guard let eThree = eThree else { 154 | completion?(.failure(AppError.eThreeNotInitialized)) 155 | return 156 | } 157 | 158 | //# start of snippet: e3kit_lookup_public_keys 159 | eThree.findUsers(with: identities) { result, error in 160 | if let result = result { 161 | self._log("Looked up \(identities)'s public key") 162 | completion?(.success(result)) 163 | } else if let error = error { 164 | self._log("Failed looking up \(identities)'s public key: \(error.localizedDescription)") 165 | completion?(.failure(error)) 166 | } 167 | } 168 | //# end of snippet: e3kit_lookup_public_keys 169 | } 170 | 171 | func encrypt(text: String, for findUsersResult: FindUsersResult? = nil) throws -> String { 172 | guard let eThree = eThree else { 173 | throw AppError.eThreeNotInitialized 174 | } 175 | 176 | let then = timeInMs() 177 | 178 | do { 179 | let repetitions = benchmarking ? 100 : 1 180 | var encryptedText: String = "" 181 | for _ in (1...repetitions) { 182 | //# start of snippet: e3kit_auth_encrypt 183 | encryptedText = try eThree.authEncrypt(text: text, for: findUsersResult!) 184 | //# end of snippet: e3kit_auth_encrypt 185 | } 186 | let time = (timeInMs() - then)/Double(repetitions) 187 | self._log("Encrypted and signed: '\(encryptedText)'. Took: \(time)ms") 188 | return encryptedText 189 | } catch(let error) { 190 | self._log("Failed encrypting and signing: \(error.localizedDescription)") 191 | throw error 192 | } 193 | } 194 | 195 | func decrypt(text: String, from user: Card? = nil) throws -> String { 196 | guard let eThree = eThree else { 197 | throw AppError.eThreeNotInitialized 198 | } 199 | 200 | let then = timeInMs() 201 | 202 | do { 203 | let repetitions = benchmarking ? 100 : 1 204 | var decryptedText: String = "" 205 | for _ in (1...repetitions) { 206 | //# start of snippet: e3kit_auth_decrypt 207 | decryptedText = try eThree.authDecrypt(text: text, from: user) 208 | //# end of snippet: e3kit_auth_decrypt 209 | } 210 | let time = (timeInMs() - then)/Double(repetitions) 211 | self._log("Decrypted and verified: '\(decryptedText)'. Took: \(time)ms") 212 | return decryptedText 213 | } catch(let error) { 214 | self._log("Failed decrypting and verifying: \(error.localizedDescription)") 215 | throw error 216 | } 217 | } 218 | 219 | func hasLocalPrivateKey() throws -> Bool { 220 | guard let eThree = eThree else { 221 | throw AppError.eThreeNotInitialized 222 | } 223 | 224 | //# start of snippet: e3kit_has_local_private_key 225 | let hasLocalPrivateKey = try eThree.hasLocalPrivateKey() 226 | //# end of snippet: e3kit_has_local_private_key 227 | 228 | return hasLocalPrivateKey 229 | } 230 | 231 | func backupPrivateKey(password: String, completion: FailableCompletion? = nil) { 232 | guard let eThree = eThree else { 233 | completion?(AppError.eThreeNotInitialized) 234 | return 235 | } 236 | 237 | //# start of snippet: e3kit_backup_private_key 238 | eThree.backupPrivateKey(password: password) { error in 239 | completion?(error) 240 | } 241 | //# end of snippet: e3kit_backup_private_key 242 | } 243 | 244 | func restorePrivateKey(password: String, completion: FailableCompletion? = nil) { 245 | guard let eThree = eThree else { 246 | completion?(AppError.eThreeNotInitialized) 247 | return 248 | } 249 | 250 | //# start of snippet: e3kit_restore_private_key 251 | eThree.restorePrivateKey(password: password) { error in 252 | completion?(error) 253 | } 254 | //# end of snippet: e3kit_restore_private_key 255 | } 256 | 257 | func rotatePrivateKey(completion: FailableCompletion? = nil) { 258 | guard let eThree = eThree else { 259 | completion?(AppError.eThreeNotInitialized) 260 | return 261 | } 262 | 263 | //# start of snippet: e3kit_rotate_private_key 264 | eThree.rotatePrivateKey { error in 265 | completion?(error) 266 | } 267 | //# end of snippet: e3kit_rotate_private_key 268 | } 269 | 270 | func unregister(completion: FailableCompletion? = nil) { 271 | guard let eThree = eThree else { 272 | completion?(AppError.eThreeNotInitialized) 273 | return 274 | } 275 | 276 | //# start of snippet: e3kit_unregister 277 | eThree.unregister { error in 278 | completion?(error) 279 | } 280 | //# end of snippet: e3kit_unregister 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | NSExceptionDomains 10 | 11 | localhost 12 | 13 | NSIncludesSubdomains 14 | 15 | NSExceptionAllowsInsecureHTTPLoads 16 | 17 | 18 | 19 | 20 | CFBundleDevelopmentRegion 21 | $(DEVELOPMENT_LANGUAGE) 22 | CFBundleExecutable 23 | $(EXECUTABLE_NAME) 24 | CFBundleIdentifier 25 | $(PRODUCT_BUNDLE_IDENTIFIER) 26 | CFBundleInfoDictionaryVersion 27 | 6.0 28 | CFBundleName 29 | $(PRODUCT_NAME) 30 | CFBundlePackageType 31 | APPL 32 | CFBundleShortVersionString 33 | 1.0 34 | CFBundleVersion 35 | 1 36 | LSRequiresIPhoneOS 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIMainStoryboardFile 41 | Main 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/TimeInMs.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimeInMs.swift 3 | // E3Kit iOS Swift Sample 4 | // 5 | // Created by Matheus Cardoso on 9/5/19. 6 | // Copyright © 2019 cardoso. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | func timeInMs() -> Double { 12 | return Double(DispatchTime.now().rawValue)/1000000 13 | } 14 | -------------------------------------------------------------------------------- /E3Kit iOS Swift Sample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // E3Kit iOS Swift Sample 4 | // 5 | // Created by Matheus Cardoso on 4/18/19. 6 | // Copyright © 2019 cardoso. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import VirgilE3Kit 11 | import VirgilCrypto 12 | 13 | var log: (_ text: Any) -> Void = { print($0) } 14 | 15 | class ViewController: UIViewController { 16 | @IBOutlet weak var logsTextView: UITextView! 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | // Do any additional setup after loading the view, typically from a nib. 21 | log = { [weak self] text in 22 | DispatchQueue.main.async { 23 | print(text) 24 | self?.logsTextView.text += "\(text)\n" 25 | } 26 | } 27 | 28 | log("* Testing main methods:"); 29 | log("\n----- EThree.initialize -----"); 30 | initializeUsers { 31 | log("\n----- EThree.register -----"); 32 | self.registerUsers { 33 | log("\n----- EThree.lookupPublicKeys -----"); 34 | self.lookupPublicKeys { 35 | do { 36 | log("\n----- EThree.encrypt & EThree.decrypt -----"); 37 | try self.encryptAndDecrypt() 38 | } catch(let e) { 39 | log(e) 40 | } 41 | } 42 | } 43 | } 44 | } 45 | 46 | let alice = Device(withIdentity: "Alice") 47 | let bob = Device(withIdentity: "Bob") 48 | 49 | var bobLookup: FindUsersResult? 50 | var aliceLookup: FindUsersResult? 51 | 52 | func initializeUsers(_ completion: @escaping Completion) { 53 | alice.initialize { _ in 54 | self.bob.initialize { _ in 55 | completion() 56 | } 57 | } 58 | } 59 | 60 | func registerUsers(_ completion: @escaping Completion) { 61 | alice.register { _ in 62 | self.bob.register { _ in 63 | completion() 64 | } 65 | } 66 | } 67 | 68 | func lookupPublicKeys(_ completion: @escaping Completion) { 69 | alice.findUsers(with: [bob.identity]) { 70 | switch $0 { 71 | case .failure: 72 | break 73 | case .success(let lookup): 74 | self.bobLookup = lookup 75 | } 76 | 77 | self.bob.findUsers(with: [self.alice.identity]) { 78 | switch $0 { 79 | case .failure: 80 | break 81 | case .success(let lookup): 82 | self.aliceLookup = lookup 83 | completion() 84 | } 85 | } 86 | } 87 | } 88 | 89 | func encryptAndDecrypt() throws { 90 | let aliceEncryptedText = try alice.encrypt(text: "Hello \(bob.identity)! How are you?", for: bobLookup) 91 | _ = try bob.decrypt(text: aliceEncryptedText, from: aliceLookup?[alice.identity]) 92 | let bobEncryptedText = try bob.encrypt(text: "Hello \(alice.identity)! How are you?", for: aliceLookup) 93 | _ = try alice.decrypt(text: bobEncryptedText, from: bobLookup?[bob.identity]) 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'E3Kit iOS Swift Sample' do 5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for E3Kit iOS Swift Sample 9 | pod 'VirgilE3Kit', '~> 0.8.0' 10 | end 11 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - VirgilCrypto (5.3.0): 3 | - VirgilCryptoFoundation (~> 0.12.0) 4 | - VirgilCryptoFoundation (0.12.0): 5 | - VSCCrypto/Common (= 0.12.0) 6 | - VSCCrypto/Foundation (= 0.12.0) 7 | - VirgilCryptoPythia (0.12.0): 8 | - VirgilCryptoFoundation (= 0.12.0) 9 | - VSCCrypto/Common (= 0.12.0) 10 | - VSCCrypto/Foundation (= 0.12.0) 11 | - VSCCrypto/Pythia (= 0.12.0) 12 | - VirgilCryptoRatchet (0.12.0): 13 | - VirgilCryptoFoundation (= 0.12.0) 14 | - VSCCrypto/Common (= 0.12.0) 15 | - VSCCrypto/Foundation (= 0.12.0) 16 | - VSCCrypto/Ratchet (= 0.12.0) 17 | - VirgilE3Kit (0.8.0): 18 | - VirgilSDKPythia (~> 0.8.0) 19 | - VirgilSDKRatchet (~> 0.5.0) 20 | - VirgilSDK (7.1.0): 21 | - VirgilCrypto (~> 5.3) 22 | - VirgilSDKPythia (0.8.0): 23 | - VirgilCryptoPythia (~> 0.12.0) 24 | - VirgilSDK (~> 7.1) 25 | - VirgilSDKRatchet (0.5.0): 26 | - VirgilCryptoRatchet (~> 0.12.0) 27 | - VirgilSDK (~> 7.1) 28 | - VSCCrypto/Common (0.12.0) 29 | - VSCCrypto/Foundation (0.12.0) 30 | - VSCCrypto/Pythia (0.12.0) 31 | - VSCCrypto/Ratchet (0.12.0) 32 | 33 | DEPENDENCIES: 34 | - VirgilE3Kit (~> 0.8.0) 35 | 36 | SPEC REPOS: 37 | trunk: 38 | - VirgilCrypto 39 | - VirgilCryptoFoundation 40 | - VirgilCryptoPythia 41 | - VirgilCryptoRatchet 42 | - VirgilE3Kit 43 | - VirgilSDK 44 | - VirgilSDKPythia 45 | - VirgilSDKRatchet 46 | - VSCCrypto 47 | 48 | SPEC CHECKSUMS: 49 | VirgilCrypto: c2831582c5230eeb2adba2365336c768cd6d8c59 50 | VirgilCryptoFoundation: 79f23a7ab6db642268d31bc63b0cf54db416f089 51 | VirgilCryptoPythia: 4234b6f84de6fd2448faf6628ecdce84f43650a4 52 | VirgilCryptoRatchet: 5aa50ee540cdf1ff7d760fbe410e4f023f52dc18 53 | VirgilE3Kit: d220265910317fb02ea17d24cb90c7d55cb46a8d 54 | VirgilSDK: 3a94e66f00cd8f89011eee4e445a5e00e9d898f1 55 | VirgilSDKPythia: 778eb39b2c73a9d1832b9cad7eaa2cbf1be264cf 56 | VirgilSDKRatchet: 9a365d3a434cda39af4e6326eaf25baeed75be68 57 | VSCCrypto: e2c8df89e0dc348c2713554f6a2c8864e1cf412d 58 | 59 | PODFILE CHECKSUM: e231bccc70d9a7b8a7762ac79a94e967d883fc89 60 | 61 | COCOAPODS: 1.8.4 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Virgil e3kit iOS Demo 2 | 3 | ## Introduction 4 | 5 | This is a sample iOS project for [Virgil Security](https://virgilsecurity.com)'s [e3kit SDK](https://github.com/VirgilSecurity/virgil-e3kit-x) which simplifies work with Virgil services and presents an easy-to-use API for adding a security layer to any application. E3kit interacts with Virgil Cards Service, Keyknox Service and Pythia Service. 6 | Virgil e3kit allows you to setup user encryption with multidevice support in just a few simple steps. 7 | 8 | ## Requirements 9 | 10 | In order to run this demo, you have: 11 | - Installed Xcode 10.2.1 or greater 12 | - Installed [CocoaPods](https://cocoapods.org/) 1.6.1 or greated 13 | - Created a Virgil E2EE v5 Application in your dashboard 14 | - Set up a local backend to generate Virgil JWT (you can find our Node.js sample [here](https://github.com/VirgilSecurity/sample-backend-nodejs)) 15 | 16 | ## Install dependencies 17 | 18 | Before running this demo, you must install e3kit using CocoaPods: 19 | 20 | ``` 21 | $ pod install 22 | ``` 23 | 24 | ## License 25 | 26 | This library is released under the [3-clause BSD License](LICENSE.md). 27 | 28 | ## Support 29 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com/). 30 | 31 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 32 | 33 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 34 | --------------------------------------------------------------------------------