2
0

Compare commits

...

126 Commits

Author SHA1 Message Date
Maarten Billemont
c97546a232 Improvements to login name editing, saving/generating. 2014-09-16 00:34:22 -04:00
Maarten Billemont
88fdc89f27 Removed iCloud + added generated login names.
[REMOVED]   UbiquityStoreManager and iCloud support.  Now using simplified local Core Data store logic.
[ADDED]     Generating site login names.
[IMPROVED]  Some refactoring and interface improvements for optionally generated user names.
2014-09-15 08:47:36 -04:00
Maarten Billemont
9109a59410 Fixes for better landscape sizing of avatar cells. 2014-09-12 17:13:33 -04:00
Maarten Billemont
61bed8b29c Fixes for positioning of avatars in different states. 2014-09-12 00:41:17 -04:00
Maarten Billemont
72b1d36626 Fix sizing issues with avatars on different size devices.
[FIXED]     Avatar cells badly sized on some size devices.
2014-09-11 20:31:23 -04:00
Maarten Billemont
6e14554f95 Weird layout problems now when building from Xcode 6.. 2014-09-11 00:26:01 -04:00
Maarten Billemont
fecbd2ea1c Some storyboard maintenance for Xcode 6. 2014-09-10 22:40:43 -04:00
Maarten Billemont
1c5f5675a5 Project update. 2014-09-10 22:18:26 -04:00
Maarten Billemont
76b717e06d Fix build for iOS simulator. 2014-09-10 22:07:51 -04:00
Maarten Billemont
eb48f749e2 Remove Love Lyndir from privacy statement, no longer used. 2014-09-09 08:35:32 -04:00
Maarten Billemont
398f7bdb66 login name UI improvements and saved key login fix.
[IMPROVED]  -saveContent now returns YES if successful and NO if nothing changed.
[FIXED]     Fix for unsetting the login key when key is saved due to a notification race.
[IMPROVED]  UI improvements for login name.
[IMPROVED]  Remove system fonts all-over and replace with Exo2.
[IMPROVED]  Various UI improvements and fixes throughout.
2014-09-08 00:15:18 -04:00
Maarten Billemont
d40ccee0fe Update of icons and site updates with new support and mac app store link. 2014-09-04 00:30:51 -04:00
Maarten Billemont
a481626f80 Small tweaks to avoid a rare crash during initialization of cells. 2014-09-03 19:29:46 -04:00
Maarten Billemont
24c48a78f8 Minor Pearl bump. 2014-09-02 23:50:32 -04:00
Maarten Billemont
edda3cf12a Fix the border radius of the iOS icon. 2014-09-02 23:48:04 -04:00
Maarten Billemont
6c2cd01015 Prettier password cells. 2014-09-02 23:19:34 -04:00
Maarten Billemont
c9988d8cc2 Fix for showing setup VC on landscape iPad + old -> new section objects crash. 2014-09-02 21:40:53 -04:00
Maarten Billemont
a8bb434ded Add mp.update.check property to disable update checking. 2014-08-31 22:14:18 -04:00
Maarten Billemont
1e8a832cba Bump lyndir POM to 1.20 to fix some warnings and dependency issues. 2014-08-31 21:55:37 -04:00
Maarten Billemont
4f70e0f676 Master Password Java GUI update. 2014-08-30 20:11:10 -04:00
Maarten Billemont
9d7799c814 Improved Master Password algorithm API & GUI improvements.
[IMPROVED]  Read the master password using Console, not stdin.
[IMPROVED]  Clear the site password when the dialog closes.
[IMPROVED]  Make the site password selectable.
2014-08-30 20:08:20 -04:00
Maarten Billemont
2adb74c971 Make log level configurable with -Dlog.level, default to INFO. Thanks @pitpalme. 2014-08-30 15:54:52 -04:00
Maarten Billemont
cc80a66331 Update of images on homepage. 2014-08-29 21:07:49 -04:00
Maarten Billemont
cf8ecb2952 Site style tweaks and Android beta link. 2014-08-28 20:10:53 -04:00
Maarten Billemont
adcea94a37 Master Password update on the site for Android & Java GUI. 2014-08-28 09:53:08 -04:00
Maarten Billemont
3ebef16007 Sign android release build and fix check for Apple classes in GUI. 2014-08-28 09:50:10 -04:00
Maarten Billemont
3225985e1e Fix update check. 2014-08-28 00:07:24 -04:00
Maarten Billemont
76280ac71c Update check for Java GUI + Copy password on Android + Native scrypt for Android. 2014-08-27 23:05:24 -04:00
Maarten Billemont
f47ff67ba9 Add tip to copy password & close app + less console verbosity in Java GUI. 2014-08-27 22:08:53 -04:00
Maarten Billemont
65cef6d8ed First working Master Password for Android, yay! 2014-08-26 19:54:33 -04:00
Maarten Billemont
89145d6e13 Prepare for Android development.
[FIXED]     Naming of avatar images.
[FIXED]     Dependency, SDK & other Maven configuration.
[UPDATED]   Dependencies changed to stable versions.
2014-08-24 22:43:34 -04:00
Maarten Billemont
63b4c605e2 OS X -> Mac 2014-08-24 00:22:03 -04:00
Maarten Billemont
b3b7858c1d Round-rect Mac icon. 2014-08-24 00:13:01 -04:00
Maarten Billemont
eb4ea08a8b Update Media.xcassets. 2014-08-24 00:01:17 -04:00
Maarten Billemont
51d61b8bc0 Mac Icon update. 2014-08-23 23:36:18 -04:00
Maarten Billemont
bddbd199e2 Type warning fixes. 2014-08-23 23:33:10 -04:00
Maarten Billemont
b579dac180 Icon update. 2014-08-23 19:17:41 -04:00
Maarten Billemont
609675f663 Minor type fixes. 2014-08-23 01:41:46 -04:00
Maarten Billemont
c57bd5d5d3 A few fixes to site import/export.
[FIXED]     A few core data issues.
[ADDED]     Avatar to export file.
[ADDED]     Generated site counter to export file.
[ADDED]     Site login name to export file.
2014-08-23 01:39:47 -04:00
Maarten Billemont
a4fe13842a Release build fixes. 2014-08-22 00:57:53 -04:00
Maarten Billemont
56bb5bf5db Provisioning profile update. 2014-08-22 00:55:01 -04:00
Maarten Billemont
f720d552bb Bump Pearl. 2014-08-22 00:53:11 -04:00
Maarten Billemont
ce8a00fd48 Minor fixes and guide pages update. 2014-08-22 00:51:36 -04:00
Maarten Billemont
d72defb0bc More optimal layoutIfNeeded. 2014-08-21 22:27:47 -04:00
Maarten Billemont
27f6bd7905 Edit indicator, cell reuse fix and item reloading improvement.
[ADDED]     Indicator when user needs to find the edit button to either set a password or login name.
[FIXED]     Cell reuse when changing between transient / element.
[IMPROVED]  Collection view item reloading now avoids reloading items that stay the same and animates better.
2014-08-21 21:51:47 -04:00
Maarten Billemont
2aebcadf70 Merge branch 'master' of github.com:Lyndir/MasterPassword 2014-08-21 00:31:59 -04:00
Maarten Billemont
cf750f30e0 Small fixes to the website. 2014-08-21 00:31:52 -04:00
Maarten Billemont
cf52221175 Deprecate iCloud and remove hardcoded absolute paths from lib dirs. 2014-08-21 00:30:38 -04:00
Maarten Billemont
adc79d331b Initial work on an Android master password app. 2014-08-21 00:26:47 -04:00
Maarten Billemont
942d10e7a2 Merge branch 'master' of github.com:Lyndir/MasterPassword 2014-08-20 15:22:31 -04:00
Maarten Billemont
aa60dcfbe4 The x template doesn't use all the symbols from the o template. 2014-08-20 15:22:08 -04:00
Maarten Billemont
a831e15b3e No more iCloud advertisement. 2014-08-11 21:56:50 +02:00
Maarten Billemont
18ae7a316f Master Password OS X on the website. 2014-08-11 21:49:00 +02:00
Maarten Billemont
7bcc631caf Build configuration for correct header copying and disable iCloud for Mac. 2014-08-11 21:14:30 +02:00
Maarten Billemont
caab474355 Fixed strength calculations, added a strength level and upgraded openssl to 1.0.1h 2014-07-28 18:53:50 -04:00
Maarten Billemont
2d4e26e009 Added time-to-crack.
[ADDED]     Compute time-to-crack for all passwords, including personal ones.
2014-07-26 01:26:33 -04:00
Maarten Billemont
7ce8df664c Merge branch 'master' of github.com:Lyndir/MasterPassword 2014-07-21 22:58:18 -04:00
Maarten Billemont
6597a44096 Change type of sites and edit password / login name. 2014-07-21 22:57:57 -04:00
Maarten Billemont
b481af2a51 Serious rewrite of site configuration UI. 2014-07-20 23:54:32 -04:00
Maarten Billemont
d35434705c Minor change. 2014-07-18 22:44:41 -04:00
Maarten Billemont
512f6faf84 Deprecating iCloud on Mac. 2014-07-18 22:04:10 -04:00
Maarten Billemont
60ecd8181e track outbound links. 2014-07-18 12:03:27 -04:00
Maarten Billemont
31b2f22ded Bump css version. 2014-07-18 10:06:02 -04:00
Maarten Billemont
9d5c2e29af Fix play icon on video button. 2014-07-18 10:05:07 -04:00
Maarten Billemont
3740ade240 Merge branch 'master' of github.com:Lyndir/MasterPassword 2014-07-18 09:45:10 -04:00
Maarten Billemont
9f2c83e4a9 Master Password video on index page. 2014-07-18 09:45:05 -04:00
Maarten Billemont
82195ee090 Site: Leaning laptop main image. 2014-07-18 09:43:40 -04:00
Maarten Billemont
eb2e070fe3 Site: known issues. 2014-07-17 14:37:15 -04:00
Maarten Billemont
14311dfe66 Fix weirdly added excess statement... 2014-07-02 00:00:12 -04:00
Maarten Billemont
10838aad00 Remove stale Love Lyndir references. 2014-07-01 23:56:44 -04:00
Maarten Billemont
d340278ec5 Did Travis CI fix their shell escaping? 2014-07-01 23:46:42 -04:00
Maarten Billemont
2eb074be87 Some fixes to the Java GUI. Thanks cuardin!
[UPDATED]   Allow lookup by short name.
[FIXED]     GUI only supports generated types, only show generated types in its list.
[UPDATED]   Update site password when type changes.
[FIXED]     Exceptions on illegal input arguments for generation, eg. empty site name.
2014-07-01 12:41:35 -04:00
Maarten Billemont
b84c9b79c8 Travis fix attempt. 2014-07-01 01:13:16 -04:00
Maarten Billemont
c367d5e6cb Small tip tweak. 2014-06-30 22:56:18 -04:00
Maarten Billemont
f8973d6c52 Added some general usage tips. 2014-06-30 21:32:17 -04:00
Maarten Billemont
beaf4e67e7 Small UI tweaks. 2014-06-30 21:12:37 -04:00
Maarten Billemont
06a150792d Catch commands when sites table is active.
[REMOVED]   Love Lyndir, just linking to http://thanks.lhunath.com now.
[UPDATED]   PearlString -> strf
[ADDED]     Catching commands when the sites table view is active too (enter/esc/..)
2014-06-30 21:00:25 -04:00
Maarten Billemont
9816e783e7 Fixed a sizing issue with the new icons. 2014-06-30 00:23:02 -04:00
Maarten Billemont
8b26c301cf Updated icon. 2014-06-30 00:17:03 -04:00
Maarten Billemont
6ddd608a3f Provisioning profiles update. 2014-06-29 23:30:00 -04:00
Maarten Billemont
f1a72d8160 Initial window improvements, reveal and reset master password.
[FIXED]     Initial intro window didn't always show up reliably.
[ADDED]     Ability to temporarily reveal master password while typing it.
[IMPROVED]  When you go down the sites list, fade out the fade-out gradient to prevent the selection from becoming invisible.
[ADDED]     Ability to reset your master password.
[UPDATED]   Initial screenshot of Master Password for Mac and iPhone.
2014-06-29 23:18:25 -04:00
Maarten Billemont
6d4d57441b Usage tip on hide passwords. 2014-06-29 00:29:05 -04:00
Maarten Billemont
971538d6b5 Remove dialog & add import/export
[REMOVED]   Mac password Dialog.
[ADDED]     Mac sites import / export.
[FIXED]     Copying of hidden passwords.
2014-06-28 23:45:06 -04:00
Maarten Billemont
34d8dc375f Update screen capture code to accurately capture the active display only. 2014-06-28 00:04:40 -04:00
Maarten Billemont
f294a8c9f5 hidePasswords, preferences, UI improvements.
[ADDED]     hidePasswords to Mac app for hiding the passwords in the large passwords display, hold alt to reveal.
[ADDED]     Way to easily open the Mac app's preferences.
[IMPROVED]  Use transparent main window to improve the blur effect.
[ADDED]     Key equivalent coach marks when holding alt.
[FIXED]     Don't change sites table when site text field loses focus.
2014-06-26 23:13:21 -04:00
Maarten Billemont
2bd4d57869 Mention IRC channel on site. 2014-06-26 01:59:09 -04:00
Maarten Billemont
c7344dbb0c Small usage tip. 2014-06-26 01:44:53 -04:00
Maarten Billemont
97809a1bc7 Added fancy password display. 2014-06-26 01:35:05 -04:00
Maarten Billemont
5056f9e2e4 Add missing features to new Mac UI: changing password type, setting custom passwords, deleting sites. 2014-06-26 01:19:42 -04:00
Maarten Billemont
150304941c UI changes to the results table. 2014-06-25 14:14:56 -04:00
Maarten Billemont
ff36f6ce87 The search for a background that works on all screens ... 2014-06-24 22:00:33 -04:00
Maarten Billemont
6422084fa0 UI improvements to the Mac app. 2014-06-24 20:30:15 -04:00
Maarten Billemont
651a398798 More Mac GUI work. 2014-06-24 10:47:04 -04:00
Maarten Billemont
31b667c7f7 More work on the experimental new Mac gui. 2014-06-24 00:55:08 -04:00
Maarten Billemont
10affd615c Remove TestFlight. 2014-06-21 23:12:14 -04:00
Maarten Billemont
126c962a98 Disable cloudSwitch when iCloud is unavailable. 2014-06-21 23:04:56 -04:00
Maarten Billemont
2d6a298095 Provisioning profile update. 2014-06-21 22:16:19 -04:00
Maarten Billemont
cc086e2dff A step-by-step guide, fix setup appearance + fix capitalization of master password.
[ADDED]     A new step-by-step guide which uses images and text to explain the basics of Master Password.
[FIXED]     The setup flow didn't appear anymore.
[FIXED]     When creating a new user, the master password field was auto-capitalized.
2014-06-21 22:00:27 -04:00
Maarten Billemont
c5fc87b7b5 An experimental new mac ui that blurs the whole screen. 2014-06-21 21:56:28 -04:00
Maarten Billemont
1433c0851e Crashlytics update. 2014-06-15 20:26:07 -04:00
Maarten Billemont
c60780a197 Hide passwords, placeholder visibility, cancel search, copy login and dark keyboard.
[ADDED]     Option to hide passwords and reveal with long-touch.
[IMPROVED]  More visible placeholder text.
[ADDED]     Cancel button on search field.
[ADDED]     Ability to copy user name.
[UPDATED]   Use dark style keyboard throughout to avoid flickery switches.
[FIXED]     Smaller ui fixes.
2014-06-15 19:51:03 -04:00
Maarten Billemont
bb48771989 Small main context fix. 2014-06-15 11:56:29 -04:00
Maarten Billemont
5466e48629 Allow leaving the master password empty in the config file for the GUI. 2014-06-15 00:05:45 -04:00
Maarten Billemont
d4969a776a Update GUI jar on site. 2014-06-14 23:37:07 -04:00
Maarten Billemont
bb81f5bd5b Merge branch 'master' of github.com:Lyndir/MasterPassword 2014-06-14 23:35:38 -04:00
Maarten Billemont
c38920f238 Improve reliability with regards to bad config files. 2014-06-14 23:33:00 -04:00
Maarten Billemont
be0ae7ff45 UI improvements for the Java GUI. 2014-06-11 09:16:24 -04:00
Maarten Billemont
6808016ab7 Added support for the C CLI's ~/.mpw config file to speed up sign-in to the GUI. 2014-06-11 01:45:31 -04:00
Maarten Billemont
d3c2698790 Add FreeBSD CLI binary. 2014-06-10 16:33:12 -04:00
Maarten Billemont
d1cc9481c3 Small C build and script fixes. 2014-06-10 16:26:24 -04:00
Maarten Billemont
cced75cdfe Update site with different Master Password options. 2014-06-08 23:49:49 -04:00
Maarten Billemont
b74bc79699 A basic cross-platform GUI for the Master Password generation algorithm. 2014-06-08 16:39:26 -04:00
Maarten Billemont
585268eb0f Update AdHoc provisioning. 2014-06-07 20:16:06 -04:00
Maarten Billemont
a713a639cd Added "delete user", fixed some minor UI issues. 2014-06-07 20:13:53 -04:00
Maarten Billemont
113c3790fb Added OS X precompiled binary package. 2014-06-07 15:53:41 -04:00
Maarten Billemont
d732b03828 Finished the C implementation & CLI tool. Providing an OS X binary. 2014-06-07 15:51:11 -04:00
Maarten Billemont
cf9dabcc82 Closed Mac beta due to overwhelming demand! 2014-06-07 13:03:12 -04:00
Maarten Billemont
2bc357cee6 WIP - Initial complete C implementation that's still buggy and generates broken passwords, yay. 2014-06-07 01:27:18 -04:00
Maarten Billemont
c4dca14800 Merge branch 'crashlytics-196' 2014-06-05 22:41:44 -04:00
Maarten Billemont
d8e2707ac0 Fixed crash when scrolling to first element of transient site.
[FIXED]     The first cell of the transient site isn't a Delete button, this caused a crash due to it being rendered with an unexpected type.
2014-06-05 22:41:28 -04:00
Maarten Billemont
25df56f90a Merge branch 'crashlytics-198'
Conflicts:
	External/Pearl
2014-06-05 22:03:32 -04:00
Maarten Billemont
2006e382d4 Hopefully fixed issue with rendering maximum security cells re-used from "new site" cells.
[FIXED]     When a "new site" cell gets recycled as a "maximum security" entity's cell, we may not be able to scroll to the cell index for the type because the collection view's cell indexes weren't updated yet.
2014-06-05 22:00:20 -04:00
Maarten Billemont
98bffa3755 Merge branch 'master' of github.com:Lyndir/MasterPassword 2014-06-05 21:44:23 -04:00
Maarten Billemont
789aa26066 Fix infinite loop when enabling iCloud.
[FIXED]     When enabling iCloud and setting the local user defaults, we re-started enabling iCloud and updating local user defaults.
2014-06-05 21:43:06 -04:00
Maarten Billemont
773058da78 WIP - remove dependency on ciphers.plist. 2014-06-05 17:49:16 -04:00
Maarten Billemont
339ef8d1bc Small improvements to the Internet Defense League code snippet. 2014-06-05 17:48:07 -04:00
442 changed files with 11686 additions and 8546 deletions

1
.gitignore vendored
View File

@@ -29,6 +29,7 @@ Press/MasterPassword_PressKit/MasterPassword_pressrelease_*.pdf
MasterPassword/Java/**/target
# C
MasterPassword/C/*.o
MasterPassword/C/mpw
MasterPassword/C/lib/*/*
!MasterPassword/C/lib/*/.source

3
.gitmodules vendored
View File

@@ -10,6 +10,3 @@
[submodule "External/RHStatusItemView"]
path = External/RHStatusItemView
url = git://github.com/lhunath/RHStatusItemView.git
[submodule "External/LoveLyndir"]
path = External/LoveLyndir
url = git://github.com/Lyndir/love-lyndir.client.git

1
External/LoveLyndir vendored

Submodule External/LoveLyndir deleted from ceed9e2000

2
External/Pearl vendored

View File

@@ -1,223 +0,0 @@
## Introduction
The TestFlight SDK allows you to track how beta testers are testing your application. Out of the box we track simple usage information, such as which tester is using your application, their device model/OS, how long they used the application, and automatic recording of any crashes they encounter.
The SDK can track more information if you pass it to TestFlight. The Checkpoint API is used to help you track exactly how your testers are using your application. Curious about which users passed level 5 in your game, or posted their high score to Twitter, or found that obscure feature? See "Checkpoint API" down below to see how.
The SDK also offers a remote logging solution. Find out more about our logging system in the "Remote Logging" section.
## Requirements
The TestFlight SDK requires iOS 4.3 or above, the Apple LLVM compiler, and the libz library to run.
## Integration
1. Add the files to your project: File -> Add Files to " "
1. Find and select the folder that contains the SDK
2. Make sure that "Copy items into destination folder (if needed)" is checked
3. Set Folders to "Create groups for any added folders"
4. Select all targets that you want to add the SDK to
2. Verify that libTestFlight.a has been added to the Link Binary With Libraries Build Phase for the targets you want to use the SDK with
1. Select your Project in the Project Navigator
2. Select the target you want to enable the SDK for
3. Select the Build Phases tab
4. Open the Link Binary With Libraries Phase
5. If libTestFlight.a is not listed, drag and drop the library from your Project Navigator to the Link Binary With Libraries area
6. Repeat Steps 2 - 5 until all targets you want to use the SDK with have the SDK linked
3. Add libz to your Link Binary With Libraries Build Phase
1. Select your Project in the Project Navigator
2. Select the target you want to enable the SDK for
3. Select the Build Phases tab
4. Open the Link Binary With Libraries Phase
5. Click the + to add a new library
6. Find libz.dylib in the list and add it
7. Repeat Steps 2 - 6 until all targets you want to use the SDK with have libz.dylib
4. Get your App Token
1. If this is a new application, and you have not uploaded it to TestFlight before, first register it here: [https://testflightapp.com/dashboard/applications/create/](https://testflightapp.com/dashboard/applications/create/).
Otherwise, if you have previously uploaded your app to TestFlight, go to your list of applications ([http://testflightapp.com/dashboard/applications/](http://testflightapp.com/dashboard/applications/)) and click on the application you are using from the list.
2. Click on the "App Token" tab on the left. The App Token for that application will be there.
5. In your Application Delegate:
1. Import TestFlight: `#import "TestFlight.h"`
2. Launch TestFlight with your App Token
In your `-application:didFinishLaunchingWithOptions:` method, call `+[TestFlight takeOff:]` with your App Token.
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// start of your application:didFinishLaunchingWithOptions
[TestFlight takeOff:@"Insert your Application Token here"];
// The rest of your application:didFinishLaunchingWithOptions method
// ...
}
3. To report crashes to you we install our own uncaught exception handler. If you are not currently using an exception handler of your own then all you need to do is go to the next step. If you currently use an Exception Handler, or you use another framework that does please go to the section on advanced exception handling.
## Uploading your build
After you have integrated the SDK into your application you need to upload your build to TestFlight. You can upload your build on our [website](https://testflightapp.com/dashboard/builds/add/), using our [desktop app](https://testflightapp.com/desktop/), or by using our [upload API](https://testflightapp.com/api/doc/).
## Basic Features
### Session Information
View information about how often users use your app, how long they use it for, and when they use it. You can see what type of device the user is using, which OS, which language, etc.
Sessions automatically start at when the app becomes active and end when the app resigns active. Sessions that start shortly after an end continue the session instead of starting a new one.
NB: Sessions do not start when `takeOff:` is called, `takeOff:` registers callbacks to start sessions when the app is active.
For **beta** users, you can see who the users are if they have a TestFlight account and their device is registered with TestFlight.
### Crash Reports
The TestFlight SDK automatically reports all crashes (beta and prod) to TestFlight's website where you can view them. Crash reports are sent **at** crash time. TestFlight will also automatically symbolicate all crashes (if you have uploaded your dSYM). For **beta** apps, on the site, you can see which checkpoints the user passed before the crash and see remote logs that were sent before the crash.
### Beta In App Updates
If a user is using a **beta** version of your app and that user has permission to install it; an in app popup will ask them if they would like to install the update. If they tap "Install", the new version is installed from inside the app.
NB: For this to work, you must increment your build version before uploading. Otherwise the new and old builds will have the same version number and we won't know if the user needs to update or is already using the new version.
To turn this off set this option before calling `takeOff:`
[TestFlight setOptions:@{ TFOptionDisableInAppUpdates : @YES }];
## Additional Features
### Checkpoints
When a tester does something you care about in your app, you can pass a checkpoint. For example completing a level, adding a todo item, etc. The checkpoint progress is used to provide insight into how your testers are testing your apps. The passed checkpoints are also attached to crashes, which can help when creating steps to replicate. Checkpoints are visible for all beta builds.
[TestFlight passCheckpoint:@"CHECKPOINT_NAME"];
Use `passCheckpoint:` to track when a user performs certain tasks in your application. This can be useful for making sure testers are hitting all parts of your application, as well as tracking which testers are being thorough.
Checkpoints are meant to tell you if a user visited a place in your app or completed a task. They should not be used for debugging purposes. Instead, use Remote Logging for debugging information (more information below).
NB: Checkpoints are only recorded during BETA sessions.
### Custom Environment Information
In **beta** builds, if you want to see some extra information about your user, you can add some custom environment information. You must add this information before the session starts (a session starts at `takeOff:`) to see it on TestFlight's website. NB: You can only see this information for **beta** users.
[TestFlight addCustomEnvironmentInformation:@"info" forKey:@"key"];
You may call this method as many times as you would like to add more information.
### User Feedback
In **beta** builds, if you collect feedback from your users, you may pass it back to TestFlight which will associate it with the user's current session.
[TestFlight submitFeedback:feedback];
Once users have submitted feedback from inside of the application you can view it in the feedback area of your build page.
### Remote Logging
Remote Logging allows you to see the logs your app prints out remotely, on TestFlight's website. You can see logs for **beta sessions**.
To use it, simply replace all of your `NSLog` calls with `TFLog` calls. An easy way to do this without rewriting all your `NSLog` calls is to add the following macro to your `.pch` file.
#import "TestFlight.h"
#define NSLog TFLog
Not only will `TFLog` log remotely to TestFlight, it will also log to the console (viewable in a device's logs) and STDERR (shown while debugging) just like NSLog does, providing a complete replacement.
For even better information in your remote logs, such as file name and line number, you can use this macro instead:
#define NSLog(__FORMAT__, ...) TFLog((@"%s [Line %d] " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
Which will produce output that looks like
-[MyAppDelegate application:didFinishLaunchingWithOptions:] [Line 45] Launched!
NB: Logs are only recorded during sessions.
**Custom Logging**
If you have your own custom logging, call `TFLog` from your custom logging function. If you do not need `TFLog` to log to the console or STDERR because you handle those yourself, you can turn them off with these calls:
[TestFlight setOptions:@{ TFOptionLogToConsole : @NO }];
[TestFlight setOptions:@{ TFOptionLogToSTDERR : @NO }];
## Advanced Notes
### Checkpoint API
When passing a checkpoint, TestFlight logs the checkpoint synchronously (See Remote Logging for more information). If your app has very high performance needs, you can turn the logging off with the `TFOptionLogOnCheckpoint` option.
### Remote Logging
All logging is done synchronously. Every time the SDK logs, it must write data to a file. This is to ensure log integrity at crash time. Without this, we could not trust logs at crash time. If you have a high performance app, please email support@testflightapp.com for more options.
### Advanced Session Control
Continuing sessions: You can adjust the amount of time a user can leave the app for and still continue the same session when they come back by changing the `TFOptionSessionKeepAliveTimeout` option. Change it to 0 to turn the feature off.
Manual Session Control: If your app is a music player that continues to play music in the background, a navigation app that continues to function in the background, or any app where a user is considered to be "using" the app even while the app is not active you should use Manual Session Control. Please only use manual session control if you know exactly what you are doing. There are many pitfalls which can result in bad session duration and counts. See `TestFlight+ManualSessions.h` for more information and instructions.
### Advanced Exception/Signal Handling
An uncaught exception means that your application is in an unknown state and there is not much that you can do but try and exit gracefully. Our SDK does its best to get the data we collect in this situation to you while it is crashing, but it is designed in such a way that the important act of saving the data occurs in as safe way a way as possible before trying to send anything. If you do use uncaught exception or signal handlers, install your handlers before calling `takeOff:`. Our SDK will then call your handler while ours is running. For example:
/*
My Apps Custom uncaught exception catcher, we do special stuff here, and TestFlight takes care of the rest
*/
void HandleExceptions(NSException *exception) {
NSLog(@"This is where we save the application data during a exception");
// Save application data on crash
}
/*
My Apps Custom signal catcher, we do special stuff here, and TestFlight takes care of the rest
*/
void SignalHandler(int sig) {
NSLog(@"This is where we save the application data during a signal");
// Save application data on crash
}
-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// installs HandleExceptions as the Uncaught Exception Handler
NSSetUncaughtExceptionHandler(&HandleExceptions);
// create the signal action structure
struct sigaction newSignalAction;
// initialize the signal action structure
memset(&newSignalAction, 0, sizeof(newSignalAction));
// set SignalHandler as the handler in the signal action structure
newSignalAction.sa_handler = &SignalHandler;
// set SignalHandler as the handlers for SIGABRT, SIGILL and SIGBUS
sigaction(SIGABRT, &newSignalAction, NULL);
sigaction(SIGILL, &newSignalAction, NULL);
sigaction(SIGBUS, &newSignalAction, NULL);
// Call takeOff after install your own unhandled exception and signal handlers
[TestFlight takeOff:@"Insert your Application Token here"];
// continue with your application initialization
}
You do not need to add the above code if your application does not use exception handling already.

View File

@@ -1,30 +0,0 @@
//
// TestFlight+AsyncLogging.h
// libTestFlight
//
// Created by Jason Gregori on 2/12/13.
// Copyright (c) 2013 TestFlight. All rights reserved.
//
/*
When logging, it is important that logs are written synchronously. In the event of a crash, all logs that happened before the crash are gauranteed to be on disk. If they were written asynchronously and a crash occurs, you might lose some very valuable logs that might have helped fixed the crash.
However, because TFLog waits until writing to disk is complete, it takes a while. If you have a very high preformance app that can't afford to wait for logs, these functions are for you.
USE THESE, BUT KNOW YOU RISK LOSING SOME LOGS AT CRASH TIME
*/
#import "TestFlight.h"
#if __cplusplus
extern "C" {
#endif
void TFLog_async(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
void TFLogv_async(NSString *format, va_list arg_list);
#if __cplusplus
}
#endif

View File

@@ -1,58 +0,0 @@
//
// TestFlight+ManualSessions.h
// libTestFlight
//
// Created by Jason Gregori on 5/16/13.
// Copyright (c) 2013 TestFlight. All rights reserved.
//
/*
YOU ARE STRONGLY ADVISED NOT TO USE THESE METHODS unless you know exactly what you are doing. By using these you take on the responsibility of ensuring your session data is reported accurately.
The way TestFlight normally does sessions is to automatically start them at app launch, app did become active, and app will enter foreground and end them at app will resign active, app did enter background, or app will terminate.
If your app is a music player that continues to play music in the background, a navigation app that continues to function in the background, or any app where a user is considered to be "using" the app even while the app is not active, this file is for you.
Usage
-----
1. Add this file to your project.
2. Set the manual sessions option to true **before** calling `takeOff:`
[TestFlight setOptions:@{ TFOptionManualSessions : @YES }];
3. Use the manually start/end session methods to control you sessions.
Pitfalls
--------
When using manual sessions in the background, you must always be aware of the fact that iOS may suspend your app at any time without any warning. You must end your session before that happens. If you do not, the session will continue and include all the time the app was suspended in it's duration if the app is brought back from suspension. This will lead to very inaccurate session lengths and counts.
On app termination: For the most accurate sessions, try to end your session if you know the app is about to terminate. If you do not, the session will still be ended on the next launch, however, it's end time will not be exact. In that case, the end time will be within 30 seconds of the correct time (session information is saved every 30 seconds and when a checkpoint is sent).
Sessions do not continue across termination if you do not end a session before termination.
On crashes: Do not worry about ending sessions in the event of a crash. Even manual sessions are automatically ended in the event of a crash.
Continuing sessions: If a session is started without 30 seconds of the last session ending (and their was no termination between the sessions), the last session will continue instead of a new session starting. This is the case in manual and automatic sessions. You may change the timeout or turn this feature off using the `TFOptionSessionKeepAliveTimeout` option.
*/
#import "TestFlight.h"
extern NSString *const TFOptionManualSessions; // Defaults to @NO. Set to @YES before calling `takeOff:` in order to use manual session methods.
@interface TestFlight (ManualSessions)
// these methods are thread safe
+ (void)manuallyStartSession;
+ (void)manuallyEndSession;
@end

View File

@@ -1,104 +0,0 @@
//
// TestFlight.h
// libTestFlight
//
// Created by Jonathan Janzen on 06/11/11.
// Copyright 2011 TestFlight. All rights reserved.
#import <Foundation/Foundation.h>
#define TESTFLIGHT_SDK_VERSION @"3.0.0"
#undef TFLog
#if __cplusplus
extern "C" {
#endif
/*
* Remote Logging
* BETA only
* Note: All Logging is synchronous, see the README for more information.
*/
void TFLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
void TFLogv(NSString *format, va_list arg_list);
void TFLogPreFormatted(NSString *message);
#if __cplusplus
}
#endif
/**
* TestFlight object
* All methods are class level
*/
@interface TestFlight : NSObject
/**
* Add custom environment information
* BETA only
* If you want to track custom information such as a user name from your application you can add it here.
* NB: This information must be added before the session starts, it is recorded only on session start.
*
* @param information A string containing the environment you are storing
* @param key The key to store the information with
*/
+ (void)addCustomEnvironmentInformation:(NSString *)information forKey:(NSString*)key;
/**
* Sets up TestFlight's infrastructure.
*
* - Saves App Token
* - Starts automatic session management
* - Installs Crash Handlers
* - Kicks off sending of old session data
*
* @param applicationToken Will be the application token for the current application.
* The token for this application can be retrieved by going to https://testflightapp.com/dashboard/applications/
* selecting this application from the list then selecting SDK.
*/
+ (void)takeOff:(NSString *)applicationToken;
/**
* Sets custom options
*
* @param options NSDictionary containing the options you want to set. Available options are described below at "TestFlight Option Keys"
*
*/
+ (void)setOptions:(NSDictionary*)options;
/**
* Track when a user has passed a checkpoint after the flight has taken off. Eg. passed level 1, posted high score.
* BETA only
* Checkpoints are sent in the background.
* Note: The checkpoint is logged synchronously (See TFLog and TFOptionLogOnCheckpoint for more information).
*
* @param checkpointName The name of the checkpoint, this should be a static string
*/
+ (void)passCheckpoint:(NSString *)checkpointName;
/**
* Submits custom feedback to the site. Sends the data in feedback to the site. This is to be used as the method to submit
* feedback from custom feedback forms.
* BETA only
*
* @param feedback Your users feedback, method does nothing if feedback is nil
*/
+ (void)submitFeedback:(NSString*)feedback;
@end
/**
* TestFlight Option Keys
*
* Pass these as keys to the dictionary you pass to +`[TestFlight setOptions:]`.
* The values should be NSNumber BOOLs (`[NSNumber numberWithBool:YES]` or `@YES`)
*/
extern NSString *const TFOptionDisableInAppUpdates; // Defaults to @NO. Setting to @YES, disables the in app update screen shown in BETA apps when there is a new version available on TestFlight.
extern NSString *const TFOptionFlushSecondsInterval; // Defaults to @60. Set to a number. @0 turns off the flush timer. 30 seconds is the minimum flush interval.
extern NSString *const TFOptionLogOnCheckpoint; // Defaults to @YES. Because logging is synchronous, if you have a high preformance app, you might want to turn this off.
extern NSString *const TFOptionLogToConsole; // Defaults to @YES. Prints remote logs to Apple System Log.
extern NSString *const TFOptionLogToSTDERR; // Defaults to @YES. Sends remote logs to STDERR when debugger is attached.
extern NSString *const TFOptionReinstallCrashHandlers; // If set to @YES: Reinstalls crash handlers, to be used if a third party library installs crash handlers overtop of the TestFlight Crash Handlers.
extern NSString *const TFOptionReportCrashes; // Defaults to @YES. If set to @NO, crash handlers are never installed. Must be set **before** calling `takeOff:`.
extern NSString *const TFOptionSendLogOnlyOnCrash; // Defaults to @NO. Setting to @YES stops remote logs from being sent when sessions end. They would only be sent in the event of a crash.
extern NSString *const TFOptionSessionKeepAliveTimeout; // Defaults to @30. This is the amount of time a user can leave the app for and still continue the same session when they come back. If they are away from the app for longer, a new session is created when they come back. Must be a number. Change to @0 to turn off.

Binary file not shown.

View File

@@ -1,318 +0,0 @@
## 3.0.0 - February 18, 2014
- Remove checkpoints, feedback, and logs from production apps.
## 2.2.2 - February 5, 2014
- Remove `+ (void)setDeviceIdentifier:(NSString *)deviceIdentifer`, it is no longer used
- On start up, if unsent events are found only attempt to send some of them (this is in case a device doesn't have internet for a while and unsent events build up)
- Fix crash if you try to run `TFLog(nil)` (thanks Florian!)
## 2.2.1 - January 16, 2014
- Consolidate both SDK versions into one which removes all access to `ASIdentifierManager`
## 2.2 - December 17, 2013
- Restore In App Updates
- Automatic identification of beta testers
## 2.1.3 - November 25, 2013
- Fix bug in 2.1.2-noadid which caused adid to be collected
## 2.1.2 - November 19, 2013
- Fix for bug that caused events to not get sent properly when using the `TFOptionSessionKeepAliveTimeout` option
- Fix for bug that caused logs that were sent immediately after start session to sometimes not be sent to server
## 2.1.1 - October 2, 2013
- Create sdk version that removes all access to `ASIdentifierManager`
- Add UIDevice's `identifierForVendor`
## 2.1 - September 30, 2013
- Full support for the iPhone 5s ARM64 processor while still supporting down to iOS 4.3
## 2.0.2 - August 30, 2013
- Fixed a bug where the sdk would cause an app's CPU usage to rise significantly if the device had no internet connection when the app started
## 2.0.1 - August 22, 2013
- Fixed rare `8badf00d` crash in TFNetworkManager that happened when the app was in the background
## 2.0 - August 12, 2013
Improvements
- ARC
- All public TestFlight methods may be called from any thread or dispatch_queue
- All public TestFlight methods (except for `TFLog` and `takeOff:`) are asynchronous, so there is never a wait on them
- TestFlight never uses more than 1 network connection at a time
- All network traffic is grouped together, sent at once, and transferred in MessagePack. This results in using less bandwidth and less network calls.
- All network traffic if server is not reachable
- Size of SDK reduced by 70%
- New In App Update UI in an alert with landscape support. Should work for all different types of apps.
- Manual Sessions: You can manually control session start and end. See `TestFlight+ManualSessions.h` for more information
- Combining of back to back sessions. If a session starts less than 30 seconds from the last session which ended, the previous session is continued. You may change the time limit (or turn this off) using the `TFOptionSessionKeepAliveTimeout` option key.
- No longer automatically starts a session on `+takeOff:` in order to support new background modes that might launch an app in the background.
- `TFOptionReportCrashes` option to not install crash handlers
- Remove all calls to `dispatch_get_current_queue`, it is deprecated
Changes
- Removed all access to mac address
- Added AdSupport.framework requirement (as a replacement for mac address to get accurate user counts)
- Add format attribute to TFLog to show warnings for wrong format specifiers or not using a format string
- Removed Questions
- Removed Feedback View (along with backtrace option)
Bug Fixes
- Fixed addrinfo memory leak
- Fixed possible `-[TFAirTrafficController getNumberOrNilFrom:withKey:]` crash when bad data is received.
- CoreTelephony crash work around: this is a workaround of a iOS bug that causes deallocated instances of `CTTelephonyNetworkInfo` to receive notifications which causes crashes. Core Telephony is used to retrieve the device's mobile carrier.
- Fix bug with crash reporting in iOS 7
## 1.2.4 - February 19, 2013
- Fixed bug that caused crash reports to sometimes not send immediately (they would be resent later)
## 1.2.3 - January 8, 2013
- Fixed typos in readme
- Fixed bug where logs not sent on crash
- Fixed bug where empty crash files were created (but not sent)
- Cache path to TF's directory so it does not need to be regenerated every time
- Use consts for `setOptions:`
- Updated `setDeviceIdentifier:` comments to make them clearer
- Remove potentially conflicting function name `UIColorFromRGB`
- Fixed crash on bad in app update data
## 1.2.2 - December 26, 2012
- Fix typo in app token error message
## 1.2.1 - December 26, 2012
- The max number of concurrent network connections has been reduced from 4 to 2.
##1.2 - November 12, 2012
* Removed Team Token support. As of version 1.2 takeOff must be called with the Application Token, https://testflightapp.com/dashboard/applications/, choose your application, select SDK, get the Token for this Application.
##1.2 BETA 3 - October 11, 2012
* Added application token support. Application Tokens are currently optional if you do not have one you do not need one
##1.2 BETA 2 - October 9, 2012
* Resolved an instance of close_file being called on a bad file descriptor
##1.2 BETA 1 - October 1, 2012
* Removed support for armv6
* Exception handler now returns instead of raising a SIGTRAP
##1.1 - September 13, 2012
* armv7s and iOS 6 support
* Updated for general release
##1.1 BETA 3 - September 12, 2012
* armv7s slice added to library
* fixed typo for in application updates, inAppUdates changed to inAppUpdates
##1.1 BETA 2 - September 6, 2012
* Re-enabled armv6 support
* Added option to disable in application updates
##1.1 BETA 1 - July 13, 2012
* Added TFLogv to allow for log customizations. Check the README or online docs for more information.
* Added option attachBacktraceToFeedback, which attaches a backtrace to feedback sent from the SDK. For users who use feedback in more than one location in the application.
* Resolved issue where other exception handlers would not be called during an exception.
* SDK now sends the device language for a session.
* Documentation fixes.
* Stability fixes.
###1.0 - March 29, 2012
* Resolved occurrences of exceptions with the message "No background task exists with identifier 0"
###1.0 BETA 1 - March 23, 2012
* Privacy Updates
* UDID is no longer collected by the SDK. During testing please use `[TestFlight setDeviceIdentifier:[[UIDevice currentDevice] uniqueIdentifier]];` to send the UDID so you can identify your testers. For release do not set `+setDeviceIdentifier`. See Beta Testing and Release Differentiation in the README or online at [https://testflightapp.com/sdk/doc/1.0beta1/](http://testflightapp.com/sdk/doc/1.0beta1/)
###0.8.3 - February 14, 2012
* Rolled previous beta code into release builds
* No longer allow in application updates to occur in applications that were obtained from the app store.
**Tested compiled library with:**
* Xcode 4.3
* Xcode 4.2
* Xcode 4.1
* Xcode 3.2.6
###0.8.3 BETA 5 - February 10, 2012
* Changed logging from asynchronous to synchronous.
* Resolved crash when looking for a log path failed.
* Added submitFeedback to the TestFlight class to allow for custom feedback forms.
###0.8.3 BETA 4 - January 20, 2012
* Resolved an issue that occured when an application was upgraded from 0.8.3 BETA 1 to 0.8.3 BETA 3+ with unsent data from 0.8.3 BETA 1
###0.8.3 BETA 3 - January 19, 2012
* On crash log files over 64k will not be sent until next launch.
**Known Issues:**
* Logging massive amounts of data at the end of a session may prevent the application from launching in time on next launch
###0.8.3 BETA 2 - January 13, 2012
* libz.dylib is now required to be added to your "Link Binary with Libraries" build phase
* Log file compression, The compression is done on an as needed basis rather than before sending
* Changed all outgoing data from JSON to MessagePack
* Added option `logToSTDERR` to disable the `STDERR` logger
###0.8.3 BETA 1 - December 29, 2011
* In rare occurrences old session data that had not been sent to our server may have been discarded or attached to the wrong build. It is now no longer discarded
* Made sending of Session End events more robust
* Network queuing system does better bursting of unsent data
* Log files that are larger than 64K are now sent sometime after the next launch
* Log files that are larger than 16MB are no longer supported and will be replaced with a message indicating the log file was too large
* Fixed crashes while resuming from background
###0.8.2 - December 20, 2011
* Promoted 0.8.2 BETA 4 to stable
**Known Issues:**
* Under some circumstances Session End events may not be sent until the next launch.
* With large log files Session End events may take a long time to show up.
**Tested compiled library with:**
* Xcode 4.3
* Xcode 4.2
* Xcode 4.1
* Xcode 3.2.6
###0.8.2 BETA 4 - December 12, 2011
* Prevented "The string argument is NULL" from occuring during finishedHandshake in rare cases
* Resolved issue where data recorded while offline may not be sent
###0.8.2 BETA 3 - December 8, 2011
* Added auto-release pools to background setup and tear down
###0.8.2 BETA 2 - December 5, 2011
* Fixed the "pointer being freed was not allocated" bug
###0.8.1 - November 18, 2011
* Implemented TFLog logging system, see README for more information
* Fixed an issue where Session End events may not be sent until next launch
* Fixed an issue where duplicate events could be sent
* Fixed an issue with Session End events not being sent from some iPod touch models
**Tested compiled library with:**
* Xcode 4.2
* Xcode 4.1
* Xcode 3.2.6
###0.8 - November 8, 2011
* Added `SIGTRAP` as a signal type that we catch
* Removed all Objective-c from crash reporting
* Removed the use of non signal safe functions from signal handling
* Created a signal safe way to get symbols from a stack trace
* Changed the keyboardType for Long Answer Questions and Feedback to allow for international character input
* Changed `TESTFLIGHT_SDK_VERSION` string to be an `NSString`
* Changed cache folder from Library/Caches/TestFlight to Library/Caches/com.testflight.testflightsdk
* Fixed issue with saving data when device is offline
* Fixed compability issues with iOS 3
* Added calling into the rootViewController shouldAutorotateToInterfaceOrientation if a rootViewController is set
* Made the comments in TestFlight.h compatible with Appledoc
Tested compiled library with:
* Xcode 4.2
* Xcode 4.1
* Xcode 3.2
###0.7.2 - September 29, 2011
* Changed `TESTFLIGHT_SDK_VERSION` string to be an `NSString`
* Fixed an issue where exiting an application while the SDK is active caused modal views to be dismissed
###0.7.1 - September 22, 2011
* Internal release
* Refactoring
###0.7 - September 21, 2011
* Moved TestFlight images and data to the Library/Caches folder
* Resolved an issue where sometimes the rootViewController could not be found and feedback, questions and upgrade views would not be displayed
* In application upgrade changed to allow skipping until the next version is installed and allows upgrades to be forced
* Fixed a memory leak when launching questions
###0.6 - September 2, 2011
* Renamed base64_encode to testflight_base64_encode to remove a conflict with other third party libraries
* Added ability to reinstall crash handlers when they are overwritten using the setOptions API
* Fixed an issue where crash reports might not get sent under certain circumstances
* Fixed a deadlock when the application is put in the background and then resumed before all information can be sent
* Fixed an issue when attempting to un-install all signal handlers during a signal
* Added support for landscape mode on the iPad to the Questions and Feedback views
* Crash reporting now works in versions of Xcode earlier than 4.2
* Fixed a memory leak during handshake
###0.5 - August 19, 2011
* Feedback that is not attached to a checkpoint [TestFlight openFeedbackView]
* Usability changes to question views
* Removed pause and resume sessions, replaced with sessions being stopped and started
* Added text auto correction to the Long Answer question type
* Crash reports now send on crash instead of next launch
###0.4 - August 15, 2011
* In Application Feedback with Questions
* In application updates
* Custom Environment Information added
* Networking stack reimplementation
* Exception handling fixes
###0.3 - June 15, 2011
* Removed all mention of JSONKit from the README
* Added support for using both the Bundle Version and the Bundle Short Version string
###0.2 - June 14, 2011
* Removed all categories this allows users to use the SDK without having to set -ObjC and -load_all
* Prefixed JSONKit for use in TestFlight to remove reported issues where some users were already using JSONKit
* Added support for armv6 again
###0.1 - June 11, 2011
* Initial Version

View File

@@ -0,0 +1,6 @@
framework module Crashlytics {
umbrella header "Crashlytics.h"
export *
module * { export * }
}

View File

@@ -15,13 +15,13 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.2.0</string>
<string>2.2.4</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
</array>
<key>CFBundleVersion</key>
<string>33</string>
<string>38</string>
<key>DTPlatformName</key>
<string>iphoneos</string>
<key>MinimumOSVersion</key>

Binary file not shown.

Binary file not shown.

View File

@@ -10,57 +10,69 @@
<string>MasterPassword</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>1712FC0BC3C9AABD8B7B5376E310E93FBDB3BCFA</key>
<string>git://github.com/lhunath/InAppSettingsKit.git</string>
<key>1AA8C0BE-EEC3-4FBC-A801-8939A1AC093A</key>
<string>git://github.com/Lyndir/love-lyndir.client.git</string>
<key>42C94803-87A2-403E-896C-D9AC3A807E1B</key>
<string>git://github.com/lhunath/UbiquityStoreManager.git</string>
<key>6A449EC2-A2A3-4635-9C5F-A811E011EAC3</key>
<string>ssh://github.com/Lyndir/MasterPassword.git</string>
<key>ADA0D7F9-4871-4128-8FEE-FD1021EEF3AC</key>
<string>ssh://github.com/Lyndir/Pearl.git</string>
<key>AE3786C7-912B-4651-A73F-2E1DACBFB604</key>
<key>2A70319CE0F91B35406CA7D970AE7CB4957B0A75</key>
<string>github.com:Lyndir/Lyndir.git</string>
<key>2FE140B36B7D26140DC8D5E5C639DC5900EFCF35</key>
<string>git://github.com/lhunath/uicolor-utilities.git</string>
<key>B0F634DD-AEE1-4F0D-AE35-4FAF51AD1B5A</key>
<key>3E67FB08419C920516AAC3B00DAAF23073B8CF77</key>
<string>git://github.com/lhunath/RHStatusItemView.git</string>
<key>CDDE92CF-0136-4DE0-8318-80EDB5C8CAF9</key>
<string>git://github.com/lhunath/InAppSettingsKit.git</string>
<key>E4C8E206-229C-4DA8-A130-0C544DEC7E07</key>
<key>4DDCFFD91B41F00326AD14553BD66CFD366ABD91</key>
<string>ssh://github.com/Lyndir/Pearl.git</string>
<key>8A15A8EA0B3D0B497C4883425BC74DF995224BB3</key>
<string>git://github.com/jonmarimba/jrswizzle.git</string>
<key>E47DEC29CB0D0FDE3560EF46E1808FA1C723D657</key>
<string>git://github.com/lhunath/UbiquityStoreManager.git</string>
<key>F788B28042EDBEF29EFE34687DA79A778C2CC260</key>
<string>ssh://github.com/Lyndir/MasterPassword.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>MasterPassword.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>1712FC0BC3C9AABD8B7B5376E310E93FBDB3BCFA</key>
<string>../External/InAppSettingsKit</string>
<key>1AA8C0BE-EEC3-4FBC-A801-8939A1AC093A</key>
<string>../External/LoveLyndir</string>
<key>42C94803-87A2-403E-896C-D9AC3A807E1B</key>
<string>../External/UbiquityStoreManager</string>
<key>6A449EC2-A2A3-4635-9C5F-A811E011EAC3</key>
<string>..</string>
<key>ADA0D7F9-4871-4128-8FEE-FD1021EEF3AC</key>
<string>../External/Pearl</string>
<key>AE3786C7-912B-4651-A73F-2E1DACBFB604</key>
<key>2A70319CE0F91B35406CA7D970AE7CB4957B0A75</key>
<string>../..</string>
<key>2FE140B36B7D26140DC8D5E5C639DC5900EFCF35</key>
<string>../External/Pearl/External/uicolor-utilities</string>
<key>B0F634DD-AEE1-4F0D-AE35-4FAF51AD1B5A</key>
<key>3E67FB08419C920516AAC3B00DAAF23073B8CF77</key>
<string>../External/RHStatusItemView</string>
<key>CDDE92CF-0136-4DE0-8318-80EDB5C8CAF9</key>
<string>../External/InAppSettingsKit</string>
<key>E4C8E206-229C-4DA8-A130-0C544DEC7E07</key>
<key>4DDCFFD91B41F00326AD14553BD66CFD366ABD91</key>
<string>../External/Pearl</string>
<key>8A15A8EA0B3D0B497C4883425BC74DF995224BB3</key>
<string>../External/Pearl/External/jrswizzle</string>
<key>E47DEC29CB0D0FDE3560EF46E1808FA1C723D657</key>
<string>../External/UbiquityStoreManager</string>
<key>F788B28042EDBEF29EFE34687DA79A778C2CC260</key>
<string>..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>ssh://github.com/Lyndir/MasterPassword.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>110</integer>
<integer>111</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>6A449EC2-A2A3-4635-9C5F-A811E011EAC3</string>
<string>F788B28042EDBEF29EFE34687DA79A778C2CC260</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>CDDE92CF-0136-4DE0-8318-80EDB5C8CAF9</string>
<string>2A70319CE0F91B35406CA7D970AE7CB4957B0A75</string>
<key>IDESourceControlWCCName</key>
<string></string>
</dict>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>1712FC0BC3C9AABD8B7B5376E310E93FBDB3BCFA</string>
<key>IDESourceControlWCCName</key>
<string>InAppSettingsKit</string>
</dict>
@@ -68,7 +80,7 @@
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>E4C8E206-229C-4DA8-A130-0C544DEC7E07</string>
<string>8A15A8EA0B3D0B497C4883425BC74DF995224BB3</string>
<key>IDESourceControlWCCName</key>
<string>jrswizzle</string>
</dict>
@@ -84,7 +96,7 @@
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>6A449EC2-A2A3-4635-9C5F-A811E011EAC3</string>
<string>F788B28042EDBEF29EFE34687DA79A778C2CC260</string>
<key>IDESourceControlWCCName</key>
<string>MasterPassword</string>
</dict>
@@ -92,7 +104,7 @@
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>ADA0D7F9-4871-4128-8FEE-FD1021EEF3AC</string>
<string>4DDCFFD91B41F00326AD14553BD66CFD366ABD91</string>
<key>IDESourceControlWCCName</key>
<string>Pearl</string>
</dict>
@@ -100,7 +112,7 @@
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>B0F634DD-AEE1-4F0D-AE35-4FAF51AD1B5A</string>
<string>3E67FB08419C920516AAC3B00DAAF23073B8CF77</string>
<key>IDESourceControlWCCName</key>
<string>RHStatusItemView</string>
</dict>
@@ -108,7 +120,7 @@
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>42C94803-87A2-403E-896C-D9AC3A807E1B</string>
<string>E47DEC29CB0D0FDE3560EF46E1808FA1C723D657</string>
<key>IDESourceControlWCCName</key>
<string>UbiquityStoreManager</string>
</dict>
@@ -116,7 +128,7 @@
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>AE3786C7-912B-4651-A73F-2E1DACBFB604</string>
<string>2FE140B36B7D26140DC8D5E5C639DC5900EFCF35</string>
<key>IDESourceControlWCCName</key>
<string>uicolor-utilities</string>
</dict>

1920
MasterPassword/C/bashlib Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +1,9 @@
#!/usr/bin/env bash
gcc -I"lib/scrypt/lib" -I"lib/scrypt/libcperciva" -I"lib/proplib/include" -l "crypto_aesctr.o" -l "sha256.o" -l "crypto_scrypt-nosse.o" -l "memlimit.o" -l "scryptenc_cpuperf.o" -l"scryptenc.o" -l"crypto" -l"prop" -L"lib/scrypt" -L"lib/proplib/src/.libs" mpw.c -o mpw
# Run with -DDEBUG to enable trace-level output.
[[ -e lib/scrypt/scryptenc.o ]] || { echo >&2 "Missing scrypt. First get and build the scrypt source in lib/scrypt from <$(<lib/scrypt/.source)>.\n"; exit 1; }
deps=( -I"lib/scrypt/lib" -I"lib/scrypt/libcperciva" -l "crypto_aesctr.o" -l "sha256.o" -l "crypto_scrypt-nosse.o" -l "memlimit.o" -l "scryptenc_cpuperf.o" -l"scryptenc.o" -l"crypto" -L"." -L"lib/scrypt" )
gcc "${deps[@]}" -Qunused-arguments -c types.c -o types.o "$@"
gcc "${deps[@]}" -Qunused-arguments -l"types.o" mpw.c -o mpw "$@"

View File

@@ -1 +0,0 @@
../Resources/Data/ciphers.plist

View File

@@ -1,15 +1,53 @@
#!/usr/bin/env bash
BINDIR=${BINDIR:+${PREFIX:+$PREFIX/bin}}
[[ $BINDIR ]] && mkdir -p "$BINDIR"
if [[ ! -w $BINDIR ]]; then
for dir in /usr/local/bin ~/.bin ~/bin /usr/bin; do
[[ -w $dir ]] && BINDIR=$dir && break
done
if [[ ! -w $BINDIR ]]; then
echo >&2 "Could not find directory to install to."
echo >&2 "You can specify a prefix to install to, eg. PREFIX=/usr/local ./install"
echo >&2 "You can specify a bin directory to install to, eg. BINDIR=~/bin ./install"
echo >&2 "Make sure you have write permission to the bin directory."
fi
#
# Install the Master Password CLI tool.
set -e
cd "${BASH_SOURCE%/*}"
source bashlib
inf "This will install the mpw tool."
# Try to guess then ask for the bin dir to install to.
IFS=: read -a paths <<< "$PATH"
if inArray ~/bin "${paths[@]}"; then
bindir=~/bin
elif inArray ~/.bin "${paths[@]}"; then
bindir=~/.bin
elif inArray /usr/local/bin "${paths[@]}"; then
bindir=/usr/local/bin
else
bindir=~/bin
fi
install -v -s mpw "$BINDIR"
bindir=$(ask -d "$bindir" "What bin directory should I install to?")
[[ -d "$bindir" ]] || mkdir "$bindir" || ftl 'Cannot create missing bin directory: %s' "$bindir" || exit
[[ -w "$bindir" ]] || ftl 'Cannot write to bin directory: %s' "$bindir" || exit
# Install Master Password.
install mpw "$bindir"
[[ ! -e "$bindir/bashlib" ]] && install bashlib "$bindir" ||:
# Convenience bash function.
inf "Installation successful!"
echo
inf "To improve usability, you can install an mpw function in your bash shell."
inf "This function adds the following features:"
inf " - Automatically remember your user name in the shell if not set."
inf " - Automatically put the password in the clipboard (some platforms)."
echo
inf "To do this you need the following function in ~/.bashrc:\n%s" "$(<mpw.bashrc)"
echo
inf "We can do this for you automatically now."
if ask -c Y!n "Append the mpw function to your .bashrc?"; then
cat mpw.bashrc >> ~/.bashrc
inf "Done! Don't forget to run '%s' to apply the changes!" "source ~/.bashrc"
fi
echo
inf "You can also save your user name in ~/.bashrc. Leave blank to skip this step."
if MP_USERNAME=$(ask "Your full name:") && [[ $MP_USERNAME ]] ; then
printf 'export MP_USERNAME=%q\n' "$MP_USERNAME" >> ~/.bashrc
fi
echo
inf "To begin using Master Password, type: mpw [site name]"

View File

@@ -1 +0,0 @@
https://code.google.com/p/portableproplib/

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,24 @@
## Added by Master Password
source bashlib
mpw() {
_copy() {
if hash pbcopy 2>/dev/null; then
pbcopy
elif hash xclip 2>/dev/null; then
xclip
else
cat; echo 2>/dev/null
return
fi
echo >&2 "Copied!"
}
# Empty the clipboard
:| _copy 2>/dev/null
# Ask for the user's name and password if not yet known.
MP_USERNAME=${MP_USERNAME:-$(ask 'Your Full Name:')}
# Start Master Password and copy the output.
printf %s "$(MP_USERNAME=$MP_USERNAME command mpw "$@")" | _copy
}

View File

@@ -1,3 +1,4 @@
#define _WITH_GETLINE
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
@@ -13,14 +14,14 @@
#include <unistd.h>
#include <math.h>
#include <pwd.h>
#include <uuid/uuid.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <alg/sha256.h>
#include <crypto/crypto_scrypt.h>
#include <prop/proplib.h>
#include "types.h"
#define MP_N 32768
#define MP_r 8
@@ -32,6 +33,28 @@
#define MP_env_sitetype "MP_SITETYPE"
#define MP_env_sitecounter "MP_SITECOUNTER"
void usage() {
fprintf(stderr, "Usage: mpw [-u name] [-t type] [-c counter] site\n\n");
fprintf(stderr, " -u name Specify the full name of the user.\n"
" Defaults to %s in env.\n\n", MP_env_username);
fprintf(stderr, " -t type Specify the password's template.\n"
" Defaults to %s in env or 'long' for password, 'name' for login.\n"
" x, max, maximum | 20 characters, contains symbols.\n"
" l, long | Copy-friendly, 14 characters, contains symbols.\n"
" m, med, medium | Copy-friendly, 8 characters, contains symbols.\n"
" b, basic | 8 characters, no symbols.\n"
" s, short | Copy-friendly, 4 characters, no symbols.\n"
" p, pin | 4 numbers.\n"
" n, name | 9 letter name.\n\n", MP_env_sitetype);
fprintf(stderr, " -c counter The value of the counter.\n"
" Defaults to %s in env or '1'.\n\n", MP_env_sitecounter);
fprintf(stderr, " -v variant The kind of content to generate.\n"
" Defaults to 'password'.\n"
" p, password | The password to log in with.\n"
" l, login | The username to log in as.\n\n");
exit(0);
}
char *homedir(const char *filename) {
char *homedir = NULL;
#if defined(__CYGWIN__)
@@ -59,73 +82,97 @@ char *homedir(const char *filename) {
int main(int argc, char *const argv[]) {
if (argc < 2)
usage();
// Read the environment.
const char *userName = getenv( MP_env_username );
const char *masterPassword = NULL;
const char *siteName = NULL;
MPElementType siteType = MPElementTypeGeneratedLong;
const char *siteTypeString = getenv( MP_env_sitetype );
MPElementVariant siteVariant = MPElementVariantPassword;
const char *siteVariantString = NULL;
uint32_t siteCounter = 1;
const char *siteCounterString = getenv( MP_env_sitecounter );
// Read the options.
char opt;
while ((opt = getopt(argc, argv, "u:t:c:")) != -1)
while ((opt = getopt(argc, argv, "u:t:c:v:h")) != -1)
switch (opt) {
case 'u':
userName = optarg;
break;
case 't':
siteTypeString = optarg;
break;
case 'c':
siteCounterString = optarg;
break;
case '?':
switch (optopt) {
case 'u':
fprintf (stderr, "Missing user name to option: -%c\n", optopt);
case 'h':
usage();
break;
case 't':
fprintf (stderr, "Missing type name to option: -%c\n", optopt);
case 'u':
userName = optarg;
break;
case 'c':
fprintf (stderr, "Missing counter value to option: -%c\n", optopt);
case 't':
siteTypeString = optarg;
break;
default:
fprintf (stderr, "Unknown option: -%c\n", optopt);
}
return 1;
default:
abort();
case 'v':
siteVariantString = optarg;
break;
case 'c':
siteCounterString = optarg;
break;
case '?':
switch (optopt) {
case 'u':
fprintf(stderr, "Missing user name to option: -%c\n", optopt);
break;
case 't':
fprintf(stderr, "Missing type name to option: -%c\n", optopt);
break;
case 'c':
fprintf(stderr, "Missing counter value to option: -%c\n", optopt);
break;
default:
fprintf(stderr, "Unknown option: -%c\n", optopt);
}
return 1;
default:
abort();
}
if (optind < argc)
siteName = argv[optind];
// Convert and validate input.
if (!userName) {
fprintf (stderr, "Missing user name.\n");
fprintf(stderr, "Missing user name.\n");
return 1;
}
trc("userName: %s\n", userName);
if (!siteName) {
fprintf (stderr, "Missing site name.\n");
fprintf(stderr, "Missing site name.\n");
return 1;
}
trc("siteName: %s\n", siteName);
if (siteCounterString)
siteCounter = atoi( siteCounterString );
if (siteCounter < 1) {
fprintf (stderr, "Invalid site counter: %d\n", siteCounter);
fprintf(stderr, "Invalid site counter: %d\n", siteCounter);
return 1;
}
trc("siteCounter: %d\n", siteCounter);
if (siteVariantString)
siteVariant = VariantWithName( siteVariantString );
trc("siteVariant: %d (%s)\n", siteVariant, siteVariantString);
if (siteVariant == MPElementVariantLogin)
siteType = MPElementTypeGeneratedName;
if (siteTypeString)
siteType = TypeWithName( siteTypeString );
trc("siteType: %d (%s)\n", siteType, siteTypeString);
// Read the master password.
char *mpwConfigPath = homedir(".mpw");
if (!mpwConfigPath) {
fprintf (stderr, "Couldn't resolve path for configuration file: %d\n", errno);
fprintf(stderr, "Couldn't resolve path for configuration file: %d\n", errno);
return 1;
}
trc("mpwConfigPath: %s\n", mpwConfigPath);
FILE *mpwConfig = fopen(mpwConfigPath, "r");
if (!mpwConfig) {
fprintf (stderr, "Couldn't open configuration file: %s: %d\n", mpwConfigPath, errno);
fprintf(stderr, "Couldn't open configuration file: %s: %d\n", mpwConfigPath, errno);
return 1;
}
free(mpwConfigPath);
@@ -134,81 +181,91 @@ int main(int argc, char *const argv[]) {
ssize_t linelen;
while ((linelen = getline(&line, &linecap, mpwConfig)) > 0)
if (strcmp(strsep(&line, ":"), userName) == 0) {
masterPassword = line;
masterPassword = strsep(&line, "\n");
break;
}
if (!masterPassword) {
fprintf (stderr, "Missing master password for user: %s\n", userName);
fprintf(stderr, "Missing master password for user: %s\n", userName);
return 1;
}
trc("masterPassword: %s\n", masterPassword);
// Calculate the master key salt.
const char *mpKeyScope = ScopeForVariant(MPElementVariantPassword);
trc("key scope: %s\n", mpKeyScope);
const uint32_t n_userNameLength = htonl(strlen(userName));
size_t masterKeySaltLength = strlen(mpKeyScope) + sizeof(n_userNameLength) + strlen(userName);
char *masterKeySalt = malloc( masterKeySaltLength );
if (!masterKeySalt) {
fprintf(stderr, "Could not allocate master key salt: %d\n", errno);
return 1;
}
char *mKS = masterKeySalt;
memcpy(mKS, mpKeyScope, strlen(mpKeyScope)); mKS += strlen(mpKeyScope);
memcpy(mKS, &n_userNameLength, sizeof(n_userNameLength)); mKS += sizeof(n_userNameLength);
memcpy(mKS, userName, strlen(userName)); mKS += strlen(userName);
if (mKS - masterKeySalt != masterKeySaltLength)
abort();
trc("masterKeySalt ID: %s\n", IDForBuf(masterKeySalt, masterKeySaltLength));
// Calculate the master key.
uint8_t *masterKey = malloc( MP_dkLen );
if (!masterKey) {
fprintf (stderr, "Could not allocate master key: %d\n", errno);
return 1;
}
const uint32_t n_userNameLength = htonl(strlen(userName));
char *masterKeySalt = NULL;
size_t masterKeySaltLength = asprintf(&masterKeySalt, "com.lyndir.masterpassword%s%s", (const char *) &n_userNameLength, userName);
if (!masterKeySalt) {
fprintf (stderr, "Could not allocate master key salt: %d\n", errno);
fprintf(stderr, "Could not allocate master key: %d\n", errno);
return 1;
}
if (crypto_scrypt( (const uint8_t *)masterPassword, strlen(masterPassword), (const uint8_t *)masterKeySalt, masterKeySaltLength, MP_N, MP_r, MP_p, masterKey, MP_dkLen ) < 0) {
fprintf (stderr, "Could not generate master key: %d\n", errno);
fprintf(stderr, "Could not generate master key: %d\n", errno);
return 1;
}
memset(masterKeySalt, 0, masterKeySaltLength);
free(masterKeySalt);
trc("masterPassword Hex: %s\n", Hex(masterPassword, strlen(masterPassword)));
trc("masterPassword ID: %s\n", IDForBuf(masterPassword, strlen(masterPassword)));
trc("masterKey ID: %s\n", IDForBuf(masterKey, MP_dkLen));
// Calculate the site seed.
const uint32_t n_siteCounter = htonl(siteCounter), n_siteNameLength = htonl(strlen(siteName));
char *sitePasswordInfo = NULL;
size_t sitePasswordInfoLength = asprintf(&sitePasswordInfo, "com.lyndir.masterpassword%s%s%s", (const char *) &n_siteNameLength, siteName, (const char *) &n_siteCounter);
const char *mpSiteScope = ScopeForVariant(siteVariant);
trc("site scope: %s\n", mpSiteScope);
const uint32_t n_siteNameLength = htonl(strlen(siteName));
const uint32_t n_siteCounter = htonl(siteCounter);
size_t sitePasswordInfoLength = strlen(mpSiteScope) + sizeof(n_siteNameLength) + strlen(siteName) + sizeof(n_siteCounter);
char *sitePasswordInfo = malloc( sitePasswordInfoLength );
if (!sitePasswordInfo) {
fprintf (stderr, "Could not allocate site seed: %d\n", errno);
fprintf(stderr, "Could not allocate site seed: %d\n", errno);
return 1;
}
char *sPI = sitePasswordInfo;
memcpy(sPI, mpSiteScope, strlen(mpSiteScope)); sPI += strlen(mpSiteScope);
memcpy(sPI, &n_siteNameLength, sizeof(n_siteNameLength)); sPI += sizeof(n_siteNameLength);
memcpy(sPI, siteName, strlen(siteName)); sPI += strlen(siteName);
memcpy(sPI, &n_siteCounter, sizeof(n_siteCounter)); sPI += sizeof(n_siteCounter);
if (sPI - sitePasswordInfo != sitePasswordInfoLength)
abort();
trc("seed from: hmac-sha256(masterKey, %s | %s | %s | %s)\n", mpSiteScope, Hex(&n_siteNameLength, sizeof(n_siteNameLength)), siteName, Hex(&n_siteCounter, sizeof(n_siteCounter)));
trc("sitePasswordInfo ID: %s\n", IDForBuf(sitePasswordInfo, sitePasswordInfoLength));
uint8_t sitePasswordSeed[32];
HMAC_SHA256_Buf(masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoLength, sitePasswordSeed);
memset(masterKey, 0, MP_dkLen);
memset(sitePasswordInfo, 0, sitePasswordInfoLength);
free(masterKey);
free(sitePasswordInfo);
trc("sitePasswordSeed ID: %s\n", IDForBuf(sitePasswordSeed, 32));
// Determine the cipher.
prop_dictionary_t MPTypes_ciphers = prop_dictionary_internalize_from_file("ciphers.plist");
if (!MPTypes_ciphers) {
fprintf (stderr, "Could not read cipher definitions: %d\n", errno);
return 1;
}
prop_array_t typeCiphers = prop_dictionary_get(prop_dictionary_get(MPTypes_ciphers, "[self classNameOfType:type]"), "[self nameOfType:type]");
if (!typeCiphers) {
fprintf (stderr, "Could not find cipher definition for type: %s\n", siteTypeString);
return 1;
}
prop_string_t cipher = prop_array_get(typeCiphers, sitePasswordSeed[0] % prop_array_count(typeCiphers));
if (!typeCiphers) {
fprintf (stderr, "Missing cipher definitions for type: %s\n", siteTypeString);
return 1;
}
//trc(@"type %@, ciphers: %@, selected: %@", [self nameOfType:type], typeCiphers, cipher);
const char *cipher = CipherForType(siteType, sitePasswordSeed[0]);
trc("type %s, cipher: %s\n", siteTypeString, cipher);
if (strlen(cipher) > 32)
abort();
// Encode the password from the seed using the cipher.
//NSAssert([seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher.");
const prop_dictionary_t characterClasses = prop_dictionary_get(MPTypes_ciphers, "MPCharacterClasses");
char *sitePassword = calloc(prop_string_size(cipher) + 1, sizeof(char));
char cipherClass[2] = {0, 0};
for (int c = 0; c < prop_string_size(cipher); ++c) {
const uint16_t keyByte = sitePasswordSeed[c + 1];
cipherClass[0] = prop_string_cstring_nocopy(cipher)[c];
const prop_string_t cipherClassCharacters = prop_dictionary_get(characterClasses, cipherClass);
const char character = prop_string_cstring_nocopy(cipherClassCharacters)[ keyByte % prop_string_size(cipherClassCharacters) ];
//trc(@"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character);
sitePassword[c] = character;
char *sitePassword = calloc(strlen(cipher) + 1, sizeof(char));
for (int c = 0; c < strlen(cipher); ++c) {
sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]);
trc("class %c, character: %c\n", cipher[c], sitePassword[c]);
}
memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed));

175
MasterPassword/C/types.c Normal file
View File

@@ -0,0 +1,175 @@
//
// MPTypes.h
// MasterPassword
//
// Created by Maarten Billemont on 02/01/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <alg/sha256.h>
#include "types.h"
const MPElementType TypeWithName(const char *typeName) {
char lowerTypeName[strlen(typeName)];
strcpy(lowerTypeName, typeName);
for (char *tN = lowerTypeName; *tN; ++tN)
*tN = tolower(*tN);
if (0 == strcmp(lowerTypeName, "x") || 0 == strcmp(lowerTypeName, "max") || 0 == strcmp(lowerTypeName, "maximum"))
return MPElementTypeGeneratedMaximum;
if (0 == strcmp(lowerTypeName, "l") || 0 == strcmp(lowerTypeName, "long"))
return MPElementTypeGeneratedLong;
if (0 == strcmp(lowerTypeName, "m") || 0 == strcmp(lowerTypeName, "med") || 0 == strcmp(lowerTypeName, "medium"))
return MPElementTypeGeneratedMedium;
if (0 == strcmp(lowerTypeName, "b") || 0 == strcmp(lowerTypeName, "basic"))
return MPElementTypeGeneratedBasic;
if (0 == strcmp(lowerTypeName, "s") || 0 == strcmp(lowerTypeName, "short"))
return MPElementTypeGeneratedShort;
if (0 == strcmp(lowerTypeName, "p") || 0 == strcmp(lowerTypeName, "pin"))
return MPElementTypeGeneratedPIN;
if (0 == strcmp(lowerTypeName, "n") || 0 == strcmp(lowerTypeName, "name"))
return MPElementTypeGeneratedName;
fprintf(stderr, "Not a generated type name: %s", lowerTypeName);
abort();
}
const char *CipherForType(MPElementType type, uint8_t seedByte) {
if (!(type & MPElementTypeClassGenerated)) {
fprintf(stderr, "Not a generated type: %d", type);
abort();
}
switch (type) {
case MPElementTypeGeneratedMaximum: {
char *ciphers[] = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
return ciphers[seedByte % 2];
}
case MPElementTypeGeneratedLong: {
char *ciphers[] = { "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" };
return ciphers[seedByte % 21];
}
case MPElementTypeGeneratedMedium: {
char *ciphers[] = { "CvcnoCvc", "CvcCvcno" };
return ciphers[seedByte % 2];
}
case MPElementTypeGeneratedBasic: {
char *ciphers[] = { "aaanaaan", "aannaaan", "aaannaaa" };
return ciphers[seedByte % 3];
}
case MPElementTypeGeneratedShort: {
return "Cvcn";
}
case MPElementTypeGeneratedPIN: {
return "nnnn";
}
case MPElementTypeGeneratedName: {
return "cvccvcvcv";
}
default: {
fprintf(stderr, "Unknown generated type: %d", type);
abort();
}
}
}
const MPElementVariant VariantWithName(const char *variantName) {
char lowerVariantName[strlen(variantName)];
strcpy(lowerVariantName, variantName);
for (char *vN = lowerVariantName; *vN; ++vN)
*vN = tolower(*vN);
if (0 == strcmp(lowerVariantName, "p") || 0 == strcmp(lowerVariantName, "password"))
return MPElementVariantPassword;
if (0 == strcmp(lowerVariantName, "l") || 0 == strcmp(lowerVariantName, "login"))
return MPElementVariantLogin;
fprintf(stderr, "Not a variant name: %s", lowerVariantName);
abort();
}
const char *ScopeForVariant(MPElementVariant variant) {
switch (variant) {
case MPElementVariantPassword: {
return "com.lyndir.masterpassword";
}
case MPElementVariantLogin: {
return "com.lyndir.masterpassword.login";
}
default: {
fprintf(stderr, "Unknown variant: %d", variant);
abort();
}
}
}
const char CharacterFromClass(char characterClass, uint8_t seedByte) {
const char *classCharacters;
switch (characterClass) {
case 'V': {
classCharacters = "AEIOU";
break;
}
case 'C': {
classCharacters = "BCDFGHJKLMNPQRSTVWXYZ";
break;
}
case 'v': {
classCharacters = "aeiou";
break;
}
case 'c': {
classCharacters = "bcdfghjklmnpqrstvwxyz";
break;
}
case 'A': {
classCharacters = "AEIOUBCDFGHJKLMNPQRSTVWXYZ";
break;
}
case 'a': {
classCharacters = "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz";
break;
}
case 'n': {
classCharacters = "0123456789";
break;
}
case 'o': {
classCharacters = "@&%?,=[]_:-+*$#!'^~;()/.";
break;
}
case 'x': {
classCharacters = "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()";
break;
}
default: {
fprintf(stderr, "Unknown character class: %c", characterClass);
abort();
}
}
return classCharacters[seedByte % strlen(classCharacters)];
}
const char *IDForBuf(const void *buf, size_t length) {
uint8_t hash[32];
SHA256_Buf(buf, length, hash);
char *id = calloc(65, sizeof(char));
for (int kH = 0; kH < 32; kH++)
sprintf(&(id[kH * 2]), "%02X", hash[kH]);
return id;
}
const char *Hex(const void *buf, size_t length) {
char *id = calloc(length*2+1, sizeof(char));
for (int kH = 0; kH < length; kH++)
sprintf(&(id[kH * 2]), "%02X", ((const uint8_t*)buf)[kH]);
return id;
}

56
MasterPassword/C/types.h Normal file
View File

@@ -0,0 +1,56 @@
//
// MPTypes.h
// MasterPassword
//
// Created by Maarten Billemont on 02/01/12.
// Copyright (c) 2012 Lyndir. All rights reserved.
//
typedef enum {
/** Generate the password to log in with. */
MPElementVariantPassword,
/** Generate the login name to log in as. */
MPElementVariantLogin,
} MPElementVariant;
typedef enum {
/** Generate the password. */
MPElementTypeClassGenerated = 1 << 4,
/** Store the password. */
MPElementTypeClassStored = 1 << 5,
} MPElementTypeClass;
typedef enum {
/** Export the key-protected content data. */
MPElementFeatureExportContent = 1 << 10,
/** Never export content. */
MPElementFeatureDevicePrivate = 1 << 11,
} MPElementFeature;
typedef enum {
MPElementTypeGeneratedMaximum = 0x0 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedBasic = 0x4 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedShort = 0x3 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedPIN = 0x5 | MPElementTypeClassGenerated | 0x0,
MPElementTypeGeneratedName = 0xF | MPElementTypeClassGenerated | 0x0,
MPElementTypeStoredPersonal = 0x0 | MPElementTypeClassStored | MPElementFeatureExportContent,
MPElementTypeStoredDevicePrivate = 0x1 | MPElementTypeClassStored | MPElementFeatureDevicePrivate,
} MPElementType;
#ifdef DEBUG
#define trc(...) fprintf(stderr, __VA_ARGS__)
#else
#define trc(...) do {} while (0)
#endif
const MPElementVariant VariantWithName(const char *variantName);
const char *ScopeForVariant(MPElementVariant variant);
const MPElementType TypeWithName(const char *typeName);
const char *CipherForType(MPElementType type, uint8_t seedByte);
const char CharacterFromClass(char characterClass, uint8_t seedByte);
const char *IDForBuf(const void *buf, size_t length);
const char *Hex(const void *buf, size_t length);

View File

@@ -5,7 +5,7 @@
<!-- PROJECT METADATA -->
<parent>
<groupId>com.lyndir.lhunath.masterpassword</groupId>
<groupId>com.lyndir.masterpassword</groupId>
<artifactId>masterpassword</artifactId>
<version>GIT-SNAPSHOT</version>
</parent>
@@ -13,7 +13,7 @@
<name>Master Password Algorithm Implementation</name>
<description>The implementation of the Master Password algorithm</description>
<groupId>com.lyndir.lhunath.masterpassword</groupId>
<groupId>com.lyndir.masterpassword</groupId>
<artifactId>masterpassword-algorithm</artifactId>
<packaging>jar</packaging>
@@ -24,12 +24,12 @@
<dependency>
<groupId>com.lyndir.lhunath.opal</groupId>
<artifactId>opal-system</artifactId>
<version>GIT-SNAPSHOT</version>
<version>1.6-p6</version>
</dependency>
<dependency>
<groupId>com.lyndir.lhunath.opal</groupId>
<artifactId>opal-crypto</artifactId>
<version>GIT-SNAPSHOT</version>
<version>1.6-p6</version>
</dependency>
<!-- EXTERNAL DEPENDENCIES -->
@@ -41,7 +41,7 @@
<dependency>
<groupId>com.lambdaworks</groupId>
<artifactId>scrypt</artifactId>
<version>1.3.2</version>
<version>1.4.0</version>
</dependency>
</dependencies>

View File

@@ -1,5 +1,6 @@
package com.lyndir.lhunath.masterpassword;
package com.lyndir.masterpassword;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.lyndir.lhunath.opal.system.logging.Logger;
import java.util.Set;
@@ -19,18 +20,21 @@ public enum MPElementType {
GeneratedShort( "Short Password", "Short", "Copy-friendly, 4 characters, no symbols.", MPElementTypeClass.Generated ),
GeneratedPIN( "PIN", "PIN", "4 numbers.", MPElementTypeClass.Generated ),
StoredPersonal( "Personal Password", "Personal", "AES-encrypted, exportable.", MPElementTypeClass.Stored, MPElementFeature.ExportContent ),
StoredDevicePrivate( "Device Private Password", "Private", "AES-encrypted, not exported.", MPElementTypeClass.Stored, MPElementFeature.DevicePrivate );
StoredPersonal( "Personal Password", "Personal", "AES-encrypted, exportable.", MPElementTypeClass.Stored,
MPElementFeature.ExportContent ),
StoredDevicePrivate( "Device Private Password", "Private", "AES-encrypted, not exported.", MPElementTypeClass.Stored,
MPElementFeature.DevicePrivate );
static final Logger logger = Logger.get( MPElementType.class );
private final MPElementTypeClass typeClass;
private final Set<MPElementFeature> typeFeatures;
private final String name;
private final String shortName;
private final MPElementTypeClass typeClass;
private final Set<MPElementFeature> typeFeatures;
private final String name;
private final String shortName;
private final String description;
MPElementType(final String name, final String shortName, final String description, final MPElementTypeClass typeClass, final MPElementFeature... typeFeatures) {
MPElementType(final String name, final String shortName, final String description, final MPElementTypeClass typeClass,
final MPElementFeature... typeFeatures) {
this.name = name;
this.shortName = shortName;
@@ -38,8 +42,9 @@ public enum MPElementType {
this.description = description;
ImmutableSet.Builder<MPElementFeature> typeFeaturesBuilder = ImmutableSet.builder();
for (final MPElementFeature typeFeature : typeFeatures)
for (final MPElementFeature typeFeature : typeFeatures) {
typeFeaturesBuilder.add( typeFeature );
}
this.typeFeatures = typeFeaturesBuilder.build();
}
@@ -68,12 +73,33 @@ public enum MPElementType {
return description;
}
/**
* @param name The full or short name of the type we want to look up. It is matched case insensitively.
*
* @return The type with the given name.
*/
public static MPElementType forName(final String name) {
for (final MPElementType type : values())
if (type.getName().equals( name ))
if (type.getName().equalsIgnoreCase( name ) || type.getShortName().equalsIgnoreCase( name ))
return type;
throw logger.bug( "Element type not known: %s", name );
}
/**
* @param typeClass The class for which we look up types.
*
* @return All types that support the given class.
*/
public static ImmutableList<MPElementType> forClass(final MPElementTypeClass typeClass) {
ImmutableList.Builder<MPElementType> types = ImmutableList.builder();
for (final MPElementType type : values())
if (type.getTypeClass() == typeClass)
types.add( type );
return types.build();
}
}

View File

@@ -1,6 +1,6 @@
package com.lyndir.lhunath.masterpassword;
package com.lyndir.masterpassword;
import com.lyndir.lhunath.masterpassword.entity.*;
import com.lyndir.masterpassword.entity.*;
/**

View File

@@ -1,4 +1,4 @@
package com.lyndir.lhunath.masterpassword;
package com.lyndir.masterpassword;
import com.google.common.collect.ImmutableList;
import com.lyndir.lhunath.opal.system.util.MetaObject;

View File

@@ -1,4 +1,4 @@
package com.lyndir.lhunath.masterpassword;
package com.lyndir.masterpassword;
import com.lyndir.lhunath.opal.system.util.MetaObject;
import com.lyndir.lhunath.opal.system.util.ObjectMeta;

View File

@@ -1,4 +1,4 @@
package com.lyndir.lhunath.masterpassword;
package com.lyndir.masterpassword;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;

View File

@@ -1,7 +1,9 @@
package com.lyndir.lhunath.masterpassword;
package com.lyndir.masterpassword;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.io.CharSource;
import com.google.common.io.CharStreams;
import com.google.common.primitives.Bytes;
import com.lambdaworks.crypto.SCrypt;
import com.lyndir.lhunath.opal.crypto.CryptUtils;
@@ -11,18 +13,17 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import javax.xml.stream.events.Characters;
/**
* Implementation of the Master Password algorithm.
*
* <i>07 04, 2012</i>
*
* @author lhunath
* @author lhunath, 2014-08-30
*/
public abstract class MasterPassword {
public class MasterKey {
static final Logger logger = Logger.get( MasterPassword.class );
@SuppressWarnings("UnusedDeclaration")
private static final Logger logger = Logger.get( MasterKey.class );
private static final int MP_N = 32768;
private static final int MP_r = 8;
private static final int MP_p = 2;
@@ -33,52 +34,60 @@ public abstract class MasterPassword {
private static final MessageAuthenticationDigests MP_mac = MessageAuthenticationDigests.HmacSHA256;
private static final MPTemplates templates = MPTemplates.load();
public static byte[] keyForPassword(final String password, final String username) {
private final String userName;
private final byte[] key;
private boolean valid;
public MasterKey(final String userName, final String masterPassword) {
this.userName = userName;
long start = System.currentTimeMillis();
byte[] nusernameLengthBytes = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE )
.order( MP_byteOrder )
.putInt( username.length() )
.array();
byte[] userNameLengthBytes = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE )
.order( MP_byteOrder )
.putInt( userName.length() )
.array();
byte[] salt = Bytes.concat( "com.lyndir.masterpassword".getBytes( MP_charset ), //
nusernameLengthBytes, //
username.getBytes( MP_charset ) );
userNameLengthBytes, userName.getBytes( MP_charset ) );
try {
byte[] key = SCrypt.scrypt( password.getBytes( MP_charset ), salt, MP_N, MP_r, MP_p, MP_dkLen );
logger.trc( "User: %s, password: %s derives to key ID: %s (took %.2fs)", username, password,
CodeUtils.encodeHex( keyIDForKey( key ) ), (double) (System.currentTimeMillis() - start) / 1000 );
key = SCrypt.scrypt( masterPassword.getBytes( MP_charset ), salt, MP_N, MP_r, MP_p, MP_dkLen );
valid = true;
return key;
logger.trc( "User: %s, master password derives to key ID: %s (took %.2fs)", //
userName, getKeyID(), (double) (System.currentTimeMillis() - start) / 1000 );
}
catch (GeneralSecurityException e) {
throw logger.bug( e );
}
}
public static byte[] subkeyForKey(final byte[] key, final int subkeyLength) {
public String getUserName() {
return userName;
}
public String getKeyID() {
Preconditions.checkState( valid );
return CodeUtils.encodeHex( MP_hash.of( key ) );
}
private byte[] getSubkey(final int subkeyLength) {
Preconditions.checkState( valid );
byte[] subkey = new byte[Math.min( subkeyLength, key.length )];
System.arraycopy( key, 0, subkey, 0, subkey.length );
return subkey;
}
public static byte[] keyIDForPassword(final String password, final String username) {
return keyIDForKey( keyForPassword( password, username ) );
}
public static byte[] keyIDForKey(final byte[] key) {
return MP_hash.of( key );
}
public static String generateContent(final MPElementType type, final String name, final byte[] key, int counter) {
public String encode(final String name, final MPElementType type, int counter) {
Preconditions.checkState( valid );
Preconditions.checkArgument( type.getTypeClass() == MPElementTypeClass.Generated );
Preconditions.checkArgument( !name.isEmpty() );
Preconditions.checkArgument( key.length > 0 );
if (counter == 0)
counter = (int) (System.currentTimeMillis() / (300 * 1000)) * 300;
@@ -112,17 +121,9 @@ public abstract class MasterPassword {
return password.toString();
}
public static void main(final String... arguments) {
public void invalidate() {
String masterPassword = "test-mp";
String username = "test-user";
String siteName = "test-site";
MPElementType siteType = MPElementType.GeneratedLong;
int siteCounter = 42;
String sitePassword = generateContent( siteType, siteName, keyForPassword( masterPassword, username ), siteCounter );
logger.inf( "master password: %s, username: %s\nsite name: %s, site type: %s, site counter: %d\n => site password: %s",
masterPassword, username, siteName, siteType, siteCounter, sitePassword );
valid = false;
Arrays.fill( key, (byte) 0 );
}
}

View File

@@ -1,18 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lyndir.lhunath.masterpassword" android:versionCode="1" android:versionName="GIT-SNAPSHOT">
package="com.lyndir.masterpassword"
android:versionCode="1"
android:versionName="GIT-SNAPSHOT">
<uses-sdk android:minSdkVersion="8"
android:targetSdkVersion="16" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".HelloAndroidActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:allowBackup="true">
<activity android:name=".EmergencyActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".UsersActivity" />
</application>
</manifest>

View File

@@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/
package com.lyndir.masterpassword;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}

View File

@@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package com.lyndir.masterpassword;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/
package com.lyndir.masterpassword;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@@ -5,7 +5,7 @@
<!-- PROJECT METADATA -->
<parent>
<groupId>com.lyndir.lhunath.masterpassword</groupId>
<groupId>com.lyndir.masterpassword</groupId>
<artifactId>masterpassword</artifactId>
<version>GIT-SNAPSHOT</version>
</parent>
@@ -13,7 +13,7 @@
<name>Master Password Android</name>
<description>An Android application to the Master Password algorithm</description>
<groupId>com.lyndir.lhunath.masterpassword</groupId>
<groupId>com.lyndir.masterpassword</groupId>
<artifactId>masterpassword-android</artifactId>
<packaging>apk</packaging>
@@ -24,35 +24,101 @@
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<!--configuration>
<proguard>
<configuration>
<zipalign>
<verbose>true</verbose>
<skip>false</skip>
<config>proguard.cfg</config>
</proguard>
</configuration-->
</zipalign>
<sdk>
<platform>19</platform>
</sdk>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>sign</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<executions>
<execution>
<id>signing</id>
<goals>
<goal>sign</goal>
</goals>
<phase>package</phase>
<inherited>true</inherited>
<configuration>
<archiveDirectory></archiveDirectory>
<includes>
<include>target/*.apk</include>
</includes>
<keystore>release.jks</keystore>
<storepass>${env.PASSWORD}</storepass>
<keypass>${env.PASSWORD}</keypass>
<alias>android</alias>
<arguments>
<argument>-sigalg</argument><argument>MD5withRSA</argument>
<argument>-digestalg</argument><argument>SHA1</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<inherited>true</inherited>
<configuration>
<sign>
<debug>false</debug>
</sign>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<!-- DEPENDENCY MANAGEMENT -->
<dependencies>
<!-- PROJECT REFERENCES -->
<dependency>
<groupId>com.lyndir.lhunath.masterpassword</groupId>
<groupId>com.lyndir.masterpassword</groupId>
<artifactId>masterpassword-algorithm</artifactId>
<version>GIT-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<groupId>com.jakewharton</groupId>
<artifactId>butterknife</artifactId>
</dependency>
<dependency>
<groupId>com.google.android</groupId>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-android</artifactId>
</dependency>
<!-- clone https://github.com/mosabua/maven-android-sdk-deployer.git
run mvn install -P 4.4 -->
<dependency>
<groupId>android</groupId>
<artifactId>android</artifactId>
<version>4.1.1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.lambdaworks</groupId>
<artifactId>libscrypt</artifactId>
<version>1.4.0</version>
<type>so</type>
<classifier>android</classifier>
<scope>runtime</scope>
</dependency>
</dependencies>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Some files were not shown because too many files have changed in this diff Show More