├── .gitignore ├── .travis.yml ├── Assets ├── icon │ ├── Action-Icon-29.png │ ├── Action-Icon-29@2x.png │ ├── Action-Icon-29@3x.png │ ├── Action-Icon-40.png │ ├── Action-Icon-40@2x.png │ ├── Action-Icon-40@3x.png │ ├── Action-Icon-60@2x.png │ ├── Action-Icon-60@3x.png │ ├── Action-Icon-76.png │ ├── Action-Icon-76@2x.png │ ├── Action-iTunesArtwork@2x.png │ ├── Icon-29.png │ ├── Icon-29@2x.png │ ├── Icon-29@3x.png │ ├── Icon-40.png │ ├── Icon-40@2x.png │ ├── Icon-40@3x.png │ ├── Icon-60@2x.png │ ├── Icon-60@3x.png │ ├── Icon-76.png │ ├── Icon-76@2x.png │ ├── iTunesArtwork@2x-header@2x.png │ ├── iTunesArtwork@2x-header@3x.png │ └── iTunesArtwork@2x.png ├── screenshots │ ├── 1.0.1 │ │ ├── 3.5-inch (iPhone 4) - Screenshot 1.jpg │ │ ├── 3.5-inch (iPhone 4) - Screenshot 2.jpg │ │ ├── 3.5-inch (iPhone 4) - Screenshot 3.jpg │ │ ├── 3.5-inch (iPhone 4) - Screenshot 4.jpg │ │ ├── 3.5-inch (iPhone 4) - Screenshot 5.jpg │ │ ├── 4-inch (iPhone 5) - Screenshot 1.jpg │ │ ├── 4-inch (iPhone 5) - Screenshot 2.jpg │ │ ├── 4-inch (iPhone 5) - Screenshot 3.jpg │ │ ├── 4-inch (iPhone 5) - Screenshot 4.jpg │ │ ├── 4-inch (iPhone 5) - Screenshot 5.jpg │ │ ├── 4.7-inch (iPhone 6) - Screenshot 1.jpg │ │ ├── 4.7-inch (iPhone 6) - Screenshot 2.jpg │ │ ├── 4.7-inch (iPhone 6) - Screenshot 3.jpg │ │ ├── 4.7-inch (iPhone 6) - Screenshot 4.jpg │ │ ├── 4.7-inch (iPhone 6) - Screenshot 5.jpg │ │ ├── 5.5-inch (iPhone 6+) - Screenshot 1.jpg │ │ ├── 5.5-inch (iPhone 6+) - Screenshot 2.jpg │ │ ├── 5.5-inch (iPhone 6+) - Screenshot 3.jpg │ │ ├── 5.5-inch (iPhone 6+) - Screenshot 4.jpg │ │ ├── 5.5-inch (iPhone 6+) - Screenshot 5.jpg │ │ ├── iPad 1.png │ │ ├── iPad 2.png │ │ ├── iPad 3.png │ │ ├── iPad 4.png │ │ ├── status bar 1.png │ │ ├── status bar 2.png │ │ ├── status bar 3.png │ │ ├── status bar 4.png │ │ └── status bar 5.png │ └── 1.0 │ │ ├── 3.5-inch (iPhone 4) - Screenshot 1.jpg │ │ ├── 3.5-inch (iPhone 4) - Screenshot 3.jpg │ │ ├── 3.5-inch (iPhone 4) - Screenshot 4.jpg │ │ ├── 4-inch (iPhone 5) - Screenshot 1.jpg │ │ ├── 4-inch (iPhone 5) - Screenshot 2.jpg │ │ ├── 4-inch (iPhone 5) - Screenshot 3.jpg │ │ ├── 4-inch (iPhone 5) - Screenshot 4.jpg │ │ ├── 4.7-inch (iPhone 6) - Screenshot 1.jpg │ │ ├── 4.7-inch (iPhone 6) - Screenshot 2.jpg │ │ ├── 4.7-inch (iPhone 6) - Screenshot 3.jpg │ │ ├── 4.7-inch (iPhone 6) - Screenshot 4.jpg │ │ ├── 5.5-inch (iPhone 6+) - Screenshot 1.jpg │ │ ├── 5.5-inch (iPhone 6+) - Screenshot 2.jpg │ │ ├── 5.5-inch (iPhone 6+) - Screenshot 3.jpg │ │ └── 5.5-inch (iPhone 6+) - Screenshot 4.jpg ├── tutorial │ ├── Tutorial0@2x.png │ ├── Tutorial0@3x.png │ ├── Tutorial1@2x.png │ ├── Tutorial1@3x.png │ ├── Tutorial2@2x.png │ ├── Tutorial2@3x.png │ ├── Tutorial3@2x.png │ └── Tutorial3@3x.png ├── zero-store-icon.pcvd └── zerostore.sketch ├── EnterPassword ├── ActionVC.swift ├── Base.lproj │ └── MainInterface.storyboard ├── EnterPassword.entitlements └── Info.plist ├── LICENSE ├── Podfile ├── README.md ├── ZeroStore.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── EnterPassword.xcscheme │ ├── ZeroStore.xcscheme │ └── ZeroStoreTestsTravis.xcscheme ├── ZeroStore.xcworkspace └── contents.xcworkspacedata ├── ZeroStore ├── About.storyboard ├── AboutVC.swift ├── AppDelegate.swift ├── Base.lproj │ └── Main.storyboard ├── ChangePasswordVC.swift ├── Constants.swift ├── CryptoAlgorithm.swift ├── Images.xcassets │ ├── ActionIcon.appiconset │ │ ├── Action-Icon-29.png │ │ ├── Action-Icon-29@2x-1.png │ │ ├── Action-Icon-29@2x.png │ │ ├── Action-Icon-29@3x.png │ │ ├── Action-Icon-40.png │ │ ├── Action-Icon-40@2x-1.png │ │ ├── Action-Icon-40@2x.png │ │ ├── Action-Icon-40@3x.png │ │ ├── Action-Icon-60@2x.png │ │ ├── Action-Icon-60@3x.png │ │ ├── Action-Icon-76.png │ │ ├── Action-Icon-76@2x.png │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-29.png │ │ ├── Icon-29@2x-1.png │ │ ├── Icon-29@2x.png │ │ ├── Icon-29@3x.png │ │ ├── Icon-40.png │ │ ├── Icon-40@2x-1.png │ │ ├── Icon-40@2x.png │ │ ├── Icon-40@3x.png │ │ ├── Icon-60@2x.png │ │ ├── Icon-60@3x.png │ │ ├── Icon-76.png │ │ └── Icon-76@2x.png │ ├── Contents.json │ ├── LargeIcon.imageset │ │ ├── Contents.json │ │ ├── iTunesArtwork@2x-header@2x-1.png │ │ ├── iTunesArtwork@2x-header@2x.png │ │ └── iTunesArtwork@2x-header@3x.png │ ├── Tutorial0.imageset │ │ ├── Contents.json │ │ ├── Tutorial0@2x-1.png │ │ ├── Tutorial0@2x.png │ │ └── Tutorial0@3x.png │ ├── Tutorial1.imageset │ │ ├── Contents.json │ │ ├── Tutorial1@2x-1.png │ │ ├── Tutorial1@2x.png │ │ └── Tutorial1@3x.png │ ├── Tutorial2.imageset │ │ ├── Contents.json │ │ ├── Tutorial2@2x-1.png │ │ ├── Tutorial2@2x.png │ │ └── Tutorial2@3x.png │ └── Tutorial3.imageset │ │ ├── Contents.json │ │ ├── Tutorial3@2x-1.png │ │ ├── Tutorial3@2x.png │ │ └── Tutorial3@3x.png ├── Info.plist ├── LaunchScreen.storyboard ├── NoPasteTextField.swift ├── PasswordManager.swift ├── SettingsVC.swift ├── String+Extensions.swift ├── Tutorial.storyboard ├── TutorialContainerVC.swift ├── TutorialPageVC.swift ├── TutorialVC.swift ├── UIViewController+Extensions.swift ├── ZeroStore-Bridging-Header.h └── ZeroStore.entitlements ├── ZeroStoreTests ├── Info.plist ├── TestConstants.swift └── TestPasswordGeneration.swift ├── ZeroStoreUITests ├── Info.plist └── ZeroStoreUITests.swift └── increment_build.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Pods directory (it's autogenerated from CocoaPods tool) 2 | Pods/ 3 | 4 | # Ignore tmp directory (where unit test results are written to) 5 | tmp/ 6 | test-reports/ 7 | 8 | # Ignore build directory (where Xcode places it's build files when ran from the command line) 9 | build/ 10 | 11 | # Ignore target directory (where the maven plugin places it's build files) 12 | target/ 13 | 14 | # Ignore lcov Files 15 | *.info 16 | 17 | # Ignore xcuserdata 18 | xcuserdata/ 19 | 20 | # Ignore Gemfile.lock 21 | Gemfile.lock 22 | 23 | # Ignore Podfile.lock 24 | Podfile.lock 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | notifications: 4 | email: false 5 | 6 | xcode_workspace: ZeroStore.xcworkspace 7 | xcode_scheme: ZeroStore 8 | osx_image: xcode7 9 | 10 | script: ./xctool/xctool.sh -workspace ZeroStore.xcworkspace -scheme ZeroStoreTestsTravis clean test CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -sdk iphonesimulator -destination 'name=iPhone 6,OS=9.0' 11 | 12 | before_install: 13 | - git clone https://github.com/facebook/xctool.git 14 | 15 | -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-29.png -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-29@2x.png -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-29@3x.png -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-40.png -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-40@2x.png -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-40@3x.png -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-60@2x.png -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-60@3x.png -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-76.png -------------------------------------------------------------------------------- /Assets/icon/Action-Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-Icon-76@2x.png -------------------------------------------------------------------------------- /Assets/icon/Action-iTunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Action-iTunesArtwork@2x.png -------------------------------------------------------------------------------- /Assets/icon/Icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-29.png -------------------------------------------------------------------------------- /Assets/icon/Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-29@2x.png -------------------------------------------------------------------------------- /Assets/icon/Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-29@3x.png -------------------------------------------------------------------------------- /Assets/icon/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-40.png -------------------------------------------------------------------------------- /Assets/icon/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-40@2x.png -------------------------------------------------------------------------------- /Assets/icon/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-40@3x.png -------------------------------------------------------------------------------- /Assets/icon/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-60@2x.png -------------------------------------------------------------------------------- /Assets/icon/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-60@3x.png -------------------------------------------------------------------------------- /Assets/icon/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-76.png -------------------------------------------------------------------------------- /Assets/icon/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/Icon-76@2x.png -------------------------------------------------------------------------------- /Assets/icon/iTunesArtwork@2x-header@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/iTunesArtwork@2x-header@2x.png -------------------------------------------------------------------------------- /Assets/icon/iTunesArtwork@2x-header@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/iTunesArtwork@2x-header@3x.png -------------------------------------------------------------------------------- /Assets/icon/iTunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/icon/iTunesArtwork@2x.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 1.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 2.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 3.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 4.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/3.5-inch (iPhone 4) - Screenshot 5.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 1.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 2.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 3.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 4.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4-inch (iPhone 5) - Screenshot 5.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 1.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 2.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 3.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 4.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/4.7-inch (iPhone 6) - Screenshot 5.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 1.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 2.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 3.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 4.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/5.5-inch (iPhone 6+) - Screenshot 5.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/iPad 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/iPad 1.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/iPad 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/iPad 2.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/iPad 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/iPad 3.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/iPad 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/iPad 4.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/status bar 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/status bar 1.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/status bar 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/status bar 2.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/status bar 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/status bar 3.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/status bar 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/status bar 4.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0.1/status bar 5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0.1/status bar 5.png -------------------------------------------------------------------------------- /Assets/screenshots/1.0/3.5-inch (iPhone 4) - Screenshot 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/3.5-inch (iPhone 4) - Screenshot 1.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/3.5-inch (iPhone 4) - Screenshot 3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/3.5-inch (iPhone 4) - Screenshot 3.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/3.5-inch (iPhone 4) - Screenshot 4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/3.5-inch (iPhone 4) - Screenshot 4.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/4-inch (iPhone 5) - Screenshot 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/4-inch (iPhone 5) - Screenshot 1.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/4-inch (iPhone 5) - Screenshot 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/4-inch (iPhone 5) - Screenshot 2.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/4-inch (iPhone 5) - Screenshot 3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/4-inch (iPhone 5) - Screenshot 3.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/4-inch (iPhone 5) - Screenshot 4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/4-inch (iPhone 5) - Screenshot 4.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/4.7-inch (iPhone 6) - Screenshot 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/4.7-inch (iPhone 6) - Screenshot 1.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/4.7-inch (iPhone 6) - Screenshot 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/4.7-inch (iPhone 6) - Screenshot 2.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/4.7-inch (iPhone 6) - Screenshot 3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/4.7-inch (iPhone 6) - Screenshot 3.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/4.7-inch (iPhone 6) - Screenshot 4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/4.7-inch (iPhone 6) - Screenshot 4.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/5.5-inch (iPhone 6+) - Screenshot 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/5.5-inch (iPhone 6+) - Screenshot 1.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/5.5-inch (iPhone 6+) - Screenshot 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/5.5-inch (iPhone 6+) - Screenshot 2.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/5.5-inch (iPhone 6+) - Screenshot 3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/5.5-inch (iPhone 6+) - Screenshot 3.jpg -------------------------------------------------------------------------------- /Assets/screenshots/1.0/5.5-inch (iPhone 6+) - Screenshot 4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/screenshots/1.0/5.5-inch (iPhone 6+) - Screenshot 4.jpg -------------------------------------------------------------------------------- /Assets/tutorial/Tutorial0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/tutorial/Tutorial0@2x.png -------------------------------------------------------------------------------- /Assets/tutorial/Tutorial0@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/tutorial/Tutorial0@3x.png -------------------------------------------------------------------------------- /Assets/tutorial/Tutorial1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/tutorial/Tutorial1@2x.png -------------------------------------------------------------------------------- /Assets/tutorial/Tutorial1@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/tutorial/Tutorial1@3x.png -------------------------------------------------------------------------------- /Assets/tutorial/Tutorial2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/tutorial/Tutorial2@2x.png -------------------------------------------------------------------------------- /Assets/tutorial/Tutorial2@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/tutorial/Tutorial2@3x.png -------------------------------------------------------------------------------- /Assets/tutorial/Tutorial3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/tutorial/Tutorial3@2x.png -------------------------------------------------------------------------------- /Assets/tutorial/Tutorial3@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/tutorial/Tutorial3@3x.png -------------------------------------------------------------------------------- /Assets/zero-store-icon.pcvd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/zero-store-icon.pcvd -------------------------------------------------------------------------------- /Assets/zerostore.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/Assets/zerostore.sketch -------------------------------------------------------------------------------- /EnterPassword/ActionVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionViewController.swift 3 | // EnterPassword 4 | // 5 | // Created by Kyle Bashour on 9/3/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | // I know this is messy and big, but not sure how best to organize — this is my first extension 10 | 11 | import UIKit 12 | import MobileCoreServices 13 | import LocalAuthentication 14 | import SSKeychain 15 | 16 | class ActionVC: UITableViewController, UITextFieldDelegate { 17 | 18 | 19 | // MARK: Properties 20 | 21 | @IBOutlet weak var masterPasswordTextField: UITextField! 22 | @IBOutlet weak var activityIndicator: UIActivityIndicatorView! 23 | 24 | var domain: String? 25 | let defaults = NSUserDefaults(suiteName: Constants.Defaults.suiteName)! 26 | 27 | 28 | // MARK: Lifecycle 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | 33 | getDomain() 34 | } 35 | 36 | override func viewDidAppear(animated: Bool) { 37 | super.viewDidAppear(animated) 38 | 39 | authenticateWithTouchID() 40 | } 41 | 42 | override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { 43 | 44 | return UIInterfaceOrientationMask.Portrait 45 | } 46 | 47 | 48 | // MARK: Actions 49 | 50 | @IBAction func cancelButtonPressed(sender: AnyObject) { 51 | 52 | extensionContext!.completeRequestReturningItems(extensionContext?.inputItems, completionHandler: nil) 53 | } 54 | 55 | 56 | // MARK: Helpers 57 | 58 | func getDomain() { 59 | 60 | guard let item = extensionContext?.inputItems.first, 61 | itemProvider = item.attachments??.first as? NSItemProvider 62 | where itemProvider.hasItemConformingToTypeIdentifier(kUTTypeURL as String) else 63 | { 64 | return 65 | } 66 | 67 | itemProvider.loadItemForTypeIdentifier(kUTTypeURL as String, options: nil) { url, error in 68 | if let url = url as? NSURL, domain = url.host { 69 | let components = domain.componentsSeparatedByString(".") 70 | if components.count >= 2 { 71 | self.domain = components[components.count - 2.. String? { 109 | 110 | let password = SSKeychain.passwordForService(Constants.Keychain.service, account: Constants.Keychain.account) 111 | return password 112 | } 113 | 114 | func generatePassword() { 115 | 116 | enableActivity(true) 117 | 118 | guard let masterPassword = masterPasswordTextField.text where masterPassword != "" else { 119 | showAlert("Failed to Generate Password", message: "Please enter your Master Password") 120 | enableActivity(false) 121 | return 122 | } 123 | 124 | guard let masterDomain = domain else { 125 | showAlert("Failed to Generate Password", message: "We were unable to fetch the service name. Please make sure you're using a compatible brower.") 126 | enableActivity(false) 127 | return 128 | } 129 | 130 | PasswordManager.sharedInstance.generatePassword(masterPassword, userID: masterDomain, length: defaults.integerForKey(Constants.Defaults.length)) { password in 131 | UIPasteboard.generalPasteboard().string = password 132 | self.extensionContext?.completeRequestReturningItems(self.extensionContext!.inputItems, completionHandler: nil) 133 | } 134 | } 135 | 136 | func showAlert(title: String?, message: String?) { 137 | 138 | let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert) 139 | 140 | let closeButton = UIAlertAction(title: "Cancel", style: .Cancel) { _ in 141 | self.extensionContext!.completeRequestReturningItems(self.extensionContext!.inputItems, completionHandler: nil) 142 | } 143 | let tryAgainButton = UIAlertAction(title: "Try Again", style: .Default) { _ in 144 | self.masterPasswordTextField.becomeFirstResponder() 145 | } 146 | 147 | alert.addAction(closeButton) 148 | alert.addAction(tryAgainButton) 149 | 150 | presentViewController(alert, animated: true, completion: nil) 151 | } 152 | 153 | func enableActivity(enabled: Bool) { 154 | 155 | enabled ? activityIndicator.startAnimating() : activityIndicator.stopAnimating() 156 | tableView.userInteractionEnabled = !enabled 157 | } 158 | 159 | 160 | // MARK: Delegate functions 161 | 162 | func textFieldShouldReturn(textField: UITextField) -> Bool { 163 | 164 | generatePassword() 165 | return true 166 | } 167 | 168 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 169 | 170 | tableView.deselectRowAtIndexPath(indexPath, animated: true) 171 | 172 | if indexPath.section == 1 && indexPath.row == 0 { 173 | generatePassword() 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /EnterPassword/Base.lproj/MainInterface.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 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 66 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /EnterPassword/EnterPassword.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.kylebashour.ZeroStore 8 | 9 | keychain-access-groups 10 | 11 | $(AppIdentifierPrefix)com.kylebashour.ZeroStore 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /EnterPassword/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ZeroStore Password 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIcons 12 | 13 | CFBundleIcons~ipad 14 | 15 | CFBundleIdentifier 16 | $(PRODUCT_BUNDLE_IDENTIFIER) 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | $(PRODUCT_NAME) 21 | CFBundlePackageType 22 | XPC! 23 | CFBundleShortVersionString 24 | 1.0.1 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | 15 29 | NSExtension 30 | 31 | NSExtensionAttributes 32 | 33 | NSExtensionActivationRule 34 | 35 | NSExtensionActivationSupportsWebURLWithMaxCount 36 | 1 37 | 38 | 39 | NSExtensionMainStoryboard 40 | MainInterface 41 | NSExtensionPointIdentifier 42 | com.apple.ui-services 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kyle Bashour 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, '8.0' 3 | use_frameworks! 4 | inhibit_all_warnings! 5 | 6 | link_with 'EnterPassword' 7 | 8 | pod 'NAChloride' 9 | pod 'SSKeychain' 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ZeroStore for iOS [![Build Status](https://travis-ci.org/kylebshr/zerostore-ios.svg?branch=develop)](https://travis-ci.org/kylebshr/zerostore-ios) 2 | 3 | An iOS implementation of [zerostore](https://github.com/joseph346/zerostore) by joseph346. This was made mostly for fun — I'm not a cryptogrography expert, and cannot vouch for the security of this project. 4 | 5 | Includes an app extension for use in browsers. 6 | 7 | [![Available on the AppStore](http://cl.ly/WouG/Download_on_the_App_Store_Badge_US-UK_135x40.svg)](https://itunes.apple.com/us/app/zerostore-password-storage/id1037141587?mt=8) 8 | 9 | ## What is this, and why does it exist? 10 | 11 | To quote the [original project](https://github.com/joseph346/zerostore): 12 | 13 | >The goal of this project is to serve as a proof-of-concept for a zero-storage password management system. This means that all the information needed to generate a secure, unique, per-site password can be kept in a user's head. In this way, users can eliminate password reuse without having to memorize multiple passwords or synch password databases between devices. A user should be able to go on any device with this program and have access to all of their passwords without having to import any data. 14 | 15 | ## How to setup 16 | 17 | Fork/clone the repo, then navigate to the directory and run `pod install`. 18 | -------------------------------------------------------------------------------- /ZeroStore.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ZeroStore.xcodeproj/xcshareddata/xcschemes/EnterPassword.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 10 | 16 | 22 | 23 | 24 | 30 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 48 | 54 | 55 | 56 | 57 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 80 | 82 | 88 | 89 | 90 | 91 | 92 | 93 | 100 | 102 | 108 | 109 | 110 | 111 | 113 | 114 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /ZeroStore.xcodeproj/xcshareddata/xcschemes/ZeroStore.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 44 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 114 | 117 | 118 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /ZeroStore.xcodeproj/xcshareddata/xcschemes/ZeroStoreTestsTravis.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 44 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 114 | 117 | 118 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /ZeroStore.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ZeroStore/About.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 | 43 | 50 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /ZeroStore/AboutVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AboutVC.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/7/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AboutVC: UITableViewController { 12 | 13 | 14 | // MARK: Properties 15 | 16 | @IBOutlet weak var twitterLinkLabel: UILabel! 17 | @IBOutlet weak var versionLabel: UILabel! 18 | 19 | let websiteURL = NSURL(string: "http://kylebashour.com")! 20 | let twitterURL = NSURL(string: "twitter://user?screen_name=kylebshr")! 21 | let twitterWebsiteURL = NSURL(string: "http://twitter.com/kylebshr")! 22 | 23 | 24 | // MARK: Lifecycle 25 | 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | 29 | setVersionNumber() 30 | } 31 | 32 | 33 | // MARK: Actions 34 | 35 | @IBAction func dismissButtonPressed(sender: UIBarButtonItem) { 36 | presentingViewController?.dismissViewControllerAnimated(true, completion: nil) 37 | } 38 | 39 | 40 | // MARK: Helper functions 41 | 42 | // Sets the version from the bundle 43 | func setVersionNumber() { 44 | 45 | if let 46 | versionObject = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"], 47 | versionString = versionObject as? String, 48 | buildObject = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"], 49 | buildString = buildObject as? String 50 | { 51 | versionLabel.text = "\(versionString) build \(buildString)" 52 | } 53 | } 54 | 55 | 56 | // MARK: Delefate funtions 57 | 58 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 59 | 60 | tableView.deselectRowAtIndexPath(indexPath, animated: true) 61 | 62 | if indexPath.section == 1 { 63 | // open my website 64 | if indexPath.row == 0 { 65 | UIApplication.sharedApplication().openURL(websiteURL) 66 | } 67 | // try to open Twitter.app, else open in browser 68 | else if indexPath.row == 1 { 69 | if !UIApplication.sharedApplication().openURL(twitterURL) { 70 | UIApplication.sharedApplication().openURL(twitterWebsiteURL) 71 | } 72 | } 73 | 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /ZeroStore/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/3/15. 6 | // Copyright (c) 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 17 | 18 | // Make sure the initial length is set (24 chars) 19 | PasswordManager.setInitialDefaultLength() 20 | 21 | return true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ZeroStore/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 | Set your password here if you want to use TouchID to fetch your account passwords. This is kept securely in the iOS keychain, and never sent anywhere else. 22 | 23 | If you don't set your password here, we never save it anywhere. 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | -------------------------------------------------------------------------------- /ZeroStore/ChangePasswordVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ChangePasswordViewController.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/3/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SSKeychain 11 | 12 | class ChangePasswordVC: UITableViewController, UITextFieldDelegate { 13 | 14 | 15 | // MARK: Properties 16 | 17 | @IBOutlet weak var passwordTextField: UITextField! 18 | @IBOutlet weak var confirmPasswordTextField: UITextField! 19 | 20 | 21 | // MARK: Lifecycle 22 | 23 | override func viewDidAppear(animated: Bool) { 24 | super.viewDidAppear(animated) 25 | 26 | passwordTextField.becomeFirstResponder() 27 | } 28 | 29 | 30 | // MARK: Actions 31 | 32 | @IBAction func cancelButtonPressed(sender: UIBarButtonItem) { 33 | 34 | dismissSelf() 35 | } 36 | 37 | 38 | // MARK: Helper functions 39 | 40 | func dismissSelf() { 41 | 42 | view.endEditing(true) 43 | presentingViewController?.dismissViewControllerAnimated(true, completion: nil) 44 | } 45 | 46 | // Checks that the password is valid and saves it if so 47 | func attemptToSaveNewPassword() { 48 | 49 | if passwordTextField.text != confirmPasswordTextField.text { 50 | showGenericAlert("Your Passwords Don't Match!", message: nil) 51 | } 52 | else if passwordTextField.text == "" { 53 | showGenericAlert("You Need To Enter a Password!", message: nil) 54 | } 55 | else if let newPassword = passwordTextField.text { 56 | SSKeychain.setPassword(newPassword, forService: Constants.Keychain.service, account: Constants.Keychain.account) 57 | dismissSelf() 58 | } 59 | else { 60 | showGenericAlert("Unknown Error", message: "Please get in touch through the About page if this continues to happen") 61 | } 62 | } 63 | 64 | 65 | // MARK: Delegate functions 66 | 67 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 68 | 69 | tableView.deselectRowAtIndexPath(indexPath, animated: true) 70 | 71 | if indexPath.section == 1 && indexPath.row == 0 { 72 | attemptToSaveNewPassword() 73 | } 74 | } 75 | 76 | func textFieldShouldReturn(textField: UITextField) -> Bool { 77 | 78 | if textField === passwordTextField { 79 | confirmPasswordTextField.becomeFirstResponder() 80 | } 81 | else if textField === confirmPasswordTextField { 82 | attemptToSaveNewPassword() 83 | } 84 | return true 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /ZeroStore/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/3/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Constants { 12 | 13 | // For use in Keychain 14 | struct Keychain { 15 | static let service = "ZeroStore" 16 | static let account = "CurrentUser" 17 | } 18 | 19 | // For use when accessing NSUserDefaults 20 | struct Defaults { 21 | static let length = "DefaultPasswordLength" 22 | static let opened = "Opened" 23 | static let suiteName = "group.com.kylebashour.ZeroStore" 24 | } 25 | 26 | // For use when working with Storyboards in code 27 | struct Storyboard { 28 | static let tutorialPageID = "TutorialPage" 29 | } 30 | } -------------------------------------------------------------------------------- /ZeroStore/CryptoAlgorithm.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoAlgorithm.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/8/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum CryptoAlgorithm { 12 | 13 | case MD5, SHA1, SHA224, SHA256, SHA384, SHA512 14 | 15 | var HMACAlgorithm: CCHmacAlgorithm { 16 | var result: Int = 0 17 | switch self { 18 | case .MD5: result = kCCHmacAlgMD5 19 | case .SHA1: result = kCCHmacAlgSHA1 20 | case .SHA224: result = kCCHmacAlgSHA224 21 | case .SHA256: result = kCCHmacAlgSHA256 22 | case .SHA384: result = kCCHmacAlgSHA384 23 | case .SHA512: result = kCCHmacAlgSHA512 24 | } 25 | return CCHmacAlgorithm(result) 26 | } 27 | 28 | var digestLength: Int { 29 | var result: Int32 = 0 30 | switch self { 31 | case .MD5: result = CC_MD5_DIGEST_LENGTH 32 | case .SHA1: result = CC_SHA1_DIGEST_LENGTH 33 | case .SHA224: result = CC_SHA224_DIGEST_LENGTH 34 | case .SHA256: result = CC_SHA256_DIGEST_LENGTH 35 | case .SHA384: result = CC_SHA384_DIGEST_LENGTH 36 | case .SHA512: result = CC_SHA512_DIGEST_LENGTH 37 | } 38 | return Int(result) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-29.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-29@2x-1.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-29@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-29@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-40.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-40@2x-1.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-40@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-40@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-60@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-60@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-76.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/ActionIcon.appiconset/Action-Icon-76@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/ActionIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Action-Icon-29@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Action-Icon-29@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Action-Icon-40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Action-Icon-40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Action-Icon-60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Action-Icon-60@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "Action-Icon-29.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "Action-Icon-29@2x-1.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "Action-Icon-40.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "Action-Icon-40@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "Action-Icon-76.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "Action-Icon-76@2x.png", 73 | "scale" : "2x" 74 | } 75 | ], 76 | "info" : { 77 | "version" : 1, 78 | "author" : "xcode" 79 | } 80 | } -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-29@2x-1.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-29@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-40@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-40@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "60x60", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-60@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-60@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "29x29", 41 | "idiom" : "ipad", 42 | "filename" : "Icon-29.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "Icon-29@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "40x40", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-40.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-40@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "76x76", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-76.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "76x76", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-76@2x.png", 73 | "scale" : "2x" 74 | } 75 | ], 76 | "info" : { 77 | "version" : 1, 78 | "author" : "xcode" 79 | } 80 | } -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-29.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-29@2x-1.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/LargeIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "iTunesArtwork@2x-header@2x-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "iTunesArtwork@2x-header@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "iTunesArtwork@2x-header@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/LargeIcon.imageset/iTunesArtwork@2x-header@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/LargeIcon.imageset/iTunesArtwork@2x-header@2x-1.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/LargeIcon.imageset/iTunesArtwork@2x-header@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/LargeIcon.imageset/iTunesArtwork@2x-header@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/LargeIcon.imageset/iTunesArtwork@2x-header@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/LargeIcon.imageset/iTunesArtwork@2x-header@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Tutorial0@2x-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Tutorial0@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Tutorial0@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial0.imageset/Tutorial0@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial0.imageset/Tutorial0@2x-1.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial0.imageset/Tutorial0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial0.imageset/Tutorial0@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial0.imageset/Tutorial0@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial0.imageset/Tutorial0@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Tutorial1@2x-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Tutorial1@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Tutorial1@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial1.imageset/Tutorial1@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial1.imageset/Tutorial1@2x-1.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial1.imageset/Tutorial1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial1.imageset/Tutorial1@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial1.imageset/Tutorial1@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial1.imageset/Tutorial1@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Tutorial2@2x-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Tutorial2@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Tutorial2@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial2.imageset/Tutorial2@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial2.imageset/Tutorial2@2x-1.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial2.imageset/Tutorial2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial2.imageset/Tutorial2@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial2.imageset/Tutorial2@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial2.imageset/Tutorial2@3x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Tutorial3@2x-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Tutorial3@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Tutorial3@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial3.imageset/Tutorial3@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial3.imageset/Tutorial3@2x-1.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial3.imageset/Tutorial3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial3.imageset/Tutorial3@2x.png -------------------------------------------------------------------------------- /ZeroStore/Images.xcassets/Tutorial3.imageset/Tutorial3@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylebshr/zerostore-ios/62669353fb47b1224f4ca916be9fc6dda5e7cdb9/ZeroStore/Images.xcassets/Tutorial3.imageset/Tutorial3@3x.png -------------------------------------------------------------------------------- /ZeroStore/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 15 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ZeroStore/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 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /ZeroStore/NoPasteTextField.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NoCursorTextField.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/3/15. 6 | // Copyright (c) 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class NoActionTextField: UITextField { 12 | 13 | override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool { 14 | return false 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ZeroStore/PasswordManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PasswordManager.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/3/15. 6 | // Copyright (c) 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import NAChloride 11 | 12 | class PasswordManager { 13 | 14 | 15 | // MARK: Properties 16 | 17 | static let sharedInstance = PasswordManager() 18 | 19 | 20 | // MARK: Lifecycle 21 | 22 | init() { 23 | 24 | // Call this because the extension can be used before the app is launched 25 | PasswordManager.setInitialDefaultLength() 26 | } 27 | 28 | func generatePassword(masterPassword: String, userID: String, length: Int, completion: (String -> ())?) { 29 | 30 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 31 | 32 | let salt = ("zerostore-salt" + userID as NSString).dataUsingEncoding(NSUTF8StringEncoding)! 33 | let password = (masterPassword as NSString).dataUsingEncoding(NSUTF8StringEncoding)! 34 | let data = try! NAScrypt.scrypt(password, salt: salt, n: 16384, r: 8, p: 1, length: 64) 35 | let digest = userID.hmac(CryptoAlgorithm.SHA256, key: data) 36 | let range = Range(start: digest.startIndex, end: digest.startIndex.advancedBy(length )) 37 | 38 | // DEBUG 39 | 40 | // print("password used: \(masterPassword)") 41 | // print("userID user: \(userID)") 42 | // print("password generated: \(digest.substringWithRange(range))") 43 | 44 | completion?(digest.substringWithRange(range)) 45 | } 46 | } 47 | 48 | // Set the password length in the defaults if there isn't one set 49 | class func setInitialDefaultLength() { 50 | 51 | guard let defaults = NSUserDefaults(suiteName: Constants.Defaults.suiteName) 52 | where !defaults.boolForKey(Constants.Defaults.opened) else 53 | { 54 | return 55 | } 56 | 57 | defaults.setBool(true, forKey: Constants.Defaults.opened) 58 | defaults.setInteger(24, forKey: Constants.Defaults.length) 59 | defaults.synchronize() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ZeroStore/SettingsVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/3/15. 6 | // Copyright (c) 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SSKeychain 11 | 12 | class SettingsVC: UITableViewController { 13 | 14 | 15 | // MARK: Properties 16 | 17 | @IBOutlet weak var defaultLengthTextField: UITextField! 18 | 19 | let defaults = NSUserDefaults(suiteName: Constants.Defaults.suiteName)! 20 | 21 | 22 | // MARK: Lifecycle 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | 27 | setUpUI() 28 | } 29 | 30 | override func viewWillAppear(animated: Bool) { 31 | super.viewWillAppear(animated) 32 | 33 | // Need this to animate cell deselection interactively on swipeback 34 | // (currently not needed, no VCs are pushed — but if any are added, this needs to be here) 35 | if let selectedIndex = tableView.indexPathForSelectedRow { 36 | tableView.deselectRowAtIndexPath(selectedIndex, animated: animated) 37 | } 38 | } 39 | 40 | // Set up the UI elements that aren't in the storyboard 41 | func setUpUI() { 42 | 43 | let defaultLength = defaults.integerForKey(Constants.Defaults.length) 44 | let doneBarButton = UIBarButtonItem(title: "Done", style: .Done, target: self, action: "dismissKeyboard") 45 | let spacing = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: self, action: nil) 46 | let doneBar = UIToolbar(frame: CGRectMake(0, 0, view.frame.width, 44)) 47 | 48 | doneBar.backgroundColor = UIColor.whiteColor() 49 | doneBar.items = [spacing, doneBarButton] 50 | 51 | defaultLengthTextField.inputAccessoryView = doneBar 52 | defaultLengthTextField.text = "\(defaultLength)" 53 | 54 | // viewWillAppear does this better 55 | clearsSelectionOnViewWillAppear = false 56 | } 57 | 58 | 59 | // MARK: Helper functions 60 | 61 | // Called when done editing the length 62 | func dismissKeyboard() { 63 | 64 | saveCurrentLength() 65 | defaultLengthTextField.resignFirstResponder() 66 | } 67 | 68 | // Checks and saves the entered length 69 | func saveCurrentLength() { 70 | 71 | guard let selectedLength = Int(defaultLengthTextField.text ?? "") where selectedLength <= 44 && selectedLength >= 4 else { 72 | showGenericAlert("Invalid Length", message: "Please make sure the length is a number between 4 and 44") 73 | return 74 | } 75 | 76 | defaults.setInteger(selectedLength, forKey: Constants.Defaults.length) 77 | defaults.synchronize() 78 | defaultLengthTextField.text = "\(selectedLength)" 79 | } 80 | 81 | // Removes the current password using a popup for confirmation 82 | func askToRemovePassword() { 83 | 84 | if SSKeychain.passwordForService(Constants.Keychain.service, account: Constants.Keychain.account) == nil { 85 | showGenericAlert("You Didn't Have a Password Saved", message: nil) 86 | } 87 | else { 88 | let confirmation = UIAlertController(title: "Are you sure?", message: "If you remove your password from the keychain, you'll have to type your Master Password every time you generate a service password.", preferredStyle: .Alert) 89 | let cancelButton = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil) 90 | let confirmButton = UIAlertAction(title: "Remove", style: .Destructive) { _ in 91 | self.attemptPasswordRemoval() 92 | } 93 | 94 | confirmation.addAction(cancelButton) 95 | confirmation.addAction(confirmButton) 96 | presentViewController(confirmation, animated: true, completion: nil) 97 | } 98 | } 99 | 100 | // Actually attempt the removal 101 | func attemptPasswordRemoval() { 102 | 103 | if SSKeychain.deletePasswordForService(Constants.Keychain.service, account: Constants.Keychain.account) { 104 | self.showGenericAlert("Successfully Removed Password", message: "Your Master Password has been removed from the keychain. You'll have to type it in manually now.") 105 | } 106 | else { 107 | self.showGenericAlert("Failed to Remove Password", message: "For some reason, Keychain isn't letting us delete the password! Please try quitting ZeroStore and trying again.") 108 | } 109 | } 110 | 111 | 112 | // MARK: Delegate functions 113 | 114 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 115 | 116 | tableView.deselectRowAtIndexPath(indexPath, animated: true) 117 | 118 | if indexPath.section == 0 && indexPath.row == 0 { 119 | defaultLengthTextField.becomeFirstResponder() 120 | } 121 | if indexPath.section == 0 && indexPath.row == 2 { 122 | askToRemovePassword() 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /ZeroStore/String+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Extensions.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/3/15. 6 | // Copyright (c) 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | // From http://stackoverflow.com/questions/24099520/commonhmac-in-swift 10 | // Modified to give back a base64 string 11 | 12 | import Foundation 13 | 14 | extension String { 15 | 16 | func hmac(algorithm: CryptoAlgorithm, key: NSData) -> String { 17 | 18 | let str = self.cStringUsingEncoding(NSUTF8StringEncoding) 19 | let strLen = Int(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)) 20 | let digestLen = algorithm.digestLength 21 | let result = UnsafeMutablePointer.alloc(digestLen) 22 | let keyStr = UnsafePointer(key.bytes) 23 | let keyLen = key.length 24 | 25 | CCHmac(algorithm.HMACAlgorithm, keyStr, keyLen, str!, strLen, result) 26 | let base64 = NSData(bytes: result, length: digestLen).base64EncodedStringWithOptions([]) 27 | result.dealloc(digestLen) 28 | 29 | return base64 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ZeroStore/Tutorial.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 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 109 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /ZeroStore/TutorialContainerVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TutorialContainerVC.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/4/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TutorialContainerVC: UIViewController { 12 | 13 | 14 | // MARK: Properties 15 | 16 | @IBOutlet weak var pageControl: UIPageControl! 17 | 18 | 19 | // MARK: Actions 20 | 21 | @IBAction func dismissButtonPressed(sender: UIBarButtonItem) { 22 | 23 | presentingViewController?.dismissViewControllerAnimated(true, completion: nil) 24 | } 25 | 26 | 27 | // MARK: Lifecycle 28 | 29 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 30 | if let destination = segue.destinationViewController as? TutorialVC { 31 | destination.pageControl = pageControl 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ZeroStore/TutorialPageVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TutorialPageVC.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/5/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TutorialPageVC: UIViewController { 12 | 13 | 14 | // MARK: Properties 15 | 16 | @IBOutlet weak var imageView: UIImageView! 17 | @IBOutlet weak var label: UILabel! 18 | @IBOutlet weak var noteLabel: UILabel! 19 | 20 | var nextPage = 0 21 | var previousPage = 0 22 | } 23 | -------------------------------------------------------------------------------- /ZeroStore/TutorialVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TutorialVC.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/4/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TutorialVC: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate { 12 | 13 | 14 | // MARK: Properties 15 | 16 | weak var pageControl: UIPageControl? 17 | 18 | let phrases = [ 19 | "Open Safari, then tap the arrow to open the action sheet", 20 | "Slide all the way to the right, and tap on \"More\"", 21 | "Turn on the ZeroStore action", 22 | "Tap on the ZeroStore Password icon to use ZeroStore in your browser" 23 | ] 24 | let notes = [ 25 | "", 26 | "", 27 | "Note: if you don't see the ZeroStore action in the list, you may be using an incompatible browser.", 28 | "" 29 | ] 30 | 31 | 32 | // MARK: Lifecycle 33 | 34 | override func viewDidLoad() { 35 | super.viewDidLoad() 36 | 37 | dataSource = self 38 | delegate = self 39 | 40 | // Sets the initial page for the tutorial 41 | setViewControllers([tutorialViewControllers[0]!], direction: .Forward, animated: false, completion: nil) 42 | } 43 | 44 | 45 | // MARK: Computed/Lazy properties 46 | 47 | // Create and save all the view controllers in memory for less glitchy paging 48 | lazy var tutorialViewControllers: [Int: TutorialPageVC] = { 49 | 50 | var viewControllers = [Int: TutorialPageVC]() 51 | 52 | for (index, phrase) in self.phrases.enumerate() { 53 | 54 | let image = UIImage(named: "Tutorial\(index)") 55 | let tutorialPage = self.storyboard!.instantiateViewControllerWithIdentifier(Constants.Storyboard.tutorialPageID) as! TutorialPageVC 56 | 57 | let _ = tutorialPage.view 58 | 59 | tutorialPage.nextPage = index + 1 60 | tutorialPage.previousPage = index - 1 61 | tutorialPage.imageView.image = image 62 | tutorialPage.label.text = phrase 63 | tutorialPage.noteLabel.text = self.notes[index] 64 | 65 | viewControllers[index] = tutorialPage 66 | } 67 | 68 | return viewControllers 69 | }() 70 | 71 | 72 | // MARK: Delegate functions 73 | 74 | func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { 75 | pageControl?.currentPage = (viewControllers!.last as! TutorialPageVC).nextPage - 1 76 | } 77 | 78 | 79 | // MARK: Datasource functions 80 | 81 | func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? { 82 | return tutorialViewControllers[(viewController as! TutorialPageVC).previousPage] 83 | } 84 | 85 | func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? { 86 | return tutorialViewControllers[(viewController as! TutorialPageVC).nextPage] 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /ZeroStore/UIViewController+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Extensions.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/8/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIViewController { 12 | 13 | // Shows an alert with an OK button and the given title and message 14 | func showGenericAlert(title: String?, message: String?) { 15 | 16 | let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert) 17 | let tryAgainButton = UIAlertAction(title: "OK", style: .Default, handler: nil) 18 | 19 | alert.addAction(tryAgainButton) 20 | presentViewController(alert, animated: true, completion: nil) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ZeroStore/ZeroStore-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import 6 | -------------------------------------------------------------------------------- /ZeroStore/ZeroStore.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.kylebashour.ZeroStore 8 | 9 | keychain-access-groups 10 | 11 | $(AppIdentifierPrefix)com.kylebashour.ZeroStore 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ZeroStoreTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 15 23 | 24 | 25 | -------------------------------------------------------------------------------- /ZeroStoreTests/TestConstants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestConstants.swift 3 | // ZeroStore 4 | // 5 | // Created by Kyle Bashour on 9/5/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // A few constants for testing 12 | struct TestConstants { 13 | 14 | static let fullGoogleURL = "https://www.google.com/this/?isa&url" 15 | static let shortGoogleURL = "google.com" 16 | static let longMasterPassword = "a master password 123" 17 | static let shortMasterPassword = "master" 18 | static let longMasterSolution = "3TOGk9PDOKM51nWkIhAf9i7C" 19 | static let shortMasterSolution = "m463yq45LfCVvQOsB/eA28y/" 20 | 21 | } -------------------------------------------------------------------------------- /ZeroStoreTests/TestPasswordGeneration.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZeroStoreTests.swift 3 | // ZeroStoreTests 4 | // 5 | // Created by Kyle Bashour on 9/3/15. 6 | // Copyright (c) 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class TestPasswordGeneration: XCTestCase { 13 | 14 | // Simple tests to make sure passwords are created correctly 15 | 16 | func testShortPassword() { 17 | 18 | let expectation = expectationWithDescription("Short Password") 19 | 20 | PasswordManager.sharedInstance.generatePassword(TestConstants.shortMasterPassword, userID: TestConstants.shortGoogleURL, length: 24) { password in 21 | XCTAssert(password == TestConstants.shortMasterSolution) 22 | expectation.fulfill() 23 | } 24 | 25 | waitForExpectationsWithTimeout(2, handler: nil) 26 | } 27 | 28 | func testLongPassword() { 29 | 30 | let expectation = expectationWithDescription("Long Password") 31 | 32 | PasswordManager.sharedInstance.generatePassword(TestConstants.longMasterPassword, userID: TestConstants.shortGoogleURL, length: 24) { password in 33 | XCTAssert(password == TestConstants.longMasterSolution) 34 | expectation.fulfill() 35 | } 36 | 37 | waitForExpectationsWithTimeout(2, handler: nil) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ZeroStoreUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 15 23 | 24 | 25 | -------------------------------------------------------------------------------- /ZeroStoreUITests/ZeroStoreUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZeroStoreUITests.swift 3 | // ZeroStoreUITests 4 | // 5 | // Created by Kyle Bashour on 9/5/15. 6 | // Copyright © 2015 Kyle Bashour. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import SSKeychain 11 | 12 | // Some UI tests — still new to these, they can probably be improved a lot 13 | class ZeroStoreUITests: XCTestCase { 14 | 15 | let domainName = NSBundle.mainBundle().bundleIdentifier! 16 | let defaults = NSUserDefaults(suiteName: Constants.Defaults.suiteName)! 17 | 18 | override func setUp() { 19 | super.setUp() 20 | 21 | continueAfterFailure = false 22 | 23 | XCUIApplication().launch() 24 | 25 | defaults.removePersistentDomainForName(Constants.Defaults.suiteName) 26 | SSKeychain.deletePasswordForService(Constants.Keychain.service, account: Constants.Keychain.account) 27 | } 28 | 29 | override func tearDown() { 30 | 31 | super.tearDown() 32 | } 33 | 34 | func testTutorial() { 35 | 36 | let app = XCUIApplication() 37 | app.tables.staticTexts["How to Use ZeroStore"].tap() 38 | 39 | let element = app.childrenMatchingType(XCUIElementType.Window).elementBoundByIndex(0) 40 | element.swipeLeft() 41 | element.swipeLeft() 42 | element.swipeLeft() 43 | 44 | app.navigationBars["Tutorial"].buttons["Stop"].tap() 45 | } 46 | 47 | func testPasswordLength() { 48 | 49 | let app = XCUIApplication() 50 | let tablesQuery = app.tables 51 | tablesQuery.staticTexts["Password Length"].tap() 52 | 53 | let deleteKey = app.keys["Delete"] 54 | deleteKey.doubleTap() 55 | 56 | let textField = tablesQuery.cells.containingType(.StaticText, identifier:"Password Length").childrenMatchingType(.TextField).element 57 | textField.typeText("3") 58 | 59 | let doneButton = app.toolbars.buttons["Done"] 60 | doneButton.tap() 61 | 62 | let okButton = app.alerts["Invalid Length"].collectionViews.buttons["OK"] 63 | okButton.tap() 64 | deleteKey.doubleTap() 65 | textField.typeText("55") 66 | doneButton.tap() 67 | okButton.tap() 68 | deleteKey.doubleTap() 69 | textField.typeText("24") 70 | doneButton.tap() 71 | } 72 | 73 | func testSettingMasterPassword() { 74 | 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /increment_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | agvtool next-version -all 4 | --------------------------------------------------------------------------------