diff --git a/README.md b/README.md deleted file mode 100644 index 344db1e3..00000000 --- a/README.md +++ /dev/null @@ -1,207 +0,0 @@ -[![Travis CI](http://img.shields.io/travis-ci/Lyndir/MasterPassword.png)](https://travis-ci.org/Lyndir/MasterPassword) -[![Join the chat at https://gitter.im/lyndir/MasterPassword](https://badges.gitter.im/lyndir/MasterPassword.svg)](https://gitter.im/lyndir/MasterPassword?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![license](https://img.shields.io/github/license/lyndir/masterpassword.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) - - - - -# [Master Password •••|](http://masterpasswordapp.com) - -Master Password is a completely new way of thinking about passwords. - -It consists of an algorithm that implements the core idea and applications for various platforms making the alogirthm available to users on a variety of devices and platforms. - -To skip the intro and go straight to the information on how to use the code, [click here](#source-code). - -Master Password is available for [📲 iOS](https://itunes.apple.com/app/id510296984), [🖥 macOS](https://ssl.masterpasswordapp.com/masterpassword-mac.zip), [📲 Android](https://ssl.masterpasswordapp.com/masterpassword-android.apk), [🖥 Desktop](https://ssl.masterpasswordapp.com/masterpassword-gui.jar), and [⌨ Console](https://ssl.masterpasswordapp.com/masterpassword-cli.tar.gz). - -Master Password is also available from the following package managers: [macOS: Homebrew](https://brew.sh/) (`brew install mpw`). -Get in touch if you are interested in adding Master Password to any other package managers. - -There are many reasons for using Master Password instead of an ordinary password manager, read below for the details, but if you want my personal favourites, they would be: - - - I don't need to worry about keeping backups of my countless authentication credentials. - - I don't need to worry that when I travel, I might not have access to my passwords vault. - - I don't need to trust an external party, proprietary code or a service to be online and stay online. - - If I feel at risk of my device being stolen or confiscated, I can set a fake master password, delete my user or wipe it worry-free. - -We also have a [Frequently Asked Questions](#faq). - - - -## What is a password? - -Ah, the "password". Somehow, passwords have become the default solution to authentication across the web. We've long since accepted this as the way things are, but let's stop to think for a moment about what passwords actually are: - -A password is a secret that is known only to the party providing a service and the party that should be allowed access to this service. - -Simple enough - a secret that you know and your website knows but nobody else, thereby guaranteeing that you and only you have access to your account on this website. Unfortunately, in practice, the ubiquitous use of passwords has us completely overwhelmed. And the only way we can cope with that is by finding ways of making the problem manageable. - - - -## What's the problem? - -Coming up with a secret password is pretty easy. Say you're organizing a secret meeting and will only let people in if they know the password at the door. You tell those you trust, the password for tonight's meeting is "purple oranges with a smile". - -The problem we have in our daily lives, however, is the fact that we need secret passwords for almost everything now. A password for our email, twitter, 9gag, facebook, imgur, amazon, ebay, paypal, bank, reddit, etc. And every time we want to use a new site, we need another one. The problem now becomes clear: passwords are meant to be remembered and recalled with ease when needed, but this becomes impossible when we have secrets for every distinct activity in our lives. - -We cannot recall passwords the way we are expected to when there are too many. - - - -## Coping - -Life gives us no advice on how to deal with this problem. So we find our own ways: - - - We use a single personal secret for all our websites, thereby violating the secrecy of these passwords (eg. you've given your email secret to twitter). - - We use simple variations of a personal secret or pattern, thereby trivializing the complexity of these passwords (eg. google98, twitter98; reversals, eg. 8991elgoog) - - We use external means of remembering passwords, thereby increasing the risk of loss (both loss of access when we lose the tool and theft when a thief finds our tool) - -These coping mechanisms come in various forms, and they all have down-sides, because at the root of each of these lies an undeniable truth: - -Our passwords are no longer true to the original definition. - - - -## Master Password's approach - -The theory behind Master Password starts with accepting that it is impossible to keep track of passwords for all your accounts. Instead, we return to the core premise of the password: a secret phrase that you can remember easily, all by yourself. - -Master Password solves this problem by letting you remember one and only one password. You use this password with Master Password only. Master Password then gives you access to any website or service you want by creating a website-specific key for it. - -1. You sign into Master Password using your one password. -2. You ask Master Password for the key to enter your website, eg. twitter. -3. You log into twitter using your username and the key from Master Password. - -Master Password is *not* a password manager. It does not store your website passwords. Therefore, there is zero risk of you losing your website passwords (or them falling in the wrong hands). Master Password simply uses your one password and the name of the site to generate a site-specific secret. - - - -## Benefits - - - You don't need to think up a new strong password every time you make a new account - Master Password gives you the key for it. - - You don't need to try remembering a password you created two years ago for that one account - Master Password just gives you the key for it. - - You don't need to worry about getting into that account you made at work after you come home because you don't have your office passwords with you - Master Password is availale everywhere, even offline. - - You don't need to try to keep password lists in sync or stored somewhere easily accessible - Master Password keys can be created anywhere. - - You don't need to worry what you'll do if your computer dies or you need to log into your bank while you're in the airport transit zone - your Master Password keys are always available, even when starting empty. - - You don't need to worry about your password manager website getting hacked, your phone getting duplicated, somebody taking a picture of your passwords book - Master Password stores no secrets. - - - -## How does it work? - -The details of how Master Password works [are available here](http://masterpasswordapp.com/algorithm.html). - -In short: - - master-key = SCRYPT( user-name, master-password ) - site-key = HMAC-SHA-256( site-name . site-counter, master-key ) - site-password = PW-TEMPLATE( site-key, site-template ) - -Master Password can derive the `site-password` in an entirely stateless manner. It is therefore better defined as a calculator than a manager. It is the user's responsibility to remember the inputs: `user-name`, `master-password`, `site-name`, `site-counter` and `site-template`. - -We standardize `user-name` as your full name, `site-name` as the domain name of the site, `site-counter` to `1` (unless you explicitly increment it) and `site-template` to `Long Password`; as a result the only token the user really needs to remember actively is `master-password`. - - - -## FAQ - - 1. If I lose my master password and need to set a new one, will I need to change all of my site passwords? - -Yes. If your master password is compromised, it is only sensible for you to change all of your site passwords. Just like if you lose the keys in your pocket, you'll have to change all the locks they open. Master Password effectively enforces this security practice. - - 2. But what if I just forget my master password or I just want to change it to something else? - -Sorry, still yes. Your master password is the secret component to your Master Password identity. If it changes, your identity changes. I wholly encourage you to think very carefully about what makes for a really memorable and good master password before just diving in with something lazy. A short phrase works great, eg. `banana coloured duckling`. - - 3. Doesn't this mean an attacker can reverse my master password from any of my site passwords? - -Technically, yes. Practically, no. - -You could argue that site passwords are "breadcrumbs" of your master password, but the same argument would suggest encrypted messages are breadcrumbs to the encryption key. Encryption works because it is computationally unfeasible to "guess" the encryption key that made the encrypted message, just like Master Password works because it is computationally unfeasible to "guess" your master password that made the site password. - - 4. The second step is just a HMAC-SHA-256, doesn't that make the SCRYPT completely pointless? - -No. They are used for different reasons and one is not weaker than the other. - -HMAC-SHA-256 is much faster to compute than SCRYPT, which leads some people to think "all an attacker needs to do is brute-force the SHA and ignore the SCRYPT". The reality is that the HMAC-SHA-256 guards a 64-byte authentication key (the `master-key`) which makes the search space for brute-forcing the HMAC wildly too large to compute. -The `master-password` on the other hand, is only a simple phrase, which means its search space is much smaller. This is why it is guarded by a much tougher SCRYPT operation. - - 5. I have another question. - -Please don't hesitate to [get in touch](#support), we're more than happy to answer all your Master Password questions. Any problems or suggestions can be reported [as GitHub issues](https://github.com/Lyndir/MasterPassword/issues). - - - - -# Source Code - -Master Password's algorithm is [documented](http://masterpasswordapp.com/algorithm.html) and its implementation is Free Software (GPLv3). - - - -## Components - -There are several components available here. As an end-user, you can currently use the iOS app, the Android app, the OS X app, the Java desktop app, the C CLI app or the Java CLI app. There are also several components that are useful for developers: - - - `core/c`: This is the reference implementation of the Master Password algorithm, written in C. - - `core/java/algorithm`: This is a Java implementation of the Master Password algorithm. - - `core/java/model`: This is an object model to simplify use of Master Password by Java applications. - - `core/java/tests`: These are Java integration tests designed to ensure Master Password performs as expected. - - `platform-android`: This is the official Android implementation of Master Password in Java. - - `platform-darwin`: This is the official iOS and OS X implementation of Master Password in Objective-C. - - `platform-independent/cli-c`: This is the platform-independent console implementation of Master Password, written in C. - - `platform-independent/cli-java`: This is the platform-independent console implementation of Master Password, written in Java. - - `platform-independent/gui-java`: This is the platform-independent desktop implementation of Master Password, written in Java. - - `platform-independent/web-js`: This is the platform-independent browser application for Master Password, written in JavaScript. - - - -## Building and running - - -### macOS or iOS - -Make sure you have all relevant submodules checked out. - -Go into `platform-darwin` and open `MasterPassword.xcworkspace` in Xcode. Select the desired target from the Scheme Selector and build, run or archive. - - -### Web - -Make sure you have all relevant submodules checked out. - -Go into `platform-independent/web-js` and open `index.html` in your browser. You should be able to run this locally, there is no need for hosting or an application server. - - -### Java - -Go into the `gradle` directory and run `./gradlew build`. All Java components will then be built: - - - `platform-independent/gui-java/build/distributions`: - contains an archive with the Master Password Java GUI. Unpack it and run the `gui` script. - - `platform-independent/cli-java/build/distributions`: - contains an archive with the Master Password Java command-line interface. Unpack it and run the `cli` script. - - `platform-android/build/outputs/apk`: - contains the Android application package. Install it on your Android device. - -Note that in order to build the Android application, you will need to have the Android SDK installed and either have the environment variable `ANDROID_HOME` set to its location or a `gradle/local.properties` file with its location, eg. (for Homebrew users who installed the SDK using `brew install android-sdk`): - - sdk.dir=/usr/local/opt/android-sdk - - -### Native CLI - -Go into the `platform-independent/cli-c` directory and run `./build`. The native command-line client will then be built. - -For detailed instructions, see [the native CLI instructions](platform-independent/cli-c/README.md). - - -## Support - -Feel free to contribute by forking the project, reporting issues or joining the discussion on: - - - [Gitter](https://gitter.im/lyndir/MasterPassword) - - #masterpassword (on chat.freenode.net) - - #masterpassword:lyndir.com (on Matrix) - - masterpassword@lyndir.com diff --git a/public/site/2015-05/_config.yml b/_config.yml similarity index 100% rename from public/site/2015-05/_config.yml rename to _config.yml diff --git a/public/site/2015-05/_includes/footer.html b/_includes/footer.html similarity index 100% rename from public/site/2015-05/_includes/footer.html rename to _includes/footer.html diff --git a/public/site/2015-05/_includes/head.html b/_includes/head.html similarity index 73% rename from public/site/2015-05/_includes/head.html rename to _includes/head.html index 1598d6fe..954896ac 100644 --- a/public/site/2015-05/_includes/head.html +++ b/_includes/head.html @@ -1,12 +1,15 @@ - + {% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %} + + + diff --git a/public/site/2015-05/_includes/header.html b/_includes/header.html similarity index 100% rename from public/site/2015-05/_includes/header.html rename to _includes/header.html diff --git a/public/site/2015-05/_includes/icon-github.html b/_includes/icon-github.html similarity index 100% rename from public/site/2015-05/_includes/icon-github.html rename to _includes/icon-github.html diff --git a/public/site/2015-05/_includes/icon-github.svg b/_includes/icon-github.svg similarity index 100% rename from public/site/2015-05/_includes/icon-github.svg rename to _includes/icon-github.svg diff --git a/public/site/2015-05/_includes/icon-twitter.html b/_includes/icon-twitter.html similarity index 100% rename from public/site/2015-05/_includes/icon-twitter.html rename to _includes/icon-twitter.html diff --git a/public/site/2015-05/_includes/icon-twitter.svg b/_includes/icon-twitter.svg similarity index 100% rename from public/site/2015-05/_includes/icon-twitter.svg rename to _includes/icon-twitter.svg diff --git a/public/site/2015-05/_layouts/default.html b/_layouts/default.html similarity index 100% rename from public/site/2015-05/_layouts/default.html rename to _layouts/default.html diff --git a/public/site/2015-05/_sass/_base.scss b/_sass/_base.scss similarity index 100% rename from public/site/2015-05/_sass/_base.scss rename to _sass/_base.scss diff --git a/public/site/2015-05/_sass/_layout.scss b/_sass/_layout.scss similarity index 100% rename from public/site/2015-05/_sass/_layout.scss rename to _sass/_layout.scss diff --git a/public/site/2015-05/_sass/_syntax-highlighting.scss b/_sass/_syntax-highlighting.scss similarity index 100% rename from public/site/2015-05/_sass/_syntax-highlighting.scss rename to _sass/_syntax-highlighting.scss diff --git a/core/c/aes.c b/core/c/aes.c deleted file mode 100644 index 7148ad5e..00000000 --- a/core/c/aes.c +++ /dev/null @@ -1,606 +0,0 @@ -/* - -Source: https://github.com/kokke/tiny-AES-c - -This is an implementation of the AES algorithm, specifically ECB and CBC mode. -Block size can be chosen in aes.h - available choices are AES128, AES192, AES256. - -The implementation is verified against the test vectors in: - National Institute of Standards and Technology Special Publication 800-38A 2001 ED - -ECB-AES128 ----------- - - plain-text: - 6bc1bee22e409f96e93d7e117393172a - ae2d8a571e03ac9c9eb76fac45af8e51 - 30c81c46a35ce411e5fbc1191a0a52ef - f69f2445df4f9b17ad2b417be66c3710 - - key: - 2b7e151628aed2a6abf7158809cf4f3c - - resulting cipher - 3ad77bb40d7a3660a89ecaf32466ef97 - f5d3d58503b9699de785895a96fdbaaf - 43b1cd7f598ece23881b00e3ed030688 - 7b0c785e27e8ad3f8223207104725dd4 - - -NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) - You should pad the end of the string with zeros if this is not the case. - For AES192/256 the block size is proportionally larger. - -*/ - - -/*****************************************************************************/ -/* Includes: */ -/*****************************************************************************/ -#include -#include "aes.h" -#include "mpw-util.h" - -/*****************************************************************************/ -/* Defines: */ -/*****************************************************************************/ -// The number of columns comprising a state in AES. This is a constant in AES. Value=4 -#define Nb 4 - -#if defined(AES_256) && (AES_256 == 1) - #define Nk 8 - #define KEYLEN 32 - #define Nr 14 - #define keyExpSize 240 -#elif defined(AES_192) && (AES_192 == 1) - #define Nk 6 - #define KEYLEN 24 - #define Nr 12 - #define keyExpSize 208 -#elif defined(AES_128) && (AES_128 == 1) - #define Nk 4 // The number of 32 bit words in a key. - #define KEYLEN 16 // Key length in bytes - #define Nr 10 // The number of rounds in AES Cipher. - #define keyExpSize 176 -#else - #error Must define either AES_128, AES_192 or AES_256. -#endif - -// jcallan@github points out that declaring Multiply as a function -// reduces code size considerably with the Keil ARM compiler. -// See this link for more information: https://github.com/kokke/tiny-AES128-C/pull/3 -#ifndef MULTIPLY_AS_A_FUNCTION - #define MULTIPLY_AS_A_FUNCTION 0 -#endif - - -/*****************************************************************************/ -/* Private variables: */ -/*****************************************************************************/ -// state - array holding the intermediate results during decryption. -typedef uint8_t state_t[4][4]; -static state_t* state; - -// The array that stores the round keys. -static uint8_t RoundKey[keyExpSize]; - -// The Key input to the AES Program -static const uint8_t* Key; - -#if defined(AES_CBC) && AES_CBC - // Initial Vector used only for CBC mode - static uint8_t* Iv; -#endif - -// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM -// The numbers below can be computed dynamically trading ROM for RAM - -// This can be useful in (embedded) bootloader applications, where ROM is often limited. -static const uint8_t sbox[256] = { - //0 1 2 3 4 5 6 7 8 9 A B C D E F - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; - -static const uint8_t rsbox[256] = { - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; - -// The round constant word array, Rcon[i], contains the values given by -// x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) -static const uint8_t Rcon[11] = { - 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; - -/* - * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES128-C/pull/12), - * that you can remove most of the elements in the Rcon array, because they are unused. - * - * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon - * - * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed), - * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm." - * - * ... which is why the full array below has been 'disabled' below. - */ -#if 0 -static const uint8_t Rcon[256] = { - 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, - 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, - 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, - 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, - 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, - 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, - 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, - 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, - 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, - 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, - 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, - 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, - 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, - 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, - 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, - 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d }; -#endif - -/*****************************************************************************/ -/* Private functions: */ -/*****************************************************************************/ -static uint8_t getSBoxValue(uint8_t num) -{ - return sbox[num]; -} - -static uint8_t getSBoxInvert(uint8_t num) -{ - return rsbox[num]; -} - -// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. -static void KeyExpansion(void) -{ - uint32_t i; - uint8_t k, tempa[4]; // Used for the column/row operations - - // The first round key is the key itself. - for (i = 0; i < Nk; ++i) - { - RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; - RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; - RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; - RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; - } - - // All other round keys are found from the previous round keys. - //i == Nk - for (; i < Nb * (Nr + 1); ++i) - { - { - tempa[0]=RoundKey[(i-1) * 4 + 0]; - tempa[1]=RoundKey[(i-1) * 4 + 1]; - tempa[2]=RoundKey[(i-1) * 4 + 2]; - tempa[3]=RoundKey[(i-1) * 4 + 3]; - } - - if (i % Nk == 0) - { - // This function shifts the 4 bytes in a word to the left once. - // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] - - // Function RotWord() - { - k = tempa[0]; - tempa[0] = tempa[1]; - tempa[1] = tempa[2]; - tempa[2] = tempa[3]; - tempa[3] = k; - } - - // SubWord() is a function that takes a four-byte input word and - // applies the S-box to each of the four bytes to produce an output word. - - // Function Subword() - { - tempa[0] = getSBoxValue(tempa[0]); - tempa[1] = getSBoxValue(tempa[1]); - tempa[2] = getSBoxValue(tempa[2]); - tempa[3] = getSBoxValue(tempa[3]); - } - - tempa[0] = tempa[0] ^ Rcon[i/Nk]; - } -#if defined(AES256) && (AES256 == 1) - if (i % Nk == 4) - { - // Function Subword() - { - tempa[0] = getSBoxValue(tempa[0]); - tempa[1] = getSBoxValue(tempa[1]); - tempa[2] = getSBoxValue(tempa[2]); - tempa[3] = getSBoxValue(tempa[3]); - } - } -#endif - RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0]; - RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1]; - RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2]; - RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3]; - } -} - -// This function adds the round key to state. -// The round key is added to the state by an XOR function. -static void AddRoundKey(uint8_t round) -{ - uint8_t i,j; - for (i=0;i<4;++i) - { - for (j = 0; j < 4; ++j) - { - (*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j]; - } - } -} - -// The SubBytes Function Substitutes the values in the -// state matrix with values in an S-box. -static void SubBytes(void) -{ - uint8_t i, j; - for (i = 0; i < 4; ++i) - { - for (j = 0; j < 4; ++j) - { - (*state)[j][i] = getSBoxValue((*state)[j][i]); - } - } -} - -// The ShiftRows() function shifts the rows in the state to the left. -// Each row is shifted with different offset. -// Offset = Row number. So the first row is not shifted. -static void ShiftRows(void) -{ - uint8_t temp; - - // Rotate first row 1 columns to left - temp = (*state)[0][1]; - (*state)[0][1] = (*state)[1][1]; - (*state)[1][1] = (*state)[2][1]; - (*state)[2][1] = (*state)[3][1]; - (*state)[3][1] = temp; - - // Rotate second row 2 columns to left - temp = (*state)[0][2]; - (*state)[0][2] = (*state)[2][2]; - (*state)[2][2] = temp; - - temp = (*state)[1][2]; - (*state)[1][2] = (*state)[3][2]; - (*state)[3][2] = temp; - - // Rotate third row 3 columns to left - temp = (*state)[0][3]; - (*state)[0][3] = (*state)[3][3]; - (*state)[3][3] = (*state)[2][3]; - (*state)[2][3] = (*state)[1][3]; - (*state)[1][3] = temp; -} - -static uint8_t xtime(uint8_t x) -{ - return (uint8_t)((x << 1) ^ (((x >> 7) & 1) * 0x1b)); -} - -// MixColumns function mixes the columns of the state matrix -static void MixColumns(void) -{ - uint8_t i; - uint8_t Tmp,Tm,t; - for (i = 0; i < 4; ++i) - { - t = (*state)[i][0]; - Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; - Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; - Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; - Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; - Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; - } -} - -// Multiply is used to multiply numbers in the field GF(2^8) -#if MULTIPLY_AS_A_FUNCTION -static uint8_t Multiply(uint8_t x, uint8_t y) -{ - return (((y & 1) * x) ^ - ((y>>1 & 1) * xtime(x)) ^ - ((y>>2 & 1) * xtime(xtime(x))) ^ - ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ - ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); - } -#else -#define Multiply(x, y) (uint8_t) \ - ( ((y & 1) * x) ^ \ - ((y>>1 & 1) * xtime(x)) ^ \ - ((y>>2 & 1) * xtime(xtime(x))) ^ \ - ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ - ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ - -#endif - -// MixColumns function mixes the columns of the state matrix. -// The method used to multiply may be difficult to understand for the inexperienced. -// Please use the references to gain more information. -static void InvMixColumns(void) -{ - int i; - uint8_t a, b, c, d; - for (i = 0; i < 4; ++i) - { - a = (*state)[i][0]; - b = (*state)[i][1]; - c = (*state)[i][2]; - d = (*state)[i][3]; - - (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); - (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); - (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); - (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); - } -} - - -// The SubBytes Function Substitutes the values in the -// state matrix with values in an S-box. -static void InvSubBytes(void) -{ - uint8_t i,j; - for (i = 0; i < 4; ++i) - { - for (j = 0; j < 4; ++j) - { - (*state)[j][i] = getSBoxInvert((*state)[j][i]); - } - } -} - -static void InvShiftRows(void) -{ - uint8_t temp; - - // Rotate first row 1 columns to right - temp = (*state)[3][1]; - (*state)[3][1] = (*state)[2][1]; - (*state)[2][1] = (*state)[1][1]; - (*state)[1][1] = (*state)[0][1]; - (*state)[0][1] = temp; - - // Rotate second row 2 columns to right - temp = (*state)[0][2]; - (*state)[0][2] = (*state)[2][2]; - (*state)[2][2] = temp; - - temp = (*state)[1][2]; - (*state)[1][2] = (*state)[3][2]; - (*state)[3][2] = temp; - - // Rotate third row 3 columns to right - temp = (*state)[0][3]; - (*state)[0][3] = (*state)[1][3]; - (*state)[1][3] = (*state)[2][3]; - (*state)[2][3] = (*state)[3][3]; - (*state)[3][3] = temp; -} - - -// Cipher is the main function that encrypts the PlainText. -static void Cipher(void) -{ - uint8_t round = 0; - - // Add the First round key to the state before starting the rounds. - AddRoundKey(0); - - // There will be Nr rounds. - // The first Nr-1 rounds are identical. - // These Nr-1 rounds are executed in the loop below. - for (round = 1; round < Nr; ++round) - { - SubBytes(); - ShiftRows(); - MixColumns(); - AddRoundKey(round); - } - - // The last round is given below. - // The MixColumns function is not here in the last round. - SubBytes(); - ShiftRows(); - AddRoundKey(Nr); -} - -static void InvCipher(void) -{ - uint8_t round=0; - - // Add the First round key to the state before starting the rounds. - AddRoundKey(Nr); - - // There will be Nr rounds. - // The first Nr-1 rounds are identical. - // These Nr-1 rounds are executed in the loop below. - for (round = (Nr - 1); round > 0; --round) - { - InvShiftRows(); - InvSubBytes(); - AddRoundKey(round); - InvMixColumns(); - } - - // The last round is given below. - // The MixColumns function is not here in the last round. - InvShiftRows(); - InvSubBytes(); - AddRoundKey(0); -} - - -/*****************************************************************************/ -/* Public functions: */ -/*****************************************************************************/ -#if defined(AES_ECB) && (AES_ECB == 1) - - -void AES_ECB_encrypt(uint8_t *output, const uint8_t *input, const uint32_t length, const uint8_t *key) -{ - // Copy input to output, and work in-memory on output - memcpy(output, input, length); - state = (state_t*)output; - - Key = key; - KeyExpansion(); - - // The next function call encrypts the PlainText with the Key using AES algorithm. - Cipher(); - - mpw_zero( RoundKey, keyExpSize ); -} - -void AES_ECB_decrypt(uint8_t *output, const uint8_t *input, const uint32_t length, const uint8_t *key) -{ - // Copy input to output, and work in-memory on output - memcpy(output, input, length); - state = (state_t*)output; - - // The KeyExpansion routine must be called before encryption. - Key = key; - KeyExpansion(); - - InvCipher(); - - mpw_zero( RoundKey, keyExpSize ); -} - - -#endif // #if defined(AES_ECB) && (AES_ECB == 1) - - - - - -#if defined(AES_CBC) && (AES_CBC == 1) - - -static void XorWithIv(uint8_t* buf) -{ - uint8_t i; - for (i = 0; i < AES_BLOCKLEN; ++i) //WAS for(i = 0; i < KEYLEN; ++i) but the block in AES is always 128bit so 16 bytes! - { - buf[i] ^= Iv[i]; - } -} - -void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv) -{ - uintptr_t i; - uint8_t extra = (uint8_t)(length % AES_BLOCKLEN); /* Remaining bytes in the last non-full block */ - - // Skip the key expansion if key is passed as 0 - if (0 != key) - { - Key = key; - KeyExpansion(); - } - - if (iv != 0) - { - Iv = (uint8_t*)iv; - } - - for (i = 0; i < length; i += AES_BLOCKLEN) - { - XorWithIv(input); - memcpy(output, input, AES_BLOCKLEN); - state = (state_t*)output; - Cipher(); - Iv = output; - input += AES_BLOCKLEN; - output += AES_BLOCKLEN; - //printf("Step %d - %d", i/16, i); - } - - if (extra) - { - memcpy(output, input, extra); - state = (state_t*)output; - Cipher(); - } - - mpw_zero( RoundKey, keyExpSize ); -} - -void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv) -{ - uintptr_t i; - uint8_t extra = (uint8_t)(length % AES_BLOCKLEN); /* Remaining bytes in the last non-full block */ - - // Skip the key expansion if key is passed as 0 - if (0 != key) - { - Key = key; - KeyExpansion(); - } - - // If iv is passed as 0, we continue to encrypt without re-setting the Iv - if (iv != 0) - { - Iv = (uint8_t*)iv; - } - - for (i = 0; i < length; i += AES_BLOCKLEN) - { - memcpy(output, input, AES_BLOCKLEN); - state = (state_t*)output; - InvCipher(); - XorWithIv(output); - Iv = input; - input += AES_BLOCKLEN; - output += AES_BLOCKLEN; - } - - if (extra) - { - memcpy(output, input, extra); - state = (state_t*)output; - InvCipher(); - } - - mpw_zero( RoundKey, keyExpSize ); -} - -#endif // #if defined(AES_CBC) && (AES_CBC == 1) diff --git a/core/c/aes.h b/core/c/aes.h deleted file mode 100644 index 462302b1..00000000 --- a/core/c/aes.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - -Source: https://github.com/kokke/tiny-AES-c - -This is an implementation of the AES algorithm, specifically ECB and CBC mode. - -*/ - -#ifndef _AES_H_ -#define _AES_H_ - -#include - - -// #define the macros below to 1/0 to enable/disable the mode of operation. -// -// AES_CBC enables AES encryption in CBC-mode of operation. -// AES_ECB enables the basic ECB 16-byte block algorithm. Both can be enabled simultaneously. - -// The #ifndef-guard allows it to be configured before #include'ing or at compile time. -#ifndef AES_CBC - #define AES_CBC 1 -#endif - -#ifndef AES_ECB - #define AES_ECB 1 -#endif - -#define AES_128 1 -//#define AES_192 1 -//#define AES_256 1 -#define AES_BLOCKLEN 16 //Block length in bytes AES is 128b block only - -#if defined(AES_ECB) && (AES_ECB == 1) - -void AES_ECB_encrypt(uint8_t *output, const uint8_t *input, const uint32_t length, const uint8_t *key); -void AES_ECB_decrypt(uint8_t *output, const uint8_t *input, const uint32_t length, const uint8_t *key); - -#endif // #if defined(AES_ECB) && (AES_ECB == !) - - -#if defined(AES_CBC) && (AES_CBC == 1) - -void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, const uint32_t length, const uint8_t* key, const uint8_t* iv); -void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, const uint32_t length, const uint8_t* key, const uint8_t* iv); - -#endif // #if defined(AES_CBC) && (AES_CBC == 1) - - -#endif //_AES_H_ diff --git a/core/c/base64.c b/core/c/base64.c deleted file mode 100644 index 5ec59496..00000000 --- a/core/c/base64.c +++ /dev/null @@ -1,155 +0,0 @@ -/* ==================================================================== -* Copyright (c) 1995-1999 The Apache Group. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* -* 3. All advertising materials mentioning features or use of this -* software must display the following acknowledgment: -* "This product includes software developed by the Apache Group -* for use in the Apache HTTP server project (http://www.apache.org/)." -* -* 4. The names "Apache Server" and "Apache Group" must not be used to -* endorse or promote products derived from this software without -* prior written permission. For written permission, please contact -* apache@apache.org. -* -* 5. Products derived from this software may not be called "Apache" -* nor may "Apache" appear in their names without prior written -* permission of the Apache Group. -* -* 6. Redistributions of any form whatsoever must retain the following -* acknowledgment: -* "This product includes software developed by the Apache Group -* for use in the Apache HTTP server project (http://www.apache.org/)." -* -* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY -* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR -* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -* OF THE POSSIBILITY OF SUCH DAMAGE. -* ==================================================================== -* -* This software consists of voluntary contributions made by many -* individuals on behalf of the Apache Group and was originally based -* on public domain software written at the National Center for -* Supercomputing Applications, University of Illinois, Urbana-Champaign. -* For more information on the Apache Group and the Apache HTTP server -* project, please see . -*/ - -#include "base64.h" - -/* aaaack but it's fast and const should make it shared text page. */ -static const uint8_t b64ToBits[256] = - { - /* ASCII table */ - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, - 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, - 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 - }; - -size_t mpw_base64_decode_max(const char *b64Text) { - - register const uint8_t *b64Cursor = (uint8_t *)b64Text; - while (b64ToBits[*(b64Cursor++)] <= 63); - int b64Size = (int)(b64Cursor - (uint8_t *)b64Text) - 1; - - // Every 4 b64 chars yield 3 plain bytes => len = 3 * ceil(b64Size / 4) - return (size_t)(3 /*bytes*/ * ((b64Size + 4 /*chars*/ - 1) / 4 /*chars*/)); -} - -int mpw_base64_decode(uint8_t *plainBuf, const char *b64Text) { - - register const uint8_t *b64Cursor = (uint8_t *)b64Text; - while (b64ToBits[*(b64Cursor++)] <= 63); - int b64Remaining = (int)(b64Cursor - (uint8_t *)b64Text) - 1; - - b64Cursor = (uint8_t *)b64Text; - register uint8_t *plainCursor = plainBuf; - while (b64Remaining > 4) { - *(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[0]] << 2 | b64ToBits[b64Cursor[1]] >> 4); - *(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[1]] << 4 | b64ToBits[b64Cursor[2]] >> 2); - *(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[2]] << 6 | b64ToBits[b64Cursor[3]]); - b64Cursor += 4; - b64Remaining -= 4; - } - - /* Note: (b64Size == 1) would be an error, so just ingore that case */ - if (b64Remaining > 1) - *(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[0]] << 2 | b64ToBits[b64Cursor[1]] >> 4); - if (b64Remaining > 2) - *(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[1]] << 4 | b64ToBits[b64Cursor[2]] >> 2); - if (b64Remaining > 3) - *(plainCursor++) = (uint8_t)(b64ToBits[b64Cursor[2]] << 6 | b64ToBits[b64Cursor[3]]); - - return (int)(plainCursor - plainBuf); -} - -static const char basis_64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -size_t mpw_base64_encode_max(size_t plainSize) { - - // Every 3 plain bytes yield 4 b64 chars => len = 4 * ceil(plainSize / 3) - return 4 /*chars*/ * (plainSize + 3 /*bytes*/ - 1) / 3 /*bytes*/; -} - -int mpw_base64_encode(char *b64Text, const uint8_t *plainBuf, size_t plainSize) { - - size_t plainCursor = 0; - char *b64Cursor = b64Text; - for (; plainCursor < plainSize - 2; plainCursor += 3) { - *b64Cursor++ = basis_64[((plainBuf[plainCursor] >> 2)) & 0x3F]; - *b64Cursor++ = basis_64[((plainBuf[plainCursor] & 0x3) << 4) | - ((plainBuf[plainCursor + 1] & 0xF0) >> 4)]; - *b64Cursor++ = basis_64[((plainBuf[plainCursor + 1] & 0xF) << 2) | - ((plainBuf[plainCursor + 2] & 0xC0) >> 6)]; - *b64Cursor++ = basis_64[plainBuf[plainCursor + 2] & 0x3F]; - } - if (plainCursor < plainSize) { - *b64Cursor++ = basis_64[(plainBuf[plainCursor] >> 2) & 0x3F]; - if (plainCursor == (plainSize - 1)) { - *b64Cursor++ = basis_64[((plainBuf[plainCursor] & 0x3) << 4)]; - *b64Cursor++ = '='; - } - else { - *b64Cursor++ = basis_64[((plainBuf[plainCursor] & 0x3) << 4) | - ((plainBuf[plainCursor + 1] & 0xF0) >> 4)]; - *b64Cursor++ = basis_64[((plainBuf[plainCursor + 1] & 0xF) << 2)]; - } - *b64Cursor++ = '='; - } - - *b64Cursor = '\0'; - return (int)(b64Cursor - b64Text); -} diff --git a/core/c/base64.h b/core/c/base64.h deleted file mode 100644 index fdbfc58a..00000000 --- a/core/c/base64.h +++ /dev/null @@ -1,78 +0,0 @@ -/* ==================================================================== -* Copyright (c) 1995-1999 The Apache Group. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* -* 3. All advertising materials mentioning features or use of this -* software must display the following acknowledgment: -* "This product includes software developed by the Apache Group -* for use in the Apache HTTP server project (http://www.apache.org/)." -* -* 4. The names "Apache Server" and "Apache Group" must not be used to -* endorse or promote products derived from this software without -* prior written permission. For written permission, please contact -* apache@apache.org. -* -* 5. Products derived from this software may not be called "Apache" -* nor may "Apache" appear in their names without prior written -* permission of the Apache Group. -* -* 6. Redistributions of any form whatsoever must retain the following -* acknowledgment: -* "This product includes software developed by the Apache Group -* for use in the Apache HTTP server project (http://www.apache.org/)." -* -* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY -* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR -* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -* OF THE POSSIBILITY OF SUCH DAMAGE. -* ==================================================================== -* -* This software consists of voluntary contributions made by many -* individuals on behalf of the Apache Group and was originally based -* on public domain software written at the National Center for -* Supercomputing Applications, University of Illinois, Urbana-Champaign. -* For more information on the Apache Group and the Apache HTTP server -* project, please see . -*/ - -#include -#include - -/** - * @return The amount of bytes needed to decode the given b64Text. - */ -size_t mpw_base64_decode_max(const char *b64Text); -/** Decodes a base-64 encoded string into a plain byte buffer. - * @param plainBuf a byte buffer, size should be at least mpw_base64_decode_max(b64Text) - * @return The amount of bytes that were written to plainBuf. - */ -int mpw_base64_decode(uint8_t *plainBuf, const char *b64Text); - -/** - * @return The amount of characters needed to encode a plainBuf of the given size as base-64 (excluding the terminating NUL). - */ -size_t mpw_base64_encode_max(size_t plainSize); -/** Encodes a plain byte buffer into a base-64 encoded string. - * @param b64Text a character buffer, size should be at least mpw_base64_encode_max(plainSize) + 1 - * @return The amount of characters that were written to b64Text, excluding the terminating NUL. - */ -int mpw_base64_encode(char *b64Text, const uint8_t *plainBuf, size_t plainSize); diff --git a/core/c/mpw-algorithm.c b/core/c/mpw-algorithm.c deleted file mode 100644 index 6a730142..00000000 --- a/core/c/mpw-algorithm.c +++ /dev/null @@ -1,226 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#include "mpw-algorithm.h" -#include "mpw-algorithm_v0.c" -#include "mpw-algorithm_v1.c" -#include "mpw-algorithm_v2.c" -#include "mpw-algorithm_v3.c" - -MPMasterKey mpw_masterKey(const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) { - - if (fullName && !strlen( fullName )) - fullName = NULL; - if (masterPassword && !strlen( masterPassword )) - masterPassword = NULL; - - trc( "-- mpw_masterKey (algorithm: %u)", algorithmVersion ); - trc( "fullName: %s", fullName ); - trc( "masterPassword.id: %s", masterPassword? mpw_id_buf( masterPassword, strlen( masterPassword ) ): NULL ); - if (!fullName || !masterPassword) - return NULL; - - switch (algorithmVersion) { - case MPAlgorithmVersion0: - return mpw_masterKey_v0( fullName, masterPassword ); - case MPAlgorithmVersion1: - return mpw_masterKey_v1( fullName, masterPassword ); - case MPAlgorithmVersion2: - return mpw_masterKey_v2( fullName, masterPassword ); - case MPAlgorithmVersion3: - return mpw_masterKey_v3( fullName, masterPassword ); - default: - err( "Unsupported version: %d", algorithmVersion ); - return NULL; - } -} - -MPSiteKey mpw_siteKey( - MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter, - const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion) { - - if (keyContext && !strlen( keyContext )) - keyContext = NULL; - - trc( "-- mpw_siteKey (algorithm: %u)", algorithmVersion ); - trc( "siteName: %s", siteName ); - trc( "siteCounter: %d", siteCounter ); - trc( "keyPurpose: %d (%s)", keyPurpose, mpw_nameForPurpose( keyPurpose ) ); - trc( "keyContext: %s", keyContext ); - if (!masterKey || !siteName) - return NULL; - - switch (algorithmVersion) { - case MPAlgorithmVersion0: - return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext ); - case MPAlgorithmVersion1: - return mpw_siteKey_v1( masterKey, siteName, siteCounter, keyPurpose, keyContext ); - case MPAlgorithmVersion2: - return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext ); - case MPAlgorithmVersion3: - return mpw_siteKey_v3( masterKey, siteName, siteCounter, keyPurpose, keyContext ); - default: - err( "Unsupported version: %d", algorithmVersion ); - return NULL; - } -} - -const char *mpw_siteResult( - MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter, - const MPKeyPurpose keyPurpose, const char *keyContext, - const MPResultType resultType, const char *resultParam, - const MPAlgorithmVersion algorithmVersion) { - - if (keyContext && !strlen( keyContext )) - keyContext = NULL; - if (resultParam && !strlen( resultParam )) - resultParam = NULL; - - MPSiteKey siteKey = mpw_siteKey( masterKey, siteName, siteCounter, keyPurpose, keyContext, algorithmVersion ); - if (!siteKey) - return NULL; - - trc( "-- mpw_siteResult (algorithm: %u)", algorithmVersion ); - trc( "resultType: %d (%s)", resultType, mpw_nameForType( resultType ) ); - trc( "resultParam: %s", resultParam ); - - char *sitePassword = NULL; - if (resultType & MPResultTypeClassTemplate) { - switch (algorithmVersion) { - case MPAlgorithmVersion0: - return mpw_sitePasswordFromTemplate_v0( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion1: - return mpw_sitePasswordFromTemplate_v1( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion2: - return mpw_sitePasswordFromTemplate_v2( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion3: - return mpw_sitePasswordFromTemplate_v3( masterKey, siteKey, resultType, resultParam ); - default: - err( "Unsupported version: %d", algorithmVersion ); - return NULL; - } - } - else if (resultType & MPResultTypeClassStateful) { - switch (algorithmVersion) { - case MPAlgorithmVersion0: - return mpw_sitePasswordFromCrypt_v0( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion1: - return mpw_sitePasswordFromCrypt_v1( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion2: - return mpw_sitePasswordFromCrypt_v2( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion3: - return mpw_sitePasswordFromCrypt_v3( masterKey, siteKey, resultType, resultParam ); - default: - err( "Unsupported version: %d", algorithmVersion ); - return NULL; - } - } - else if (resultType & MPResultTypeClassDerive) { - switch (algorithmVersion) { - case MPAlgorithmVersion0: - return mpw_sitePasswordFromDerive_v0( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion1: - return mpw_sitePasswordFromDerive_v1( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion2: - return mpw_sitePasswordFromDerive_v2( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion3: - return mpw_sitePasswordFromDerive_v3( masterKey, siteKey, resultType, resultParam ); - default: - err( "Unsupported version: %d", algorithmVersion ); - return NULL; - } - } - else { - err( "Unsupported password type: %d", resultType ); - } - - return sitePassword; -} - -const char *mpw_siteState( - MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter, - const MPKeyPurpose keyPurpose, const char *keyContext, - const MPResultType resultType, const char *resultParam, - const MPAlgorithmVersion algorithmVersion) { - - if (keyContext && !strlen( keyContext )) - keyContext = NULL; - if (resultParam && !strlen( resultParam )) - resultParam = NULL; - - MPSiteKey siteKey = mpw_siteKey( masterKey, siteName, siteCounter, keyPurpose, keyContext, algorithmVersion ); - if (!siteKey) - return NULL; - - trc( "-- mpw_siteState (algorithm: %u)", algorithmVersion ); - trc( "resultType: %d (%s)", resultType, mpw_nameForType( resultType ) ); - trc( "resultParam: %zu bytes = %s", sizeof( resultParam ), resultParam ); - if (!masterKey || !resultParam) - return NULL; - - switch (algorithmVersion) { - case MPAlgorithmVersion0: - return mpw_siteState_v0( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion1: - return mpw_siteState_v1( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion2: - return mpw_siteState_v2( masterKey, siteKey, resultType, resultParam ); - case MPAlgorithmVersion3: - return mpw_siteState_v3( masterKey, siteKey, resultType, resultParam ); - default: - err( "Unsupported version: %d", algorithmVersion ); - return NULL; - } -} - -MPIdenticon mpw_identicon(const char *fullName, const char *masterPassword) { - - const char *leftArm[] = { "╔", "╚", "╰", "═" }; - const char *rightArm[] = { "╗", "╝", "╯", "═" }; - const char *body[] = { "█", "░", "▒", "▓", "☺", "☻" }; - const char *accessory[] = { - "◈", "◎", "◐", "◑", "◒", "◓", "☀", "☁", "☂", "☃", "", "★", "☆", "☎", "☏", "⎈", "⌂", "☘", "☢", "☣", - "☕", "⌚", "⌛", "⏰", "⚡", "⛄", "⛅", "☔", "♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛", "♜", "♝", "♞", "♟", - "♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌" - }; - - const uint8_t *identiconSeed = NULL; - if (fullName && strlen( fullName ) && masterPassword && strlen( masterPassword )) - identiconSeed = mpw_hash_hmac_sha256( - (const uint8_t *)masterPassword, strlen( masterPassword ), - (const uint8_t *)fullName, strlen( fullName ) ); - if (!identiconSeed) - return (MPIdenticon){ - .leftArm = "", - .body = "", - .rightArm = "", - .accessory = "", - .color=0, - }; - - MPIdenticon identicon = { - .leftArm = leftArm[identiconSeed[0] % (sizeof( leftArm ) / sizeof( leftArm[0] ))], - .body = body[identiconSeed[1] % (sizeof( body ) / sizeof( body[0] ))], - .rightArm = rightArm[identiconSeed[2] % (sizeof( rightArm ) / sizeof( rightArm[0] ))], - .accessory = accessory[identiconSeed[3] % (sizeof( accessory ) / sizeof( accessory[0] ))], - .color = (uint8_t)(identiconSeed[4] % (MPIdenticonColorLast - MPIdenticonColorFirst + 1) + MPIdenticonColorFirst), - }; - mpw_free( &identiconSeed, 32 ); - - return identicon; -} diff --git a/core/c/mpw-algorithm.h b/core/c/mpw-algorithm.h deleted file mode 100644 index 3cf8d702..00000000 --- a/core/c/mpw-algorithm.h +++ /dev/null @@ -1,72 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -// NOTE: mpw is currently NOT thread-safe. -#include "mpw-types.h" - -#ifndef _MPW_ALGORITHM_H -#define _MPW_ALGORITHM_H - -typedef mpw_enum( unsigned int, MPAlgorithmVersion ) { - /** V0 did math with chars whose signedness was platform-dependent. */ - MPAlgorithmVersion0, - /** V1 miscounted the byte-length of multi-byte site names. */ - MPAlgorithmVersion1, - /** V2 miscounted the byte-length of multi-byte user names. */ - MPAlgorithmVersion2, - /** V3 is the current version. */ - MPAlgorithmVersion3, - - MPAlgorithmVersionCurrent = MPAlgorithmVersion3, - MPAlgorithmVersionFirst = MPAlgorithmVersion0, - MPAlgorithmVersionLast = MPAlgorithmVersion3, -}; - -/** Derive the master key for a user based on their name and master password. - * @return A new MPMasterKeySize-byte allocated buffer or NULL if an error occurred. */ -MPMasterKey mpw_masterKey( - const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion); - -/** Derive the site key for a user's site from the given master key and site parameters. - * @return A new MPSiteKeySize-byte allocated buffer or NULL if an error occurred. */ -MPSiteKey mpw_siteKey( - MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter, - const MPKeyPurpose keyPurpose, const char *keyContext, const MPAlgorithmVersion algorithmVersion); - -/** Generate a site result token from the given parameters. - * @param resultParam A parameter for the resultType. For stateful result types, the output of mpw_siteState. - * @return A newly allocated string or NULL if an error occurred. */ -const char *mpw_siteResult( - MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter, - const MPKeyPurpose keyPurpose, const char *keyContext, - const MPResultType resultType, const char *resultParam, - const MPAlgorithmVersion algorithmVersion); - -/** Encrypt a stateful site token for persistence. - * @param resultParam A parameter for the resultType. For stateful result types, the desired mpw_siteResult. - * @return A newly allocated string or NULL if an error occurred. */ -const char *mpw_siteState( - MPMasterKey masterKey, const char *siteName, const MPCounterValue siteCounter, - const MPKeyPurpose keyPurpose, const char *keyContext, - const MPResultType resultType, const char *resultParam, - const MPAlgorithmVersion algorithmVersion); - -/** @return A fingerprint for a user. */ -MPIdenticon mpw_identicon(const char *fullName, const char *masterPassword); - -#endif // _MPW_ALGORITHM_H diff --git a/core/c/mpw-algorithm_v0.c b/core/c/mpw-algorithm_v0.c deleted file mode 100644 index b1f237d3..00000000 --- a/core/c/mpw-algorithm_v0.c +++ /dev/null @@ -1,257 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#include -#include -#include - -#include "mpw-util.h" -#include "base64.h" - -#define MP_N 32768LU -#define MP_r 8U -#define MP_p 2U -#define MP_otp_window 5 * 60 /* s */ - -// Algorithm version helpers. -static const char *mpw_templateForType_v0(MPResultType type, uint16_t templateIndex) { - - size_t count = 0; - const char **templates = mpw_templatesForType( type, &count ); - char const *template = templates && count? templates[templateIndex % count]: NULL; - free( templates ); - return template; -} - -static const char mpw_characterFromClass_v0(char characterClass, uint16_t classIndex) { - - const char *classCharacters = mpw_charactersInClass( characterClass ); - if (!classCharacters) - return '\0'; - - return classCharacters[classIndex % strlen( classCharacters )]; -} - -// Algorithm version overrides. -static MPMasterKey mpw_masterKey_v0( - const char *fullName, const char *masterPassword) { - - const char *keyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication ); - trc( "keyScope: %s", keyScope ); - - // Calculate the master key salt. - trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s", - keyScope, mpw_hex_l( (uint32_t)mpw_utf8_strlen( fullName ) ), fullName ); - size_t masterKeySaltSize = 0; - uint8_t *masterKeySalt = NULL; - mpw_push_string( &masterKeySalt, &masterKeySaltSize, keyScope ); - mpw_push_int( &masterKeySalt, &masterKeySaltSize, (uint32_t)mpw_utf8_strlen( fullName ) ); - mpw_push_string( &masterKeySalt, &masterKeySaltSize, fullName ); - if (!masterKeySalt) { - err( "Could not allocate master key salt: %s", strerror( errno ) ); - return NULL; - } - trc( " => masterKeySalt.id: %s", mpw_id_buf( masterKeySalt, masterKeySaltSize ) ); - - // Calculate the master key. - trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )", MP_N, MP_r, MP_p ); - MPMasterKey masterKey = mpw_kdf_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); - mpw_free( &masterKeySalt, masterKeySaltSize ); - if (!masterKey) { - err( "Could not derive master key: %s", strerror( errno ) ); - return NULL; - } - trc( " => masterKey.id: %s", mpw_id_buf( masterKey, MPMasterKeySize ) ); - - return masterKey; -} - -static MPSiteKey mpw_siteKey_v0( - MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter, - MPKeyPurpose keyPurpose, const char *keyContext) { - - const char *keyScope = mpw_scopeForPurpose( keyPurpose ); - trc( "keyScope: %s", keyScope ); - - // OTP counter value. - if (siteCounter == MPCounterValueTOTP) - siteCounter = ((uint32_t)time( NULL ) / MP_otp_window) * MP_otp_window; - - // Calculate the site seed. - trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s", - keyScope, mpw_hex_l( (uint32_t)mpw_utf8_strlen( siteName ) ), siteName, mpw_hex_l( siteCounter ), - keyContext? mpw_hex_l( (uint32_t)mpw_utf8_strlen( keyContext ) ): NULL, keyContext ); - size_t siteSaltSize = 0; - uint8_t *siteSalt = NULL; - mpw_push_string( &siteSalt, &siteSaltSize, keyScope ); - mpw_push_int( &siteSalt, &siteSaltSize, (uint32_t)mpw_utf8_strlen( siteName ) ); - mpw_push_string( &siteSalt, &siteSaltSize, siteName ); - mpw_push_int( &siteSalt, &siteSaltSize, siteCounter ); - if (keyContext) { - mpw_push_int( &siteSalt, &siteSaltSize, (uint32_t)mpw_utf8_strlen( keyContext ) ); - mpw_push_string( &siteSalt, &siteSaltSize, keyContext ); - } - if (!siteSalt) { - err( "Could not allocate site salt: %s", strerror( errno ) ); - return NULL; - } - trc( " => siteSalt.id: %s", mpw_id_buf( siteSalt, siteSaltSize ) ); - - trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )", - mpw_id_buf( masterKey, MPMasterKeySize ) ); - MPSiteKey siteKey = mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); - mpw_free( &siteSalt, siteSaltSize ); - if (!siteKey) { - err( "Could not derive site key: %s", strerror( errno ) ); - return NULL; - } - trc( " => siteKey.id: %s", mpw_id_buf( siteKey, MPSiteKeySize ) ); - - return siteKey; -} - -static const char *mpw_sitePasswordFromTemplate_v0( - MPMasterKey __unused masterKey, MPSiteKey siteKey, MPResultType resultType, const char __unused *resultParam) { - - const char *_siteKey = (const char *)siteKey; - - // Determine the template. - uint16_t seedByte; - mpw_uint16( (uint16_t)_siteKey[0], (uint8_t *)&seedByte ); - const char *template = mpw_templateForType_v0( resultType, seedByte ); - trc( "template: %u => %s", seedByte, template ); - if (!template) - return NULL; - if (strlen( template ) > MPSiteKeySize) { - err( "Template too long for password seed: %zu", strlen( template ) ); - return NULL; - } - - // Encode the password from the seed using the template. - char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) ); - for (size_t c = 0; c < strlen( template ); ++c) { - mpw_uint16( (uint16_t)_siteKey[c + 1], (uint8_t *)&seedByte ); - sitePassword[c] = mpw_characterFromClass_v0( template[c], seedByte ); - trc( " - class: %c, index: %5u (0x%02hX) => character: %c", - template[c], seedByte, seedByte, sitePassword[c] ); - } - trc( " => password: %s", sitePassword ); - - return sitePassword; -} - -static const char *mpw_sitePasswordFromCrypt_v0( - MPMasterKey masterKey, MPSiteKey __unused siteKey, MPResultType __unused resultType, const char *cipherText) { - - if (!cipherText) { - err( "Missing encrypted state." ); - return NULL; - } - - // Base64-decode - uint8_t *cipherBuf = calloc( 1, mpw_base64_decode_max( cipherText ) ); - size_t bufSize = (size_t)mpw_base64_decode( cipherBuf, cipherText ), cipherBufSize = bufSize; - if ((int)bufSize < 0) { - err( "Base64 decoding error." ); - mpw_free( &cipherBuf, mpw_base64_decode_max( cipherText ) ); - return NULL; - } - trc( "b64 decoded: %zu bytes = %s", bufSize, mpw_hex( cipherBuf, bufSize ) ); - - // Decrypt - const uint8_t *plainBytes = mpw_aes_decrypt( masterKey, MPMasterKeySize, cipherBuf, &bufSize ); - mpw_free( &cipherBuf, cipherBufSize ); - const char *plainText = mpw_strndup( (char *)plainBytes, bufSize ); - mpw_free( &plainBytes, bufSize ); - if (!plainText) - err( "AES decryption error: %s", strerror( errno ) ); - trc( "decrypted -> plainText: %zu bytes = %s = %s", strlen( plainText ), plainText, mpw_hex( plainText, strlen( plainText ) ) ); - - return plainText; -} - -static const char *mpw_sitePasswordFromDerive_v0( - MPMasterKey __unused masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) { - - switch (resultType) { - case MPResultTypeDeriveKey: { - if (!resultParam) { - err( "Missing key size parameter." ); - return NULL; - } - int resultParamInt = atoi( resultParam ); - if (!resultParamInt) - resultParamInt = 512; - if (resultParamInt < 128 || resultParamInt > 512 || resultParamInt % 8 != 0) { - err( "Parameter is not a valid key size (should be 128 - 512): %s", resultParam ); - return NULL; - } - uint16_t keySize = (uint16_t)(resultParamInt / 8); - trc( "keySize: %u", keySize ); - - // Derive key - const uint8_t *resultKey = mpw_kdf_blake2b( keySize, siteKey, MPSiteKeySize, NULL, 0, 0, NULL ); - if (!resultKey) { - err( "Could not derive result key: %s", strerror( errno ) ); - return NULL; - } - - // Base64-encode - size_t b64Max = mpw_base64_encode_max( keySize ); - char *b64Key = calloc( 1, b64Max + 1 ); - if (mpw_base64_encode( b64Key, resultKey, keySize ) < 0) { - err( "Base64 encoding error." ); - mpw_free_string( &b64Key ); - } - else - trc( "b64 encoded -> key: %s", b64Key ); - mpw_free( &resultKey, keySize ); - - return b64Key; - } - default: - err( "Unsupported derived password type: %d", resultType ); - return NULL; - } -} - -static const char *mpw_siteState_v0( - MPMasterKey masterKey, MPSiteKey __unused siteKey, MPResultType __unused resultType, const char *plainText) { - - // Encrypt - size_t bufSize = strlen( plainText ); - const uint8_t *cipherBuf = mpw_aes_encrypt( masterKey, MPMasterKeySize, (const uint8_t *)plainText, &bufSize ); - if (!cipherBuf) { - err( "AES encryption error: %s", strerror( errno ) ); - return NULL; - } - trc( "cipherBuf: %zu bytes = %s", bufSize, mpw_hex( cipherBuf, bufSize ) ); - - // Base64-encode - size_t b64Max = mpw_base64_encode_max( bufSize ); - char *cipherText = calloc( 1, b64Max + 1 ); - if (mpw_base64_encode( cipherText, cipherBuf, bufSize ) < 0) { - err( "Base64 encoding error." ); - mpw_free_string( &cipherText ); - } - else - trc( "b64 encoded -> cipherText: %s", cipherText ); - mpw_free( &cipherBuf, bufSize ); - - return cipherText; -} diff --git a/core/c/mpw-algorithm_v1.c b/core/c/mpw-algorithm_v1.c deleted file mode 100644 index 3a4a4bce..00000000 --- a/core/c/mpw-algorithm_v1.c +++ /dev/null @@ -1,98 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#include - -#include "mpw-util.h" - -#define MP_N 32768LU -#define MP_r 8U -#define MP_p 2U -#define MP_otp_window 5 * 60 /* s */ - -// Inherited functions. -MPMasterKey mpw_masterKey_v0( - const char *fullName, const char *masterPassword); -MPSiteKey mpw_siteKey_v0( - MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter, - MPKeyPurpose keyPurpose, const char *keyContext); -const char *mpw_sitePasswordFromCrypt_v0( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText); -const char *mpw_sitePasswordFromDerive_v0( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam); -const char *mpw_siteState_v0( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state); - -// Algorithm version overrides. -static MPMasterKey mpw_masterKey_v1( - const char *fullName, const char *masterPassword) { - - return mpw_masterKey_v0( fullName, masterPassword ); -} - -static MPSiteKey mpw_siteKey_v1( - MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter, - MPKeyPurpose keyPurpose, const char *keyContext) { - - return mpw_siteKey_v0( masterKey, siteName, siteCounter, keyPurpose, keyContext ); -} - -static const char *mpw_sitePasswordFromTemplate_v1( - MPMasterKey __unused masterKey, MPSiteKey siteKey, MPResultType resultType, const char __unused *resultParam) { - - // Determine the template. - uint8_t seedByte = siteKey[0]; - const char *template = mpw_templateForType( resultType, seedByte ); - trc( "template: %u => %s", seedByte, template ); - if (!template) - return NULL; - if (strlen( template ) > MPSiteKeySize) { - err( "Template too long for password seed: %zu", strlen( template ) ); - return NULL; - } - - // Encode the password from the seed using the template. - char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) ); - for (size_t c = 0; c < strlen( template ); ++c) { - seedByte = siteKey[c + 1]; - sitePassword[c] = mpw_characterFromClass( template[c], seedByte ); - trc( " - class: %c, index: %3u (0x%02hhX) => character: %c", - template[c], seedByte, seedByte, sitePassword[c] ); - } - trc( " => password: %s", sitePassword ); - - return sitePassword; -} - -static const char *mpw_sitePasswordFromCrypt_v1( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText) { - - return mpw_sitePasswordFromCrypt_v0( masterKey, siteKey, resultType, cipherText ); -} - -static const char *mpw_sitePasswordFromDerive_v1( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) { - - return mpw_sitePasswordFromDerive_v0( masterKey, siteKey, resultType, resultParam ); -} - -static const char *mpw_siteState_v1( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state) { - - return mpw_siteState_v0( masterKey, siteKey, resultType, state ); -} diff --git a/core/c/mpw-algorithm_v2.c b/core/c/mpw-algorithm_v2.c deleted file mode 100644 index a6b3d44f..00000000 --- a/core/c/mpw-algorithm_v2.c +++ /dev/null @@ -1,115 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#include -#include -#include - -#include "mpw-util.h" - -#define MP_N 32768LU -#define MP_r 8U -#define MP_p 2U -#define MP_otp_window 5 * 60 /* s */ - -// Inherited functions. -MPMasterKey mpw_masterKey_v1( - const char *fullName, const char *masterPassword); -const char *mpw_sitePasswordFromTemplate_v1( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam); -const char *mpw_sitePasswordFromCrypt_v1( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText); -const char *mpw_sitePasswordFromDerive_v1( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam); -const char *mpw_siteState_v1( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state); - -// Algorithm version overrides. -static MPMasterKey mpw_masterKey_v2( - const char *fullName, const char *masterPassword) { - - return mpw_masterKey_v1( fullName, masterPassword ); -} - -static MPSiteKey mpw_siteKey_v2( - MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter, - MPKeyPurpose keyPurpose, const char *keyContext) { - - const char *keyScope = mpw_scopeForPurpose( keyPurpose ); - trc( "keyScope: %s", keyScope ); - - // OTP counter value. - if (siteCounter == MPCounterValueTOTP) - siteCounter = ((uint32_t)time( NULL ) / MP_otp_window) * MP_otp_window; - - // Calculate the site seed. - trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s", - keyScope, mpw_hex_l( (uint32_t)strlen( siteName ) ), siteName, mpw_hex_l( siteCounter ), - keyContext? mpw_hex_l( (uint32_t)strlen( keyContext ) ): NULL, keyContext ); - size_t siteSaltSize = 0; - uint8_t *siteSalt = NULL; - mpw_push_string( &siteSalt, &siteSaltSize, keyScope ); - mpw_push_int( &siteSalt, &siteSaltSize, (uint32_t)strlen( siteName ) ); - mpw_push_string( &siteSalt, &siteSaltSize, siteName ); - mpw_push_int( &siteSalt, &siteSaltSize, siteCounter ); - if (keyContext) { - mpw_push_int( &siteSalt, &siteSaltSize, (uint32_t)strlen( keyContext ) ); - mpw_push_string( &siteSalt, &siteSaltSize, keyContext ); - } - if (!siteSalt) { - err( "Could not allocate site salt: %s", strerror( errno ) ); - return NULL; - } - trc( " => siteSalt.id: %s", mpw_id_buf( siteSalt, siteSaltSize ) ); - - trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )", - mpw_id_buf( masterKey, MPMasterKeySize ) ); - MPSiteKey siteKey = mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, siteSalt, siteSaltSize ); - mpw_free( &siteSalt, siteSaltSize ); - if (!siteKey) { - err( "Could not derive site key: %s", strerror( errno ) ); - return NULL; - } - trc( " => siteKey.id: %s", mpw_id_buf( siteKey, MPSiteKeySize ) ); - - return siteKey; -} - -static const char *mpw_sitePasswordFromTemplate_v2( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) { - - return mpw_sitePasswordFromTemplate_v1( masterKey, siteKey, resultType, resultParam ); -} - -static const char *mpw_sitePasswordFromCrypt_v2( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText) { - - return mpw_sitePasswordFromCrypt_v1( masterKey, siteKey, resultType, cipherText ); -} - -static const char *mpw_sitePasswordFromDerive_v2( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) { - - return mpw_sitePasswordFromDerive_v1( masterKey, siteKey, resultType, resultParam ); -} - -static const char *mpw_siteState_v2( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state) { - - return mpw_siteState_v1( masterKey, siteKey, resultType, state ); -} diff --git a/core/c/mpw-algorithm_v3.c b/core/c/mpw-algorithm_v3.c deleted file mode 100644 index a3caebde..00000000 --- a/core/c/mpw-algorithm_v3.c +++ /dev/null @@ -1,105 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#include -#include - -#include "mpw-util.h" - -#define MP_N 32768LU -#define MP_r 8U -#define MP_p 2U -#define MP_otp_window 5 * 60 /* s */ - -// Inherited functions. -MPSiteKey mpw_siteKey_v2( - MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter, - MPKeyPurpose keyPurpose, const char *keyContext); -const char *mpw_sitePasswordFromTemplate_v2( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam); -const char *mpw_sitePasswordFromCrypt_v2( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText); -const char *mpw_sitePasswordFromDerive_v2( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam); -const char *mpw_siteState_v2( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state); - -// Algorithm version overrides. -static MPMasterKey mpw_masterKey_v3( - const char *fullName, const char *masterPassword) { - - const char *keyScope = mpw_scopeForPurpose( MPKeyPurposeAuthentication ); - trc( "keyScope: %s", keyScope ); - - // Calculate the master key salt. - trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s", - keyScope, mpw_hex_l( (uint32_t)strlen( fullName ) ), fullName ); - size_t masterKeySaltSize = 0; - uint8_t *masterKeySalt = NULL; - mpw_push_string( &masterKeySalt, &masterKeySaltSize, keyScope ); - mpw_push_int( &masterKeySalt, &masterKeySaltSize, (uint32_t)strlen( fullName ) ); - mpw_push_string( &masterKeySalt, &masterKeySaltSize, fullName ); - if (!masterKeySalt) { - err( "Could not allocate master key salt: %s", strerror( errno ) ); - return NULL; - } - trc( " => masterKeySalt.id: %s", mpw_id_buf( masterKeySalt, masterKeySaltSize ) ); - - // Calculate the master key. - trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%lu, r=%u, p=%u )", MP_N, MP_r, MP_p ); - MPMasterKey masterKey = mpw_kdf_scrypt( MPMasterKeySize, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p ); - mpw_free( &masterKeySalt, masterKeySaltSize ); - if (!masterKey) { - err( "Could not derive master key: %s", strerror( errno ) ); - return NULL; - } - trc( " => masterKey.id: %s", mpw_id_buf( masterKey, MPMasterKeySize ) ); - - return masterKey; -} - -static MPSiteKey mpw_siteKey_v3( - MPMasterKey masterKey, const char *siteName, MPCounterValue siteCounter, - MPKeyPurpose keyPurpose, const char *keyContext) { - - return mpw_siteKey_v2( masterKey, siteName, siteCounter, keyPurpose, keyContext ); -} - -static const char *mpw_sitePasswordFromTemplate_v3( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) { - - return mpw_sitePasswordFromTemplate_v2( masterKey, siteKey, resultType, resultParam ); -} - -static const char *mpw_sitePasswordFromCrypt_v3( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *cipherText) { - - return mpw_sitePasswordFromCrypt_v2( masterKey, siteKey, resultType, cipherText ); -} - -static const char *mpw_sitePasswordFromDerive_v3( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *resultParam) { - - return mpw_sitePasswordFromDerive_v2( masterKey, siteKey, resultType, resultParam ); -} - -static const char *mpw_siteState_v3( - MPMasterKey masterKey, MPSiteKey siteKey, MPResultType resultType, const char *state) { - - return mpw_siteState_v2( masterKey, siteKey, resultType, state ); -} diff --git a/core/c/mpw-marshal-util.c b/core/c/mpw-marshal-util.c deleted file mode 100644 index 9bd0e66b..00000000 --- a/core/c/mpw-marshal-util.c +++ /dev/null @@ -1,115 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#include - -#include "mpw-marshal-util.h" -#include "mpw-util.h" - -char *mpw_get_token(const char **in, const char *eol, char *delim) { - - // Skip leading spaces. - for (; **in == ' '; ++*in); - - // Find characters up to the first delim. - size_t len = strcspn( *in, delim ); - char *token = len && len <= (size_t)(eol - *in)? mpw_strndup( *in, len ): NULL; - - // Advance past the delimitor. - *in = min( eol, *in + len + 1 ); - return token; -} - -time_t mpw_mktime( - const char *time) { - - struct tm tm = { .tm_isdst = -1 }; - if (time && sscanf( time, "%4d-%2d-%2dT%2d:%2d:%2dZ", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, - &tm.tm_hour, &tm.tm_min, &tm.tm_sec ) == 6) { - tm.tm_year -= 1900; // tm_year 0 = rfc3339 year 1900 - tm.tm_mon -= 1; // tm_mon 0 = rfc3339 month 1 - return mktime( &tm ); - } - - return false; -} - -#if MPW_JSON -json_object *mpw_get_json_section( - json_object *obj, const char *section) { - - json_object *json_value = obj; - char *sectionTokenizer = mpw_strdup( section ), *sectionToken = sectionTokenizer; - for (sectionToken = strtok( sectionToken, "." ); sectionToken; sectionToken = strtok( NULL, "." )) - if (!json_object_object_get_ex( json_value, sectionToken, &json_value ) || !json_value) { - trc( "While resolving: %s: Missing value for: %s", section, sectionToken ); - json_value = NULL; - break; - } - free( sectionTokenizer ); - - return json_value; -} - -const char *mpw_get_json_string( - json_object *obj, const char *section, const char *defaultValue) { - - json_object *json_value = mpw_get_json_section( obj, section ); - if (!json_value) - return defaultValue; - - return json_object_get_string( json_value ); -} - -int64_t mpw_get_json_int( - json_object *obj, const char *section, int64_t defaultValue) { - - json_object *json_value = mpw_get_json_section( obj, section ); - if (!json_value) - return defaultValue; - - return json_object_get_int64( json_value ); -} - -bool mpw_get_json_boolean( - json_object *obj, const char *section, bool defaultValue) { - - json_object *json_value = mpw_get_json_section( obj, section ); - if (!json_value) - return defaultValue; - - return json_object_get_boolean( json_value ) == TRUE; -} -#endif - -bool mpw_update_masterKey(MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, MPAlgorithmVersion targetKeyAlgorithm, - const char *fullName, const char *masterPassword) { - - if (*masterKeyAlgorithm != targetKeyAlgorithm) { - mpw_free( masterKey, MPMasterKeySize ); - *masterKeyAlgorithm = targetKeyAlgorithm; - *masterKey = mpw_masterKey( fullName, masterPassword, *masterKeyAlgorithm ); - if (!*masterKey) { - err( "Couldn't derive master key for user %s, algorithm %d.", fullName, *masterKeyAlgorithm ); - return false; - } - } - - return true; -} diff --git a/core/c/mpw-marshal-util.h b/core/c/mpw-marshal-util.h deleted file mode 100644 index 3afbfb07..00000000 --- a/core/c/mpw-marshal-util.h +++ /dev/null @@ -1,73 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#ifndef _MPW_MARSHAL_UTIL_H -#define _MPW_MARSHAL_UTIL_H - -#include -#if MPW_JSON -#include "json-c/json.h" -#endif - -#include "mpw-algorithm.h" - -/// Type parsing. - -/** Get a token from a string by searching until the first character in delim, no farther than eol. - * The input string reference is advanced beyond the token delimitor if one is found. - * @return A new string containing the token or NULL if the delim wasn't found before eol. */ -char *mpw_get_token( - const char **in, const char *eol, char *delim); -/** Convert an RFC 3339 time string into epoch time. */ -time_t mpw_mktime( - const char *time); - -/// JSON parsing. - -#if MPW_JSON -/** Search for a JSON child object in a JSON object tree. - * @param section A dot-delimited list of JSON object keys to walk toward the child object. - * @return A new JSON object or NULL if one of the section's object keys was not found in the source object's tree. */ -json_object *mpw_get_json_section( - json_object *obj, const char *section); -/** Search for a string in a JSON object tree. - * @param section A dot-delimited list of JSON object keys to walk toward the child object. - * @return A new string or defaultValue if one of the section's object keys was not found in the source object's tree. */ -const char *mpw_get_json_string( - json_object *obj, const char *section, const char *defaultValue); -/** Search for an integer in a JSON object tree. - * @param section A dot-delimited list of JSON object keys to walk toward the child object. - * @return The integer value or defaultValue if one of the section's object keys was not found in the source object's tree. */ -int64_t mpw_get_json_int( - json_object *obj, const char *section, int64_t defaultValue); -/** Search for a boolean in a JSON object tree. - * @param section A dot-delimited list of JSON object keys to walk toward the child object. - * @return The boolean value or defaultValue if one of the section's object keys was not found in the source object's tree. */ -bool mpw_get_json_boolean( - json_object *obj, const char *section, bool defaultValue); -#endif - -/// mpw. - -/** Calculate a master key if the target master key algorithm is different from the given master key algorithm. - * @return false if an error occurred during the derivation of the master key. */ -bool mpw_update_masterKey( - MPMasterKey *masterKey, MPAlgorithmVersion *masterKeyAlgorithm, MPAlgorithmVersion targetKeyAlgorithm, - const char *fullName, const char *masterPassword); - -#endif // _MPW_MARSHAL_UTIL_H diff --git a/core/c/mpw-marshal.c b/core/c/mpw-marshal.c deleted file mode 100644 index fd17669e..00000000 --- a/core/c/mpw-marshal.c +++ /dev/null @@ -1,924 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - - -#include -#include -#include - -#include "mpw-marshal.h" -#include "mpw-util.h" -#include "mpw-marshal-util.h" - -MPMarshalledUser *mpw_marshal_user( - const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) { - - MPMarshalledUser *user; - if (!fullName || !masterPassword || !(user = malloc( sizeof( MPMarshalledUser ) ))) - return NULL; - - *user = (MPMarshalledUser){ - .fullName = mpw_strdup( fullName ), - .masterPassword = mpw_strdup( masterPassword ), - .algorithm = algorithmVersion, - .redacted = true, - - .avatar = 0, - .defaultType = MPResultTypeDefault, - .lastUsed = 0, - - .sites_count = 0, - .sites = NULL, - }; - return user; -} - -MPMarshalledSite *mpw_marshal_site( - MPMarshalledUser *user, const char *siteName, const MPResultType resultType, - const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion) { - - if (!siteName || !mpw_realloc( &user->sites, NULL, sizeof( MPMarshalledSite ) * ++user->sites_count )) - return NULL; - - MPMarshalledSite *site = &user->sites[user->sites_count - 1]; - *site = (MPMarshalledSite){ - .name = mpw_strdup( siteName ), - .content = NULL, - .type = resultType, - .counter = siteCounter, - .algorithm = algorithmVersion, - - .loginContent = NULL, - .loginType = MPResultTypeTemplateName, - - .url = NULL, - .uses = 0, - .lastUsed = 0, - - .questions_count = 0, - .questions = NULL, - }; - return site; -} - -MPMarshalledQuestion *mpw_marshal_question( - MPMarshalledSite *site, const char *keyword) { - - if (!mpw_realloc( &site->questions, NULL, sizeof( MPMarshalledQuestion ) * ++site->questions_count )) - return NULL; - if (!keyword) - keyword = ""; - - MPMarshalledQuestion *question = &site->questions[site->questions_count - 1]; - *question = (MPMarshalledQuestion){ - .keyword = mpw_strdup( keyword ), - .content = NULL, - .type = MPResultTypeTemplatePhrase, - }; - return question; -} - -bool mpw_marshal_info_free( - MPMarshalInfo **info) { - - if (!info || !*info) - return true; - - bool success = true; - success &= mpw_free_strings( &(*info)->fullName, &(*info)->keyID, NULL ); - success &= mpw_free( info, sizeof( MPMarshalInfo ) ); - - return success; -} - -bool mpw_marshal_free( - MPMarshalledUser **user) { - - if (!user || !*user) - return true; - - bool success = true; - success &= mpw_free_strings( &(*user)->fullName, &(*user)->masterPassword, NULL ); - - for (size_t s = 0; s < (*user)->sites_count; ++s) { - MPMarshalledSite *site = &(*user)->sites[s]; - success &= mpw_free_strings( &site->name, &site->content, &site->loginContent, &site->url, NULL ); - - for (size_t q = 0; q < site->questions_count; ++q) { - MPMarshalledQuestion *question = &site->questions[q]; - success &= mpw_free_strings( &question->keyword, &question->content, NULL ); - } - success &= mpw_free( &site->questions, sizeof( MPMarshalledQuestion ) * site->questions_count ); - } - - success &= mpw_free( &(*user)->sites, sizeof( MPMarshalledSite ) * (*user)->sites_count ); - success &= mpw_free( user, sizeof( MPMarshalledUser ) ); - - return success; -} - -static bool mpw_marshal_write_flat( - char **out, const MPMarshalledUser *user, MPMarshalError *error) { - - *error = (MPMarshalError){ MPMarshalErrorInternal, "Unexpected internal error." }; - if (!user->fullName || !strlen( user->fullName )) { - *error = (MPMarshalError){ MPMarshalErrorMissing, "Missing full name." }; - return false; - } - if (!user->masterPassword || !strlen( user->masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorMasterPassword, "Missing master password." }; - return false; - } - MPMasterKey masterKey = NULL; - MPAlgorithmVersion masterKeyAlgorithm = user->algorithm - 1; - if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, user->algorithm, user->fullName, user->masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." }; - return false; - } - - mpw_string_pushf( out, "# Master Password site export\n" ); - if (user->redacted) - mpw_string_pushf( out, "# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n" ); - else - mpw_string_pushf( out, "# Export of site names and passwords in clear-text.\n" ); - mpw_string_pushf( out, "# \n" ); - mpw_string_pushf( out, "##\n" ); - mpw_string_pushf( out, "# Format: %d\n", 1 ); - - char dateString[21]; - time_t now = time( NULL ); - if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &now ) )) - mpw_string_pushf( out, "# Date: %s\n", dateString ); - mpw_string_pushf( out, "# User Name: %s\n", user->fullName ); - mpw_string_pushf( out, "# Full Name: %s\n", user->fullName ); - mpw_string_pushf( out, "# Avatar: %u\n", user->avatar ); - mpw_string_pushf( out, "# Key ID: %s\n", mpw_id_buf( masterKey, MPMasterKeySize ) ); - mpw_string_pushf( out, "# Algorithm: %d\n", user->algorithm ); - mpw_string_pushf( out, "# Default Type: %d\n", user->defaultType ); - mpw_string_pushf( out, "# Passwords: %s\n", user->redacted? "PROTECTED": "VISIBLE" ); - mpw_string_pushf( out, "##\n" ); - mpw_string_pushf( out, "#\n" ); - mpw_string_pushf( out, "# Last Times Password Login\t Site\tSite\n" ); - mpw_string_pushf( out, "# used used type name\t name\tpassword\n" ); - - // Sites. - for (size_t s = 0; s < user->sites_count; ++s) { - MPMarshalledSite *site = &user->sites[s]; - if (!site->name || !strlen( site->name )) - continue; - - const char *content = NULL, *loginContent = NULL; - if (!user->redacted) { - // Clear Text - if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, user->fullName, user->masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." }; - return false; - } - - content = mpw_siteResult( masterKey, site->name, site->counter, - MPKeyPurposeAuthentication, NULL, site->type, site->content, site->algorithm ); - loginContent = mpw_siteResult( masterKey, site->name, MPCounterValueInitial, - MPKeyPurposeIdentification, NULL, site->loginType, site->loginContent, site->algorithm ); - } - else { - // Redacted - if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content )) - content = mpw_strdup( site->content ); - if (site->loginType & MPSiteFeatureExportContent && site->loginContent && strlen( site->loginContent )) - loginContent = mpw_strdup( site->loginContent ); - } - - if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site->lastUsed ) )) - mpw_string_pushf( out, "%s %8ld %lu:%lu:%lu %25s\t%25s\t%s\n", - dateString, (long)site->uses, (long)site->type, (long)site->algorithm, (long)site->counter, - loginContent?: "", site->name, content?: "" ); - mpw_free_strings( &content, &loginContent, NULL ); - } - mpw_free( &masterKey, MPMasterKeySize ); - - *error = (MPMarshalError){ .type = MPMarshalSuccess }; - return true; -} - -#if MPW_JSON -static bool mpw_marshal_write_json( - char **out, const MPMarshalledUser *user, MPMarshalError *error) { - - *error = (MPMarshalError){ MPMarshalErrorInternal, "Unexpected internal error." }; - if (!user->fullName || !strlen( user->fullName )) { - *error = (MPMarshalError){ MPMarshalErrorMissing, "Missing full name." }; - return false; - } - if (!user->masterPassword || !strlen( user->masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorMasterPassword, "Missing master password." }; - return false; - } - MPMasterKey masterKey = NULL; - MPAlgorithmVersion masterKeyAlgorithm = user->algorithm - 1; - if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, user->algorithm, user->fullName, user->masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." }; - return false; - } - - // Section: "export" - json_object *json_file = json_object_new_object(); - json_object *json_export = json_object_new_object(); - json_object_object_add( json_file, "export", json_export ); - json_object_object_add( json_export, "format", json_object_new_int( 1 ) ); - json_object_object_add( json_export, "redacted", json_object_new_boolean( user->redacted ) ); - - char dateString[21]; - time_t now = time( NULL ); - if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &now ) )) - json_object_object_add( json_export, "date", json_object_new_string( dateString ) ); - - // Section: "user" - json_object *json_user = json_object_new_object(); - json_object_object_add( json_file, "user", json_user ); - json_object_object_add( json_user, "avatar", json_object_new_int( (int32_t)user->avatar ) ); - json_object_object_add( json_user, "full_name", json_object_new_string( user->fullName ) ); - - if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &user->lastUsed ) )) - json_object_object_add( json_user, "last_used", json_object_new_string( dateString ) ); - json_object_object_add( json_user, "key_id", json_object_new_string( mpw_id_buf( masterKey, MPMasterKeySize ) ) ); - - json_object_object_add( json_user, "algorithm", json_object_new_int( (int32_t)user->algorithm ) ); - json_object_object_add( json_user, "default_type", json_object_new_int( (int32_t)user->defaultType ) ); - - // Section "sites" - json_object *json_sites = json_object_new_object(); - json_object_object_add( json_file, "sites", json_sites ); - for (size_t s = 0; s < user->sites_count; ++s) { - MPMarshalledSite *site = &user->sites[s]; - if (!site->name || !strlen( site->name )) - continue; - - const char *content = NULL, *loginContent = NULL; - if (!user->redacted) { - // Clear Text - if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, user->fullName, user->masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." }; - return false; - } - - content = mpw_siteResult( masterKey, site->name, site->counter, - MPKeyPurposeAuthentication, NULL, site->type, site->content, site->algorithm ); - loginContent = mpw_siteResult( masterKey, site->name, MPCounterValueInitial, - MPKeyPurposeIdentification, NULL, site->loginType, site->loginContent, site->algorithm ); - } - else { - // Redacted - if (site->type & MPSiteFeatureExportContent && site->content && strlen( site->content )) - content = mpw_strdup( site->content ); - if (site->loginType & MPSiteFeatureExportContent && site->loginContent && strlen( site->loginContent )) - loginContent = mpw_strdup( site->loginContent ); - } - - json_object *json_site = json_object_new_object(); - json_object_object_add( json_sites, site->name, json_site ); - json_object_object_add( json_site, "type", json_object_new_int( (int32_t)site->type ) ); - json_object_object_add( json_site, "counter", json_object_new_int( (int32_t)site->counter ) ); - json_object_object_add( json_site, "algorithm", json_object_new_int( (int32_t)site->algorithm ) ); - if (content) - json_object_object_add( json_site, "password", json_object_new_string( content ) ); - if (loginContent) - json_object_object_add( json_site, "login_name", json_object_new_string( loginContent ) ); - json_object_object_add( json_site, "login_type", json_object_new_int( (int32_t)site->loginType ) ); - - json_object_object_add( json_site, "uses", json_object_new_int( (int32_t)site->uses ) ); - if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site->lastUsed ) )) - json_object_object_add( json_site, "last_used", json_object_new_string( dateString ) ); - - json_object *json_site_questions = json_object_new_object(); - json_object_object_add( json_site, "questions", json_site_questions ); - for (size_t q = 0; q < site->questions_count; ++q) { - MPMarshalledQuestion *question = &site->questions[q]; - if (!question->keyword) - continue; - - json_object *json_site_question = json_object_new_object(); - json_object_object_add( json_site_questions, question->keyword, json_site_question ); - json_object_object_add( json_site_question, "type", json_object_new_int( (int32_t)question->type ) ); - - if (!user->redacted) { - // Clear Text - const char *answerContent = mpw_siteResult( masterKey, site->name, MPCounterValueInitial, - MPKeyPurposeRecovery, question->keyword, question->type, question->content, site->algorithm ); - json_object_object_add( json_site_question, "answer", json_object_new_string( answerContent ) ); - } - else { - // Redacted - if (site->type & MPSiteFeatureExportContent && question->content && strlen( question->content )) - json_object_object_add( json_site_question, "answer", json_object_new_string( question->content ) ); - } - } - - json_object *json_site_mpw = json_object_new_object(); - json_object_object_add( json_site, "_ext_mpw", json_site_mpw ); - if (site->url) - json_object_object_add( json_site_mpw, "url", json_object_new_string( site->url ) ); - - mpw_free_strings( &content, &loginContent, NULL ); - } - - mpw_string_pushf( out, "%s\n", json_object_to_json_string_ext( json_file, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED ) ); - mpw_free( &masterKey, MPMasterKeySize ); - json_object_put( json_file ); - - *error = (MPMarshalError){ .type = MPMarshalSuccess }; - return true; -} -#endif - -bool mpw_marshal_write( - char **out, const MPMarshalFormat outFormat, const MPMarshalledUser *user, MPMarshalError *error) { - - switch (outFormat) { - case MPMarshalFormatNone: - *error = (MPMarshalError){ .type = MPMarshalSuccess }; - return false; - case MPMarshalFormatFlat: - return mpw_marshal_write_flat( out, user, error ); -#if MPW_JSON - case MPMarshalFormatJSON: - return mpw_marshal_write_json( out, user, error ); -#endif - default: - *error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported output format: %u", outFormat ) }; - return false; - } -} - -static void mpw_marshal_read_flat_info( - const char *in, MPMarshalInfo *info) { - - info->algorithm = MPAlgorithmVersionCurrent; - - // Parse import data. - bool headerStarted = false; - for (const char *endOfLine, *positionInLine = in; (endOfLine = strstr( positionInLine, "\n" )); positionInLine = endOfLine + 1) { - - // Comment or header - if (*positionInLine == '#') { - ++positionInLine; - - if (!headerStarted) { - if (*positionInLine == '#') - // ## starts header - headerStarted = true; - // Comment before header - continue; - } - if (*positionInLine == '#') - // ## ends header - break; - - // Header - char *headerName = mpw_get_token( &positionInLine, endOfLine, ":\n" ); - char *headerValue = mpw_get_token( &positionInLine, endOfLine, "\n" ); - if (!headerName || !headerValue) - continue; - - if (strcmp( headerName, "Algorithm" ) == 0) - info->algorithm = (MPAlgorithmVersion)atoi( headerValue ); - if (strcmp( headerName, "Full Name" ) == 0 || strcmp( headerName, "User Name" ) == 0) - info->fullName = mpw_strdup( headerValue ); - if (strcmp( headerName, "Key ID" ) == 0) - info->keyID = mpw_strdup( headerValue ); - if (strcmp( headerName, "Passwords" ) == 0) - info->redacted = strcmp( headerValue, "VISIBLE" ) != 0; - if (strcmp( headerName, "Date" ) == 0) - info->date = mpw_mktime( headerValue ); - - mpw_free_strings( &headerName, &headerValue, NULL ); - continue; - } - } -} - -static MPMarshalledUser *mpw_marshal_read_flat( - const char *in, const char *masterPassword, MPMarshalError *error) { - - *error = (MPMarshalError){ MPMarshalErrorInternal, "Unexpected internal error." }; - if (!in || !strlen( in )) { - error->type = MPMarshalErrorStructure; - error->description = mpw_str( "No input data." ); - return NULL; - } - - // Parse import data. - MPMasterKey masterKey = NULL; - MPMarshalledUser *user = NULL; - unsigned int format = 0, avatar = 0; - char *fullName = NULL, *keyID = NULL; - MPAlgorithmVersion algorithm = MPAlgorithmVersionCurrent, masterKeyAlgorithm = (MPAlgorithmVersion)-1; - MPResultType defaultType = MPResultTypeDefault; - bool headerStarted = false, headerEnded = false, importRedacted = false; - for (const char *endOfLine, *positionInLine = in; (endOfLine = strstr( positionInLine, "\n" )); positionInLine = endOfLine + 1) { - - // Comment or header - if (*positionInLine == '#') { - ++positionInLine; - - if (!headerStarted) { - if (*positionInLine == '#') - // ## starts header - headerStarted = true; - // Comment before header - continue; - } - if (headerEnded) - // Comment after header - continue; - if (*positionInLine == '#') { - // ## ends header - headerEnded = true; - continue; - } - - // Header - char *headerName = mpw_get_token( &positionInLine, endOfLine, ":\n" ); - char *headerValue = mpw_get_token( &positionInLine, endOfLine, "\n" ); - if (!headerName || !headerValue) { - error->type = MPMarshalErrorStructure; - error->description = mpw_str( "Invalid header: %s", mpw_strndup( positionInLine, (size_t)(endOfLine - positionInLine) ) ); - return NULL; - } - - if (strcmp( headerName, "Format" ) == 0) - format = (unsigned int)atoi( headerValue ); - if (strcmp( headerName, "Full Name" ) == 0 || strcmp( headerName, "User Name" ) == 0) - fullName = mpw_strdup( headerValue ); - if (strcmp( headerName, "Avatar" ) == 0) - avatar = (unsigned int)atoi( headerValue ); - if (strcmp( headerName, "Key ID" ) == 0) - keyID = mpw_strdup( headerValue ); - if (strcmp( headerName, "Algorithm" ) == 0) { - int value = atoi( headerValue ); - if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user algorithm version: %s", headerValue ) }; - return NULL; - } - algorithm = (MPAlgorithmVersion)value; - } - if (strcmp( headerName, "Default Type" ) == 0) { - int value = atoi( headerValue ); - if (!mpw_nameForType( (MPResultType)value )) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user default type: %s", headerValue ) }; - return NULL; - } - defaultType = (MPResultType)value; - } - if (strcmp( headerName, "Passwords" ) == 0) - importRedacted = strcmp( headerValue, "VISIBLE" ) != 0; - - mpw_free_strings( &headerName, &headerValue, NULL ); - continue; - } - if (!headerEnded) - continue; - if (!fullName) { - *error = (MPMarshalError){ MPMarshalErrorMissing, "Missing header: Full Name" }; - return NULL; - } - if (positionInLine >= endOfLine) - continue; - - if (!user) { - if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, algorithm, fullName, masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." }; - return NULL; - } - if (keyID && !mpw_id_buf_equals( keyID, mpw_id_buf( masterKey, MPMasterKeySize ) )) { - *error = (MPMarshalError){ MPMarshalErrorMasterPassword, "Master password doesn't match key ID." }; - return NULL; - } - if (!(user = mpw_marshal_user( fullName, masterPassword, algorithm ))) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate a new user." }; - return NULL; - } - - user->redacted = importRedacted; - user->avatar = avatar; - user->defaultType = defaultType; - } - - // Site - char *siteLoginName = NULL, *siteName = NULL, *siteContent = NULL; - char *str_lastUsed = NULL, *str_uses = NULL, *str_type = NULL, *str_algorithm = NULL, *str_counter = NULL; - switch (format) { - case 0: { - str_lastUsed = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); - str_uses = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); - char *typeAndVersion = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); - if (typeAndVersion) { - str_type = mpw_strdup( strtok( typeAndVersion, ":" ) ); - str_algorithm = mpw_strdup( strtok( NULL, "" ) ); - mpw_free_string( &typeAndVersion ); - } - str_counter = mpw_strdup( "1" ); - siteLoginName = NULL; - siteName = mpw_get_token( &positionInLine, endOfLine, "\t\n" ); - siteContent = mpw_get_token( &positionInLine, endOfLine, "\n" ); - break; - } - case 1: { - str_lastUsed = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); - str_uses = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); - char *typeAndVersionAndCounter = mpw_get_token( &positionInLine, endOfLine, " \t\n" ); - if (typeAndVersionAndCounter) { - str_type = mpw_strdup( strtok( typeAndVersionAndCounter, ":" ) ); - str_algorithm = mpw_strdup( strtok( NULL, ":" ) ); - str_counter = mpw_strdup( strtok( NULL, "" ) ); - mpw_free_string( &typeAndVersionAndCounter ); - } - siteLoginName = mpw_get_token( &positionInLine, endOfLine, "\t\n" ); - siteName = mpw_get_token( &positionInLine, endOfLine, "\t\n" ); - siteContent = mpw_get_token( &positionInLine, endOfLine, "\n" ); - break; - } - default: { - *error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unexpected import format: %u", format ) }; - return NULL; - } - } - - if (siteName && str_type && str_counter && str_algorithm && str_uses && str_lastUsed) { - MPResultType siteType = (MPResultType)atoi( str_type ); - if (!mpw_nameForType( siteType )) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid site type: %s: %s", siteName, str_type ) }; - return NULL; - } - long long int value = atoll( str_counter ); - if (value < MPCounterValueFirst || value > MPCounterValueLast) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid site counter: %s: %s", siteName, str_counter ) }; - return NULL; - } - MPCounterValue siteCounter = (MPCounterValue)value; - value = atoll( str_algorithm ); - if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid site algorithm: %s: %s", siteName, str_algorithm ) }; - return NULL; - } - MPAlgorithmVersion siteAlgorithm = (MPAlgorithmVersion)value; - time_t siteLastUsed = mpw_mktime( str_lastUsed ); - if (!siteLastUsed) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid site last used: %s: %s", siteName, str_lastUsed ) }; - return NULL; - } - - MPMarshalledSite *site = mpw_marshal_site( - user, siteName, siteType, siteCounter, siteAlgorithm ); - if (!site) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate a new site." }; - return NULL; - } - - site->uses = (unsigned int)atoi( str_uses ); - site->lastUsed = siteLastUsed; - if (!user->redacted) { - // Clear Text - if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." }; - return NULL; - } - - if (siteContent && strlen( siteContent )) - site->content = mpw_siteState( masterKey, site->name, site->counter, - MPKeyPurposeAuthentication, NULL, site->type, siteContent, site->algorithm ); - if (siteLoginName && strlen( siteLoginName )) - site->loginContent = mpw_siteState( masterKey, site->name, MPCounterValueInitial, - MPKeyPurposeIdentification, NULL, site->loginType, siteLoginName, site->algorithm ); - } - else { - // Redacted - if (siteContent && strlen( siteContent )) - site->content = mpw_strdup( siteContent ); - if (siteLoginName && strlen( siteLoginName )) - site->loginContent = mpw_strdup( siteLoginName ); - } - } - else { - error->type = MPMarshalErrorMissing; - error->description = mpw_str( - "Missing one of: lastUsed=%s, uses=%s, type=%s, version=%s, counter=%s, loginName=%s, siteName=%s", - str_lastUsed, str_uses, str_type, str_algorithm, str_counter, siteLoginName, siteName ); - return NULL; - } - - mpw_free_strings( &str_lastUsed, &str_uses, &str_type, &str_algorithm, &str_counter, NULL ); - mpw_free_strings( &siteLoginName, &siteName, &siteContent, NULL ); - } - mpw_free_strings( &fullName, &keyID, NULL ); - mpw_free( &masterKey, MPMasterKeySize ); - - *error = (MPMarshalError){ .type = MPMarshalSuccess }; - return user; -} - -#if MPW_JSON -static void mpw_marshal_read_json_info( - const char *in, MPMarshalInfo *info) { - - // Parse JSON. - enum json_tokener_error json_error = json_tokener_success; - json_object *json_file = json_tokener_parse_verbose( in, &json_error ); - if (!json_file || json_error != json_tokener_success) - return; - - // Section: "export" - int64_t fileFormat = mpw_get_json_int( json_file, "export.format", 0 ); - if (fileFormat < 1) - return; - info->redacted = mpw_get_json_boolean( json_file, "export.redacted", true ); - info->date = mpw_mktime( mpw_get_json_string( json_file, "export.date", NULL ) ); - - // Section: "user" - info->algorithm = (MPAlgorithmVersion)mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent ); - info->fullName = mpw_strdup( mpw_get_json_string( json_file, "user.full_name", NULL ) ); - info->keyID = mpw_strdup( mpw_get_json_string( json_file, "user.key_id", NULL ) ); - - json_object_put( json_file ); -} - -static MPMarshalledUser *mpw_marshal_read_json( - const char *in, const char *masterPassword, MPMarshalError *error) { - - *error = (MPMarshalError){ MPMarshalErrorInternal, "Unexpected internal error." }; - if (!in || !strlen( in )) { - error->type = MPMarshalErrorStructure; - error->description = mpw_str( "No input data." ); - return NULL; - } - - // Parse JSON. - enum json_tokener_error json_error = json_tokener_success; - json_object *json_file = json_tokener_parse_verbose( in, &json_error ); - if (!json_file || json_error != json_tokener_success) { - *error = (MPMarshalError){ MPMarshalErrorStructure, mpw_str( "JSON error: %s", json_tokener_error_desc( json_error ) ) }; - return NULL; - } - - // Parse import data. - MPMasterKey masterKey = NULL; - MPAlgorithmVersion masterKeyAlgorithm = (MPAlgorithmVersion)-1; - MPMarshalledUser *user = NULL; - - // Section: "export" - int64_t fileFormat = mpw_get_json_int( json_file, "export.format", 0 ); - if (fileFormat < 1) { - *error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported format: %u", fileFormat ) }; - return NULL; - } - bool fileRedacted = mpw_get_json_boolean( json_file, "export.redacted", true ); - - // Section: "user" - unsigned int avatar = (unsigned int)mpw_get_json_int( json_file, "user.avatar", 0 ); - const char *fullName = mpw_get_json_string( json_file, "user.full_name", NULL ); - const char *str_lastUsed = mpw_get_json_string( json_file, "user.last_used", NULL ); - const char *keyID = mpw_get_json_string( json_file, "user.key_id", NULL ); - int64_t value = mpw_get_json_int( json_file, "user.algorithm", MPAlgorithmVersionCurrent ); - if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user algorithm version: %u", value ) }; - return NULL; - } - MPAlgorithmVersion algorithm = (MPAlgorithmVersion)value; - MPResultType defaultType = (MPResultType)mpw_get_json_int( json_file, "user.default_type", MPResultTypeDefault ); - if (!mpw_nameForType( defaultType )) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user default type: %u", defaultType ) }; - return NULL; - } - time_t lastUsed = mpw_mktime( str_lastUsed ); - if (!lastUsed) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid user last used: %s", str_lastUsed ) }; - return NULL; - } - if (!fullName || !strlen( fullName )) { - *error = (MPMarshalError){ MPMarshalErrorMissing, "Missing value for full name." }; - return NULL; - } - if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, algorithm, fullName, masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." }; - return NULL; - } - if (keyID && !mpw_id_buf_equals( keyID, mpw_id_buf( masterKey, MPMasterKeySize ) )) { - *error = (MPMarshalError){ MPMarshalErrorMasterPassword, "Master password doesn't match key ID." }; - return NULL; - } - if (!(user = mpw_marshal_user( fullName, masterPassword, algorithm ))) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate a new user." }; - return NULL; - } - user->redacted = fileRedacted; - user->avatar = avatar; - user->defaultType = defaultType; - user->lastUsed = lastUsed; - - // Section "sites" - json_object_iter json_site; - json_object *json_sites = mpw_get_json_section( json_file, "sites" ); - json_object_object_foreachC( json_sites, json_site ) { - const char *siteName = json_site.key; - value = mpw_get_json_int( json_site.val, "algorithm", (int32_t)user->algorithm ); - if (value < MPAlgorithmVersionFirst || value > MPAlgorithmVersionLast) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid site algorithm version: %s: %d", siteName, value ) }; - return NULL; - } - MPAlgorithmVersion siteAlgorithm = (MPAlgorithmVersion)value; - MPResultType siteType = (MPResultType)mpw_get_json_int( json_site.val, "type", (int32_t)user->defaultType ); - if (!mpw_nameForType( siteType )) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid site type: %s: %u", siteName, siteType ) }; - return NULL; - } - value = mpw_get_json_int( json_site.val, "counter", 1 ); - if (value < MPCounterValueFirst || value > MPCounterValueLast) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid site counter: %s: %d", siteName, value ) }; - return NULL; - } - MPCounterValue siteCounter = (MPCounterValue)value; - const char *siteContent = mpw_get_json_string( json_site.val, "password", NULL ); - const char *siteLoginName = mpw_get_json_string( json_site.val, "login_name", NULL ); - MPResultType siteLoginType = (MPResultType)mpw_get_json_int( json_site.val, "login_type", MPResultTypeTemplateName ); - unsigned int siteUses = (unsigned int)mpw_get_json_int( json_site.val, "uses", 0 ); - str_lastUsed = mpw_get_json_string( json_site.val, "last_used", NULL ); - time_t siteLastUsed = mpw_mktime( str_lastUsed ); - if (!siteLastUsed) { - *error = (MPMarshalError){ MPMarshalErrorIllegal, mpw_str( "Invalid site last used: %s: %s", siteName, str_lastUsed ) }; - return NULL; - } - - json_object *json_site_mpw = mpw_get_json_section( json_site.val, "_ext_mpw" ); - const char *siteURL = mpw_get_json_string( json_site_mpw, "url", NULL ); - - MPMarshalledSite *site = mpw_marshal_site( user, siteName, siteType, siteCounter, siteAlgorithm ); - if (!site) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't allocate a new site." }; - return NULL; - } - - site->loginType = siteLoginType; - site->url = siteURL? mpw_strdup( siteURL ): NULL; - site->uses = siteUses; - site->lastUsed = siteLastUsed; - if (!user->redacted) { - // Clear Text - if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) { - *error = (MPMarshalError){ MPMarshalErrorInternal, "Couldn't derive master key." }; - return NULL; - } - - if (siteContent && strlen( siteContent )) - site->content = mpw_siteState( masterKey, site->name, site->counter, - MPKeyPurposeAuthentication, NULL, site->type, siteContent, site->algorithm ); - if (siteLoginName && strlen( siteLoginName )) - site->loginContent = mpw_siteState( masterKey, site->name, MPCounterValueInitial, - MPKeyPurposeIdentification, NULL, site->loginType, siteLoginName, site->algorithm ); - } - else { - // Redacted - if (siteContent && strlen( siteContent )) - site->content = mpw_strdup( siteContent ); - if (siteLoginName && strlen( siteLoginName )) - site->loginContent = mpw_strdup( siteLoginName ); - } - - json_object_iter json_site_question; - json_object *json_site_questions = mpw_get_json_section( json_site.val, "questions" ); - json_object_object_foreachC( json_site_questions, json_site_question ) { - MPMarshalledQuestion *question = mpw_marshal_question( site, json_site_question.key ); - const char *answerContent = mpw_get_json_string( json_site_question.val, "answer", NULL ); - question->type = (MPResultType)mpw_get_json_int( json_site_question.val, "type", MPResultTypeTemplatePhrase ); - - if (!user->redacted) { - // Clear Text - if (answerContent && strlen( answerContent )) - question->content = mpw_siteState( masterKey, site->name, MPCounterValueInitial, - MPKeyPurposeRecovery, question->keyword, question->type, answerContent, site->algorithm ); - } - else { - // Redacted - if (answerContent && strlen( answerContent )) - question->content = mpw_strdup( answerContent ); - } - } - } - json_object_put( json_file ); - - *error = (MPMarshalError){ .type = MPMarshalSuccess }; - return user; -} -#endif - -MPMarshalInfo *mpw_marshal_read_info( - const char *in) { - - MPMarshalInfo *info = malloc( sizeof( MPMarshalInfo ) ); - *info = (MPMarshalInfo){ .format = MPMarshalFormatNone }; - - if (in && strlen( in )) { - if (in[0] == '#') { - *info = (MPMarshalInfo){ .format = MPMarshalFormatFlat }; - mpw_marshal_read_flat_info( in, info ); - } - else if (in[0] == '{') { - *info = (MPMarshalInfo){ .format = MPMarshalFormatJSON }; -#if MPW_JSON - mpw_marshal_read_json_info( in, info ); -#endif - } - } - - return info; -} - -MPMarshalledUser *mpw_marshal_read( - const char *in, const MPMarshalFormat inFormat, const char *masterPassword, MPMarshalError *error) { - - switch (inFormat) { - case MPMarshalFormatNone: - *error = (MPMarshalError){ .type = MPMarshalSuccess }; - return false; - case MPMarshalFormatFlat: - return mpw_marshal_read_flat( in, masterPassword, error ); -#if MPW_JSON - case MPMarshalFormatJSON: - return mpw_marshal_read_json( in, masterPassword, error ); -#endif - default: - *error = (MPMarshalError){ MPMarshalErrorFormat, mpw_str( "Unsupported input format: %u", inFormat ) }; - return NULL; - } -} - -const MPMarshalFormat mpw_formatWithName( - const char *formatName) { - - if (!formatName || !strlen( formatName )) - return MPMarshalFormatNone; - - // Lower-case to standardize it. - size_t stdFormatNameSize = strlen( formatName ); - char stdFormatName[stdFormatNameSize + 1]; - for (size_t c = 0; c < stdFormatNameSize; ++c) - stdFormatName[c] = (char)tolower( formatName[c] ); - stdFormatName[stdFormatNameSize] = '\0'; - - if (strncmp( mpw_nameForFormat( MPMarshalFormatNone ), stdFormatName, strlen( stdFormatName ) ) == 0) - return MPMarshalFormatNone; - if (strncmp( mpw_nameForFormat( MPMarshalFormatFlat ), stdFormatName, strlen( stdFormatName ) ) == 0) - return MPMarshalFormatFlat; - if (strncmp( mpw_nameForFormat( MPMarshalFormatJSON ), stdFormatName, strlen( stdFormatName ) ) == 0) - return MPMarshalFormatJSON; - - dbg( "Not a format name: %s", stdFormatName ); - return (MPMarshalFormat)ERR; -} - -const char *mpw_nameForFormat( - const MPMarshalFormat format) { - - switch (format) { - case MPMarshalFormatNone: - return "none"; - case MPMarshalFormatFlat: - return "flat"; - case MPMarshalFormatJSON: - return "json"; - default: { - dbg( "Unknown format: %d", format ); - return NULL; - } - } -} - -const char *mpw_marshal_format_extension( - const MPMarshalFormat format) { - - switch (format) { - case MPMarshalFormatNone: - return NULL; - case MPMarshalFormatFlat: - return "mpsites"; - case MPMarshalFormatJSON: - return "mpsites.json"; - default: { - dbg( "Unknown format: %d", format ); - return NULL; - } - } -} diff --git a/core/c/mpw-marshal.h b/core/c/mpw-marshal.h deleted file mode 100644 index 3a75d8a7..00000000 --- a/core/c/mpw-marshal.h +++ /dev/null @@ -1,159 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#ifndef _MPW_MARSHAL_H -#define _MPW_MARSHAL_H - -#include - -#include "mpw-algorithm.h" - -//// Types. - -typedef mpw_enum( unsigned int, MPMarshalFormat ) { - /** Do not marshal. */ - MPMarshalFormatNone, - /** Marshal using the line-based plain-text format. */ - MPMarshalFormatFlat, - /** Marshal using the JSON structured format. */ - MPMarshalFormatJSON, - -#if MPW_JSON - MPMarshalFormatDefault = MPMarshalFormatJSON, -#else - MPMarshalFormatDefault = MPMarshalFormatFlat, -#endif -}; - -typedef mpw_enum( unsigned int, MPMarshalErrorType ) { - /** The marshalling operation completed successfully. */ - MPMarshalSuccess, - /** An error in the structure of the marshall file interrupted marshalling. */ - MPMarshalErrorStructure, - /** The marshall file uses an unsupported format version. */ - MPMarshalErrorFormat, - /** A required value is missing or not specified. */ - MPMarshalErrorMissing, - /** The given master password is not valid. */ - MPMarshalErrorMasterPassword, - /** An illegal value was specified. */ - MPMarshalErrorIllegal, - /** An internal system error interrupted marshalling. */ - MPMarshalErrorInternal, -}; -typedef struct MPMarshalError { - MPMarshalErrorType type; - const char *description; -} MPMarshalError; - -typedef struct MPMarshalledQuestion { - const char *keyword; - const char *content; - MPResultType type; -} MPMarshalledQuestion; - -typedef struct MPMarshalledSite { - const char *name; - const char *content; - MPResultType type; - MPCounterValue counter; - MPAlgorithmVersion algorithm; - - const char *loginContent; - MPResultType loginType; - - const char *url; - unsigned int uses; - time_t lastUsed; - - size_t questions_count; - MPMarshalledQuestion *questions; -} MPMarshalledSite; - -typedef struct MPMarshalledUser { - const char *fullName; - const char *masterPassword; - MPAlgorithmVersion algorithm; - bool redacted; - - unsigned int avatar; - MPResultType defaultType; - time_t lastUsed; - - size_t sites_count; - MPMarshalledSite *sites; -} MPMarshalledUser; - -typedef struct MPMarshalInfo { - MPMarshalFormat format; - MPAlgorithmVersion algorithm; - const char *fullName; - const char *keyID; - bool redacted; - time_t date; -} MPMarshalInfo; - -//// Marshalling. - -/** Write the user and all associated data out to the given output buffer using the given marshalling format. */ -bool mpw_marshal_write( - char **out, const MPMarshalFormat outFormat, const MPMarshalledUser *user, MPMarshalError *error); -/** Try to read metadata on the sites in the input buffer. */ -MPMarshalInfo *mpw_marshal_read_info( - const char *in); -/** Unmarshall sites in the given input buffer by parsing it using the given marshalling format. */ -MPMarshalledUser *mpw_marshal_read( - const char *in, const MPMarshalFormat inFormat, const char *masterPassword, MPMarshalError *error); - -//// Utilities. - -/** Create a new user object ready for marshalling. */ -MPMarshalledUser *mpw_marshal_user( - const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion); -/** Create a new site attached to the given user object, ready for marshalling. */ -MPMarshalledSite *mpw_marshal_site( - MPMarshalledUser *user, - const char *siteName, const MPResultType resultType, const MPCounterValue siteCounter, const MPAlgorithmVersion algorithmVersion); -/** Create a new question attached to the given site object, ready for marshalling. */ -MPMarshalledQuestion *mpw_marshal_question( - MPMarshalledSite *site, const char *keyword); -/** Free the given user object and all associated data. */ -bool mpw_marshal_info_free( - MPMarshalInfo **info); -bool mpw_marshal_free( - MPMarshalledUser **user); - -//// Format. - -/** - * @return The purpose represented by the given name. - */ -const MPMarshalFormat mpw_formatWithName( - const char *formatName); -/** - * @return The standard name for the given purpose. - */ -const char *mpw_nameForFormat( - const MPMarshalFormat format); -/** - * @return The file extension that's recommended for files that use the given marshalling format. - */ -const char *mpw_marshal_format_extension( - const MPMarshalFormat format); - -#endif // _MPW_MARSHAL_H diff --git a/core/c/mpw-types.c b/core/c/mpw-types.c deleted file mode 100644 index 12487813..00000000 --- a/core/c/mpw-types.c +++ /dev/null @@ -1,267 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#include -#include - -#include "mpw-types.h" -#include "mpw-util.h" - -const size_t MPMasterKeySize = 64; -const size_t MPSiteKeySize = 256 / 8; // Size of HMAC-SHA-256 - -const MPResultType mpw_typeWithName(const char *typeName) { - - // Find what password type is represented by the type letter. - if (strlen( typeName ) == 1) { - if ('x' == typeName[0]) - return MPResultTypeTemplateMaximum; - if ('l' == typeName[0]) - return MPResultTypeTemplateLong; - if ('m' == typeName[0]) - return MPResultTypeTemplateMedium; - if ('b' == typeName[0]) - return MPResultTypeTemplateBasic; - if ('s' == typeName[0]) - return MPResultTypeTemplateShort; - if ('i' == typeName[0]) - return MPResultTypeTemplatePIN; - if ('n' == typeName[0]) - return MPResultTypeTemplateName; - if ('p' == typeName[0]) - return MPResultTypeTemplatePhrase; - if ('P' == typeName[0]) - return MPResultTypeStatefulPersonal; - if ('D' == typeName[0]) - return MPResultTypeStatefulDevice; - if ('K' == typeName[0]) - return MPResultTypeDeriveKey; - } - - // Lower-case typeName to standardize it. - size_t stdTypeNameSize = strlen( typeName ); - char stdTypeName[stdTypeNameSize + 1]; - for (size_t c = 0; c < stdTypeNameSize; ++c) - stdTypeName[c] = (char)tolower( typeName[c] ); - stdTypeName[stdTypeNameSize] = '\0'; - - // Find what password type is represented by the type name. - if (strncmp( mpw_nameForType( MPResultTypeTemplateMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeTemplateMaximum; - if (strncmp( mpw_nameForType( MPResultTypeTemplateLong ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeTemplateLong; - if (strncmp( mpw_nameForType( MPResultTypeTemplateMedium ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeTemplateMedium; - if (strncmp( mpw_nameForType( MPResultTypeTemplateBasic ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeTemplateBasic; - if (strncmp( mpw_nameForType( MPResultTypeTemplateShort ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeTemplateShort; - if (strncmp( mpw_nameForType( MPResultTypeTemplatePIN ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeTemplatePIN; - if (strncmp( mpw_nameForType( MPResultTypeTemplateName ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeTemplateName; - if (strncmp( mpw_nameForType( MPResultTypeTemplatePhrase ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeTemplatePhrase; - if (strncmp( mpw_nameForType( MPResultTypeStatefulPersonal ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeStatefulPersonal; - if (strncmp( mpw_nameForType( MPResultTypeStatefulDevice ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeStatefulDevice; - if (strncmp( mpw_nameForType( MPResultTypeDeriveKey ), stdTypeName, strlen( stdTypeName ) ) == 0) - return MPResultTypeDeriveKey; - - dbg( "Not a generated type name: %s", stdTypeName ); - return (MPResultType)ERR; -} - -const char *mpw_nameForType(MPResultType resultType) { - - switch (resultType) { - case MPResultTypeTemplateMaximum: - return "maximum"; - case MPResultTypeTemplateLong: - return "long"; - case MPResultTypeTemplateMedium: - return "medium"; - case MPResultTypeTemplateBasic: - return "basic"; - case MPResultTypeTemplateShort: - return "short"; - case MPResultTypeTemplatePIN: - return "pin"; - case MPResultTypeTemplateName: - return "name"; - case MPResultTypeTemplatePhrase: - return "phrase"; - case MPResultTypeStatefulPersonal: - return "personal"; - case MPResultTypeStatefulDevice: - return "device"; - case MPResultTypeDeriveKey: - return "key"; - default: { - dbg( "Unknown password type: %d", resultType ); - return NULL; - } - } -} - -const char **mpw_templatesForType(MPResultType type, size_t *count) { - - if (!(type & MPResultTypeClassTemplate)) { - dbg( "Not a generated type: %d", type ); - return NULL; - } - - switch (type) { - case MPResultTypeTemplateMaximum: - return mpw_alloc_array( count, const char *, - "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" ); - case MPResultTypeTemplateLong: - return mpw_alloc_array( count, const char *, - "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", - "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", - "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", - "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", - "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", - "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", - "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" ); - case MPResultTypeTemplateMedium: - return mpw_alloc_array( count, const char *, - "CvcnoCvc", "CvcCvcno" ); - case MPResultTypeTemplateBasic: - return mpw_alloc_array( count, const char *, - "aaanaaan", "aannaaan", "aaannaaa" ); - case MPResultTypeTemplateShort: - return mpw_alloc_array( count, const char *, - "Cvcn" ); - case MPResultTypeTemplatePIN: - return mpw_alloc_array( count, const char *, - "nnnn" ); - case MPResultTypeTemplateName: - return mpw_alloc_array( count, const char *, - "cvccvcvcv" ); - case MPResultTypeTemplatePhrase: - return mpw_alloc_array( count, const char *, - "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" ); - default: { - dbg( "Unknown generated type: %d", type ); - return NULL; - } - } -} - -const char *mpw_templateForType(MPResultType type, uint8_t templateIndex) { - - size_t count = 0; - const char **templates = mpw_templatesForType( type, &count ); - char const *template = templates && count? templates[templateIndex % count]: NULL; - free( templates ); - - return template; -} - -const MPKeyPurpose mpw_purposeWithName(const char *purposeName) { - - // Lower-case and trim optionally leading "generated" string from typeName to standardize it. - size_t stdPurposeNameSize = strlen( purposeName ); - char stdPurposeName[stdPurposeNameSize + 1]; - for (size_t c = 0; c < stdPurposeNameSize; ++c) - stdPurposeName[c] = (char)tolower( purposeName[c] ); - stdPurposeName[stdPurposeNameSize] = '\0'; - - if (strncmp( mpw_nameForPurpose( MPKeyPurposeAuthentication ), stdPurposeName, strlen( stdPurposeName ) ) == 0) - return MPKeyPurposeAuthentication; - if (strncmp( mpw_nameForPurpose( MPKeyPurposeIdentification ), stdPurposeName, strlen( stdPurposeName ) ) == 0) - return MPKeyPurposeIdentification; - if (strncmp( mpw_nameForPurpose( MPKeyPurposeRecovery ), stdPurposeName, strlen( stdPurposeName ) ) == 0) - return MPKeyPurposeRecovery; - - dbg( "Not a purpose name: %s", stdPurposeName ); - return (MPKeyPurpose)ERR; -} - -const char *mpw_nameForPurpose(MPKeyPurpose purpose) { - - switch (purpose) { - case MPKeyPurposeAuthentication: - return "authentication"; - case MPKeyPurposeIdentification: - return "identification"; - case MPKeyPurposeRecovery: - return "recovery"; - default: { - dbg( "Unknown purpose: %d", purpose ); - return NULL; - } - } -} - -const char *mpw_scopeForPurpose(MPKeyPurpose purpose) { - - switch (purpose) { - case MPKeyPurposeAuthentication: - return "com.lyndir.masterpassword"; - case MPKeyPurposeIdentification: - return "com.lyndir.masterpassword.login"; - case MPKeyPurposeRecovery: - return "com.lyndir.masterpassword.answer"; - default: { - dbg( "Unknown purpose: %d", purpose ); - return NULL; - } - } -} - -const char *mpw_charactersInClass(char characterClass) { - - switch (characterClass) { - case 'V': - return "AEIOU"; - case 'C': - return "BCDFGHJKLMNPQRSTVWXYZ"; - case 'v': - return "aeiou"; - case 'c': - return "bcdfghjklmnpqrstvwxyz"; - case 'A': - return "AEIOUBCDFGHJKLMNPQRSTVWXYZ"; - case 'a': - return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz"; - case 'n': - return "0123456789"; - case 'o': - return "@&%?,=[]_:-+*$#!'^~;()/."; - case 'x': - return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()"; - case ' ': - return " "; - default: { - dbg( "Unknown character class: %c", characterClass ); - return NULL; - } - } -} - -const char mpw_characterFromClass(char characterClass, uint8_t seedByte) { - - const char *classCharacters = mpw_charactersInClass( characterClass ); - if (!classCharacters) - return '\0'; - - return classCharacters[seedByte % strlen( classCharacters )]; -} diff --git a/core/c/mpw-types.h b/core/c/mpw-types.h deleted file mode 100644 index 95208040..00000000 --- a/core/c/mpw-types.h +++ /dev/null @@ -1,180 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#ifndef _MPW_TYPES_H -#define _MPW_TYPES_H - -#include -#include -#include - -#ifdef NS_ENUM -#define mpw_enum(_type, _name) NS_ENUM(_type, _name) -#else -#define mpw_enum(_type, _name) _type _name; enum -#endif - -#ifndef __unused -#define __unused __attribute__((unused)) -#endif - -//// Types. - -extern const size_t MPMasterKeySize, MPSiteKeySize; /* bytes */ -typedef const uint8_t *MPMasterKey, *MPSiteKey; -typedef const char *MPKeyID; - -typedef mpw_enum( uint8_t, MPKeyPurpose ) { - /** Generate a key for authentication. */ - MPKeyPurposeAuthentication, - /** Generate a name for identification. */ - MPKeyPurposeIdentification, - /** Generate a recovery token. */ - MPKeyPurposeRecovery, -}; - -// bit 4 - 9 -typedef mpw_enum( uint16_t, MPResultTypeClass ) { - /** Use the site key to generate a password from a template. */ - MPResultTypeClassTemplate = 1 << 4, - /** Use the site key to encrypt and decrypt a stateful entity. */ - MPResultTypeClassStateful = 1 << 5, - /** Use the site key to derive a site-specific object. */ - MPResultTypeClassDerive = 1 << 6, -}; - -// bit 10 - 15 -typedef mpw_enum( uint16_t, MPSiteFeature ) { - /** Export the key-protected content data. */ - MPSiteFeatureExportContent = 1 << 10, - /** Never export content. */ - MPSiteFeatureDevicePrivate = 1 << 11, - /** Don't use this as the primary authentication result type. */ - MPSiteFeatureAlternative = 1 << 12, -}; - -// bit 0-3 | MPResultTypeClass | MPSiteFeature -typedef mpw_enum( uint32_t, MPResultType ) { - /** 16: pg^VMAUBk5x3p%HP%i4= */ - MPResultTypeTemplateMaximum = 0x0 | MPResultTypeClassTemplate | 0x0, - /** 17: BiroYena8:Kixa */ - MPResultTypeTemplateLong = 0x1 | MPResultTypeClassTemplate | 0x0, - /** 18: BirSuj0- */ - MPResultTypeTemplateMedium = 0x2 | MPResultTypeClassTemplate | 0x0, - /** 19: Bir8 */ - MPResultTypeTemplateShort = 0x3 | MPResultTypeClassTemplate | 0x0, - /** 20: pO98MoD0 */ - MPResultTypeTemplateBasic = 0x4 | MPResultTypeClassTemplate | 0x0, - /** 21: 2798 */ - MPResultTypeTemplatePIN = 0x5 | MPResultTypeClassTemplate | 0x0, - /** 30: birsujano */ - MPResultTypeTemplateName = 0xE | MPResultTypeClassTemplate | 0x0, - /** 31: bir yennoquce fefi */ - MPResultTypeTemplatePhrase = 0xF | MPResultTypeClassTemplate | 0x0, - - /** 1056: Custom saved password. */ - MPResultTypeStatefulPersonal = 0x0 | MPResultTypeClassStateful | MPSiteFeatureExportContent, - /** 2081: Custom saved password that should not be exported from the device. */ - MPResultTypeStatefulDevice = 0x1 | MPResultTypeClassStateful | MPSiteFeatureDevicePrivate, - - /** 4160: Derive a unique binary key. */ - MPResultTypeDeriveKey = 0x0 | MPResultTypeClassDerive | MPSiteFeatureAlternative, - - MPResultTypeDefault = MPResultTypeTemplateLong, -}; - -typedef mpw_enum ( uint32_t, MPCounterValue ) { - /** Use a time-based counter value, resulting in a TOTP generator. */ - MPCounterValueTOTP = 0, - /** The initial value for a site's counter. */ - MPCounterValueInitial = 1, - - MPCounterValueDefault = MPCounterValueInitial, - MPCounterValueFirst = MPCounterValueTOTP, - MPCounterValueLast = UINT32_MAX, -}; - -/** These colours are compatible with the original ANSI SGR. */ -typedef mpw_enum( uint8_t, MPIdenticonColor ) { - MPIdenticonColorRed = 1, - MPIdenticonColorGreen, - MPIdenticonColorYellow, - MPIdenticonColorBlue, - MPIdenticonColorMagenta, - MPIdenticonColorCyan, - MPIdenticonColorWhite, - - MPIdenticonColorFirst = MPIdenticonColorRed, - MPIdenticonColorLast = MPIdenticonColorWhite, -}; - -typedef struct { - const char *leftArm; - const char *body; - const char *rightArm; - const char *accessory; - MPIdenticonColor color; -} MPIdenticon; - -//// Type utilities. - -/** - * @return The purpose represented by the given name. - */ -const MPKeyPurpose mpw_purposeWithName(const char *purposeName); -/** - * @return The standard name for the given purpose. - */ -const char *mpw_nameForPurpose(MPKeyPurpose purpose); -/** - * @return An internal string containing the scope identifier to apply when encoding for the given purpose. - */ -const char *mpw_scopeForPurpose(MPKeyPurpose purpose); - -/** - * @return The password type represented by the given name. - */ -const MPResultType mpw_typeWithName(const char *typeName); -/** - * @return The standard name for the given password type. - */ -const char *mpw_nameForType(MPResultType resultType); - -/** - * @return A newly allocated array of internal strings that express the templates to use for the given type. - * The amount of elements in the array is stored in count. - * If an unsupported type is given, count will be 0 and will return NULL. -* The array needs to be free'ed, the strings themselves must not be free'ed or modified. - */ -const char **mpw_templatesForType(MPResultType type, size_t *count); -/** - * @return An internal string that contains the password encoding template of the given type - * for a seed that starts with the given byte. - */ -const char *mpw_templateForType(MPResultType type, uint8_t templateIndex); - -/** - * @return An internal string that contains all the characters that occur in the given character class. - */ -const char *mpw_charactersInClass(char characterClass); -/** - * @return A character from given character class that encodes the given byte. - */ -const char mpw_characterFromClass(char characterClass, uint8_t seedByte); - -#endif // _MPW_TYPES_H diff --git a/core/c/mpw-util.c b/core/c/mpw-util.c deleted file mode 100644 index 1eca80ae..00000000 --- a/core/c/mpw-util.c +++ /dev/null @@ -1,498 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#include -#include -#include - -#if MPW_CPERCIVA -#include -#include -#elif MPW_SODIUM -#include "sodium.h" -#endif -#define AES_ECB 0 -#define AES_CBC 1 -#include "aes.h" - -#include "mpw-util.h" - -#ifdef inf_level -int mpw_verbosity = inf_level; -#endif - -void mpw_uint16(const uint16_t number, uint8_t buf[2]) { - - buf[0] = (uint8_t)((number >> 8L) & UINT8_MAX); - buf[1] = (uint8_t)((number >> 0L) & UINT8_MAX); -} - -void mpw_uint32(const uint32_t number, uint8_t buf[4]) { - - buf[0] = (uint8_t)((number >> 24) & UINT8_MAX); - buf[1] = (uint8_t)((number >> 16) & UINT8_MAX); - buf[2] = (uint8_t)((number >> 8L) & UINT8_MAX); - buf[3] = (uint8_t)((number >> 0L) & UINT8_MAX); -} - -void mpw_uint64(const uint64_t number, uint8_t buf[8]) { - - buf[0] = (uint8_t)((number >> 56) & UINT8_MAX); - buf[1] = (uint8_t)((number >> 48) & UINT8_MAX); - buf[2] = (uint8_t)((number >> 40) & UINT8_MAX); - buf[3] = (uint8_t)((number >> 32) & UINT8_MAX); - buf[4] = (uint8_t)((number >> 24) & UINT8_MAX); - buf[5] = (uint8_t)((number >> 16) & UINT8_MAX); - buf[6] = (uint8_t)((number >> 8L) & UINT8_MAX); - buf[7] = (uint8_t)((number >> 0L) & UINT8_MAX); -} - -bool mpw_push_buf(uint8_t **buffer, size_t *bufferSize, const void *pushBuffer, const size_t pushSize) { - - if (!buffer || !bufferSize || !pushBuffer || !pushSize) - return false; - if (*bufferSize == (size_t)ERR) - // The buffer was marked as broken, it is missing a previous push. Abort to avoid corrupt content. - return false; - - if (!mpw_realloc( buffer, bufferSize, pushSize )) { - // realloc failed, we can't push. Mark the buffer as broken. - mpw_free( buffer, *bufferSize ); - *bufferSize = (size_t)ERR; - return false; - } - - uint8_t *bufferOffset = *buffer + *bufferSize - pushSize; - memcpy( bufferOffset, pushBuffer, pushSize ); - return true; -} - -bool mpw_push_string(uint8_t **buffer, size_t *bufferSize, const char *pushString) { - - return pushString && mpw_push_buf( buffer, bufferSize, pushString, strlen( pushString ) ); -} - -bool mpw_string_push(char **string, const char *pushString) { - - if (!string || !pushString) - return false; - if (!*string) - *string = calloc( 1, sizeof( char ) ); - - size_t stringLength = strlen( *string ); - return pushString && mpw_push_buf( (uint8_t **const)string, &stringLength, pushString, strlen( pushString ) + 1 ); -} - -bool mpw_string_pushf(char **string, const char *pushFormat, ...) { - - va_list args; - va_start( args, pushFormat ); - bool success = mpw_string_push( string, mpw_vstr( pushFormat, args ) ); - va_end( args ); - - return success; -} - -bool mpw_push_int(uint8_t **buffer, size_t *bufferSize, const uint32_t pushInt) { - - uint8_t pushBuf[4 /* 32 / 8 */]; - mpw_uint32( pushInt, pushBuf ); - return mpw_push_buf( buffer, bufferSize, &pushBuf, sizeof( pushBuf ) ); -} - -bool __mpw_realloc(const void **buffer, size_t *bufferSize, const size_t deltaSize) { - - if (!buffer) - return false; - - void *newBuffer = realloc( (void *)*buffer, (bufferSize? *bufferSize: 0) + deltaSize ); - if (!newBuffer) - return false; - - *buffer = newBuffer; - if (bufferSize) - *bufferSize += deltaSize; - - return true; -} - -void mpw_zero(void *buffer, size_t bufferSize) { - - uint8_t *b = buffer; - for (; bufferSize > 0; --bufferSize) - *b++ = 0; -} - -bool __mpw_free(void **buffer, const size_t bufferSize) { - - if (!buffer || !*buffer) - return false; - - mpw_zero( *buffer, bufferSize ); - free( *buffer ); - *buffer = NULL; - - return true; -} - -bool __mpw_free_string(char **string) { - - return *string && __mpw_free( (void **)string, strlen( *string ) ); -} - -bool __mpw_free_strings(char **strings, ...) { - - bool success = true; - - va_list args; - va_start( args, strings ); - success &= mpw_free_string( strings ); - for (char **string; (string = va_arg( args, char ** ));) - success &= mpw_free_string( string ); - va_end( args ); - - return success; -} - -uint8_t const *mpw_kdf_scrypt(const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize, - uint64_t N, uint32_t r, uint32_t p) { - - if (!secret || !salt) - return NULL; - - uint8_t *key = malloc( keySize ); - if (!key) - return NULL; - -#if MPW_CPERCIVA - if (crypto_scrypt( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize ) < 0) { - mpw_free( &key, keySize ); - return NULL; - } -#elif MPW_SODIUM - if (crypto_pwhash_scryptsalsa208sha256_ll( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize ) != 0) { - mpw_free( &key, keySize ); - return NULL; - } -#else -#error No crypto support for mpw_scrypt. -#endif - - return key; -} - -uint8_t const *mpw_kdf_blake2b(const size_t subkeySize, const uint8_t *key, const size_t keySize, - const uint8_t *context, const size_t contextSize, const uint64_t id, const char *personal) { - - if (!key || !keySize || !subkeySize) { - errno = EINVAL; - return NULL; - } - - uint8_t *subkey = malloc( subkeySize ); - if (!subkey) - return NULL; - -#if MPW_SODIUM - if (keySize < crypto_generichash_blake2b_KEYBYTES_MIN || keySize > crypto_generichash_blake2b_KEYBYTES_MAX || - subkeySize < crypto_generichash_blake2b_KEYBYTES_MIN || subkeySize > crypto_generichash_blake2b_KEYBYTES_MAX || - (personal && strlen( personal ) > crypto_generichash_blake2b_PERSONALBYTES)) { - errno = EINVAL; - free( subkey ); - return NULL; - } - - uint8_t saltBuf[crypto_generichash_blake2b_SALTBYTES]; - mpw_zero( saltBuf, sizeof saltBuf ); - if (id) - mpw_uint64( id, saltBuf ); - - uint8_t personalBuf[crypto_generichash_blake2b_PERSONALBYTES]; - mpw_zero( personalBuf, sizeof personalBuf ); - if (personal && strlen( personal )) - memcpy( personalBuf, personal, strlen( personal ) ); - - if (crypto_generichash_blake2b_salt_personal( subkey, subkeySize, context, contextSize, key, keySize, saltBuf, personalBuf ) != 0) { - mpw_free( &subkey, subkeySize ); - return NULL; - } -#else -#error No crypto support for mpw_kdf_blake2b. -#endif - - return subkey; -} - -uint8_t const *mpw_hash_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *message, const size_t messageSize) { - - if (!key || !keySize || !message || !messageSize) - return NULL; - -#if MPW_CPERCIVA - uint8_t *const mac = malloc( 32 ); - if (!mac) - return NULL; - - HMAC_SHA256_Buf( key, keySize, message, messageSize, mac ); -#elif MPW_SODIUM - uint8_t *const mac = malloc( crypto_auth_hmacsha256_BYTES ); - if (!mac) - return NULL; - - crypto_auth_hmacsha256_state state; - if (crypto_auth_hmacsha256_init( &state, key, keySize ) != 0 || - crypto_auth_hmacsha256_update( &state, message, messageSize ) != 0 || - crypto_auth_hmacsha256_final( &state, mac ) != 0) { - mpw_free( &mac, crypto_auth_hmacsha256_BYTES ); - return NULL; - } -#else -#error No crypto support for mpw_hmac_sha256. -#endif - - return mac; -} - -// We do our best to not fail on odd buf's, eg. non-padded cipher texts. -static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t keySize, const uint8_t *buf, size_t *bufSize) { - - if (!key || keySize < 16 || !*bufSize) - return NULL; - - // IV = zero - uint8_t iv[16]; - mpw_zero( iv, sizeof iv ); - - // Add PKCS#7 padding - uint32_t aesSize = ((uint32_t)*bufSize + 15 / 16) * 16; // round up to block size. - if (encrypt && !(*bufSize % 16)) // add pad block if plain text fits block size. - encrypt += 16; - uint8_t aesBuf[aesSize]; - memcpy( aesBuf, buf, *bufSize ); - memset( aesBuf + *bufSize, aesSize - *bufSize, aesSize - *bufSize ); - uint8_t *resultBuf = malloc( aesSize ); - - if (encrypt) - AES_CBC_encrypt_buffer( resultBuf, aesBuf, aesSize, key, iv ); - else - AES_CBC_decrypt_buffer( resultBuf, aesBuf, aesSize, key, iv ); - mpw_zero( aesBuf, aesSize ); - mpw_zero( iv, 16 ); - - // Truncate PKCS#7 padding - if (encrypt) - *bufSize = aesSize; - else if (*bufSize % 16 == 0 && resultBuf[aesSize - 1] < 16) - *bufSize -= resultBuf[aesSize - 1]; - - return resultBuf; -} - -uint8_t const *mpw_aes_encrypt(const uint8_t *key, const size_t keySize, const uint8_t *plainBuf, size_t *bufSize) { - - return mpw_aes( true, key, keySize, plainBuf, bufSize ); -} - -uint8_t const *mpw_aes_decrypt(const uint8_t *key, const size_t keySize, const uint8_t *cipherBuf, size_t *bufSize) { - - return mpw_aes( false, key, keySize, cipherBuf, bufSize ); -} - -#if UNUSED -const char *mpw_hotp(const uint8_t *key, size_t keySize, uint64_t movingFactor, uint8_t digits, uint8_t truncationOffset) { - - // Hash the moving factor with the key. - uint8_t counter[8]; - mpw_uint64( movingFactor, counter ); - uint8_t hash[20]; - hmac_sha1( key, keySize, counter, sizeof( counter ), hash ); - - // Determine the offset to select OTP bytes from. - int offset; - if ((truncationOffset >= 0) && (truncationOffset < (sizeof( hash ) - 4))) - offset = truncationOffset; - else - offset = hash[sizeof( hash ) - 1] & 0xf; - - // Select four bytes from the truncation offset. - uint32_t otp = 0U - | ((hash[offset + 0] & 0x7f) << 24) - | ((hash[offset + 1] & 0xff) << 16) - | ((hash[offset + 2] & 0xff) << 8) - | ((hash[offset + 3] & 0xff) << 0); - - // Render the OTP as `digits` decimal digits. - otp %= (int)pow(10, digits); - return mpw_strdup( mpw_str( "%0*d", digits, otp ) ); -} -#endif - -MPKeyID mpw_id_buf(const void *buf, size_t length) { - - if (!buf) - return ""; - -#if MPW_CPERCIVA - uint8_t hash[32]; - SHA256_Buf( buf, length, hash ); -#elif MPW_SODIUM - uint8_t hash[crypto_hash_sha256_BYTES]; - crypto_hash_sha256( hash, buf, length ); -#else -#error No crypto support for mpw_id_buf. -#endif - - return mpw_hex( hash, sizeof( hash ) / sizeof( uint8_t ) ); -} - -bool mpw_id_buf_equals(const char *id1, const char *id2) { - - size_t size = strlen( id1 ); - if (size != strlen( id2 )) - return false; - - for (size_t c = 0; c < size; ++c) - if (tolower( id1[c] ) != tolower( id2[c] )) - return false; - - return true; -} - -const char *mpw_str(const char *format, ...) { - - va_list args; - va_start( args, format ); - const char *str_str = mpw_vstr( format, args ); - va_end( args ); - - return str_str; -} - -const char *mpw_vstr(const char *format, va_list args) { - - // TODO: We should find a way to get rid of this shared storage medium. - // TODO: Not thread-safe - static char *str_str; - static size_t str_str_max; - if (!str_str && !(str_str = calloc( str_str_max = 1, sizeof( char ) ))) - return NULL; - - do { - va_list args_attempt; - va_copy( args_attempt, args ); - size_t len = (size_t)vsnprintf( str_str, str_str_max, format, args_attempt ); - va_end( args_attempt ); - - if ((int)len < 0) - return NULL; - if (len < str_str_max) - break; - - if (!mpw_realloc( &str_str, &str_str_max, len - str_str_max + 1 )) - return NULL; - } while (true); - - return str_str; -} - -const char *mpw_hex(const void *buf, size_t length) { - - // TODO: We should find a way to get rid of this shared storage medium. - // TODO: Not thread-safe - static char **mpw_hex_buf; - static unsigned int mpw_hex_buf_i; - - if (!mpw_hex_buf) - mpw_hex_buf = calloc( 10, sizeof( char * ) ); - mpw_hex_buf_i = (mpw_hex_buf_i + 1) % 10; - - if (mpw_realloc( &mpw_hex_buf[mpw_hex_buf_i], NULL, length * 2 + 1 )) - for (size_t kH = 0; kH < length; kH++) - sprintf( &(mpw_hex_buf[mpw_hex_buf_i][kH * 2]), "%02X", ((const uint8_t *)buf)[kH] ); - - return mpw_hex_buf[mpw_hex_buf_i]; -} - -const char *mpw_hex_l(uint32_t number) { - - uint8_t buf[4 /* 32 / 8 */]; - buf[0] = (uint8_t)((number >> 24) & UINT8_MAX); - buf[1] = (uint8_t)((number >> 16) & UINT8_MAX); - buf[2] = (uint8_t)((number >> 8L) & UINT8_MAX); - buf[3] = (uint8_t)((number >> 0L) & UINT8_MAX); - return mpw_hex( &buf, sizeof( buf ) ); -} - -/** -* @return the amount of bytes used by UTF-8 to encode a single character that starts with the given byte. -*/ -static int mpw_utf8_sizeof(unsigned char utf8Byte) { - - if (!utf8Byte) - return 0; - if ((utf8Byte & 0x80) == 0) - return 1; - if ((utf8Byte & 0xC0) != 0xC0) - return 0; - if ((utf8Byte & 0xE0) == 0xC0) - return 2; - if ((utf8Byte & 0xF0) == 0xE0) - return 3; - if ((utf8Byte & 0xF8) == 0xF0) - return 4; - - return 0; -} - -const size_t mpw_utf8_strlen(const char *utf8String) { - - size_t charlen = 0; - char *remainingString = (char *)utf8String; - for (int charByteSize; (charByteSize = mpw_utf8_sizeof( (unsigned char)*remainingString )); remainingString += charByteSize) - ++charlen; - - return charlen; -} - -char *mpw_strdup(const char *src) { - - if (!src) - return NULL; - - size_t len = strlen( src ); - char *dst = malloc( len + 1 ); - memcpy( dst, src, len ); - dst[len] = '\0'; - - return dst; -} - -char *mpw_strndup(const char *src, size_t max) { - - if (!src) - return NULL; - - size_t len = 0; - for (; len < max && src[len] != '\0'; ++len); - - char *dst = malloc( len + 1 ); - memcpy( dst, src, len ); - dst[len] = '\0'; - - return dst; -} diff --git a/core/c/mpw-util.h b/core/c/mpw-util.h deleted file mode 100644 index d0d4da96..00000000 --- a/core/c/mpw-util.h +++ /dev/null @@ -1,211 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -#ifndef _MPW_UTIL_H -#define _MPW_UTIL_H - -#include -#include - -#include "mpw-types.h" - -//// Logging. -extern int mpw_verbosity; - -#ifndef mpw_log_do -#define mpw_log_do(level, format, ...) \ - fprintf( stderr, format "\n", ##__VA_ARGS__ ) -#endif - -#ifndef mpw_log -#define mpw_log(level, ...) ({ \ - if (mpw_verbosity >= level) { \ - mpw_log_do( level, ##__VA_ARGS__ ); \ - }; }) -#endif - -#ifndef trc -/** Logging internal state. */ -#define trc_level 3 -#define trc(...) mpw_log( trc_level, ##__VA_ARGS__ ) - -/** Logging state and events interesting when investigating issues. */ -#define dbg_level 2 -#define dbg(...) mpw_log( dbg_level, ##__VA_ARGS__ ) - -/** User messages. */ -#define inf_level 1 -#define inf(...) mpw_log( inf_level, ##__VA_ARGS__ ) - -/** Recoverable issues and user suggestions. */ -#define wrn_level 0 -#define wrn(...) mpw_log( wrn_level, ##__VA_ARGS__ ) - -/** Unrecoverable issues. */ -#define err_level -1 -#define err(...) mpw_log( err_level, ##__VA_ARGS__ ) - -/** Issues that lead to abortion. */ -#define ftl_level -2 -#define ftl(...) mpw_log( ftl_level, ##__VA_ARGS__ ) -#endif - -#ifndef min -#define min(a, b) ({ \ - __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a < _b ? _a : _b; }) -#endif -#ifndef max -#define max(a, b) ({ \ - __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a > _b ? _a : _b; }) -#endif -#ifndef ERR -#define ERR -1 -#endif -#ifndef OK -#define OK 0 -#endif -#ifndef stringify -#define stringify(s) #s -#endif -#ifndef stringify_def -#define stringify_def(s) stringify(s) -#endif - -//// Buffers and memory. - -/** Write a number to a byte buffer using mpw's endianness (big/network endian). */ -void mpw_uint16(const uint16_t number, uint8_t buf[2]); -void mpw_uint32(const uint32_t number, uint8_t buf[4]); -void mpw_uint64(const uint64_t number, uint8_t buf[8]); - -/** Allocate a new array of _type, assign its element count to _count if not NULL and populate it with the varargs. */ -#define mpw_alloc_array(_count, _type, ...) ({ \ - _type stackElements[] = { __VA_ARGS__ }; \ - if (_count) \ - *_count = sizeof( stackElements ) / sizeof( _type ); \ - _type *allocElements = malloc( sizeof( stackElements ) ); \ - memcpy( allocElements, stackElements, sizeof( stackElements ) ); \ - allocElements; \ - }) - -/** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */ -bool mpw_push_buf( - uint8_t **buffer, size_t *bufferSize, const void *pushBuffer, const size_t pushSize); -/** Push a string onto a buffer. reallocs the given buffer and appends the given string. */ -bool mpw_push_string( - uint8_t **buffer, size_t *bufferSize, const char *pushString); -/** Push a string onto another string. reallocs the target string and appends the source string. */ -bool mpw_string_push( - char **string, const char *pushString); -bool mpw_string_pushf( - char **string, const char *pushFormat, ...); -/** Push an integer onto a buffer. reallocs the given buffer and appends the given integer. */ -bool mpw_push_int( - uint8_t **buffer, size_t *bufferSize, const uint32_t pushInt); -/** Reallocate the given buffer from the given size by adding the delta size. - * On success, the buffer size pointer will be updated to the buffer's new size - * and the buffer pointer may be updated to a new memory address. - * On failure, the buffer and pointers will remain unaffected. - * @param buffer A pointer to the buffer to reallocate. - * @param bufferSize A pointer to the buffer's actual size. - * @param deltaSize The amount to increase the buffer's size by. - * @return true if successful, false if reallocation failed. - */ -#define mpw_realloc(buffer, bufferSize, deltaSize) \ - ({ __typeof__(buffer) _b = buffer; const void *__b = *_b; (void)__b; __mpw_realloc( (const void **)_b, bufferSize, deltaSize ); }) -bool __mpw_realloc(const void **buffer, size_t *bufferSize, const size_t deltaSize); -void mpw_zero( - void *buffer, size_t bufferSize); -/** Free a buffer after zero'ing its contents, then set the reference to NULL. */ -#define mpw_free(buffer, bufferSize) \ - ({ __typeof__(buffer) _b = buffer; const void *__b = *_b; (void)__b; __mpw_free( (void **)_b, bufferSize ); }) -bool __mpw_free( - void **buffer, size_t bufferSize); -/** Free a string after zero'ing its contents, then set the reference to NULL. */ -#define mpw_free_string(string) \ - ({ __typeof__(string) _s = string; const char *__s = *_s; (void)__s; __mpw_free_string( (char **)_s ); }) -bool __mpw_free_string( - char **string); -/** Free strings after zero'ing their contents, then set the references to NULL. Terminate the va_list with NULL. */ -#define mpw_free_strings(strings, ...) \ - ({ __typeof__(strings) _s = strings; const char *__s = *_s; (void)__s; __mpw_free_strings( (char **)_s, __VA_ARGS__ ); }) -bool __mpw_free_strings( - char **strings, ...); - -//// Cryptographic functions. - -/** Derive a key from the given secret and salt using the scrypt KDF. - * @return A new keySize allocated buffer containing the key. */ -uint8_t const *mpw_kdf_scrypt( - const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize, - uint64_t N, uint32_t r, uint32_t p); -/** Derive a subkey from the given key using the blake2b KDF. - * @return A new keySize allocated buffer containing the key. */ -uint8_t const *mpw_kdf_blake2b( - const size_t subkeySize, const uint8_t *key, const size_t keySize, - const uint8_t *context, const size_t contextSize, const uint64_t id, const char *personal); -/** Calculate the MAC for the given message with the given key using SHA256-HMAC. - * @return A new 32-byte allocated buffer containing the MAC. */ -uint8_t const *mpw_hash_hmac_sha256( - const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize); -/** Encrypt a plainBuf with the given key using AES-128-CBC. - * @return A new bufSize allocated buffer containing the cipherBuf. */ -uint8_t const *mpw_aes_encrypt( - const uint8_t *key, const size_t keySize, const uint8_t *plainBuf, size_t *bufSize); -/** Decrypt a cipherBuf with the given key using AES-128-CBC. - * @return A new bufSize allocated buffer containing the plainBuf. */ -uint8_t const *mpw_aes_decrypt( - const uint8_t *key, const size_t keySize, const uint8_t *cipherBuf, size_t *bufSize); -/** Calculate an OTP using RFC-4226. - * @return A newly allocated string containing exactly `digits` decimal OTP digits. */ -#if UNUSED -const char *mpw_hotp( - const uint8_t *key, size_t keySize, uint64_t movingFactor, uint8_t digits, uint8_t truncationOffset); -#endif - -//// Visualizers. - -/** Compose a formatted string. - * @return A C-string in a reused buffer, do not free or store it. */ -const char *mpw_str(const char *format, ...); -const char *mpw_vstr(const char *format, va_list args); -/** Encode a buffer as a string of hexadecimal characters. - * @return A C-string in a reused buffer, do not free or store it. */ -const char *mpw_hex(const void *buf, size_t length); -const char *mpw_hex_l(uint32_t number); -/** Encode a fingerprint for a buffer. - * @return A C-string in a reused buffer, do not free or store it. */ -MPKeyID mpw_id_buf(const void *buf, size_t length); -/** Compare two fingerprints for equality. - * @return true if the buffers represent identical fingerprints. */ -bool mpw_id_buf_equals(const char *id1, const char *id2); - -//// String utilities. - -/** @return The amount of display characters in the given UTF-8 string. */ -const size_t mpw_utf8_strlen(const char *utf8String); -/** Drop-in for POSIX strdup(3). */ -char *mpw_strdup(const char *src); -/** Drop-in for POSIX strndup(3). */ -char *mpw_strndup(const char *src, size_t max); - -#endif // _MPW_UTIL_H diff --git a/core/java/algorithm/build.gradle b/core/java/algorithm/build.gradle deleted file mode 100644 index 59da7457..00000000 --- a/core/java/algorithm/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -plugins { - id 'java' -} - -description = 'Master Password Algorithm Implementation' - -dependencies { - compile (group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.6-p11') { - exclude( module: 'joda-time' ) - } - compile group: 'com.lyndir.lhunath.opal', name: 'opal-crypto', version: '1.6-p11' - - compile group: 'com.lambdaworks', name: 'scrypt', version: '1.4.0' - compile group: 'org.jetbrains', name: 'annotations', version: '13.0' - compile group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1' -} diff --git a/core/java/algorithm/pom.xml b/core/java/algorithm/pom.xml deleted file mode 100644 index b4c41ae2..00000000 --- a/core/java/algorithm/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - 4.0.0 - - - - com.lyndir.masterpassword - masterpassword - GIT-SNAPSHOT - - - Master Password Algorithm Implementation - The implementation of the Master Password algorithm - - masterpassword-algorithm - jar - - - - - - - com.lyndir.lhunath.opal - opal-system - 1.6-p11 - - - joda-time - joda-time - - - - - com.lyndir.lhunath.opal - opal-crypto - 1.6-p11 - - - - - com.lambdaworks - scrypt - 1.4.0 - - - - - diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithm.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithm.java deleted file mode 100644 index 68750fe4..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithm.java +++ /dev/null @@ -1,99 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import com.google.common.base.Charsets; -import com.google.common.primitives.UnsignedInteger; -import com.lyndir.lhunath.opal.system.MessageAuthenticationDigests; -import com.lyndir.lhunath.opal.system.MessageDigests; -import java.io.Serializable; -import java.nio.ByteOrder; -import java.nio.charset.Charset; -import javax.annotation.Nullable; - - -/** - * @see MPMasterKey.Version - */ -public interface MPAlgorithm { - - /** - * mpw: validity for the time-based rolling counter. - */ - int mpw_otp_window = 5 * 60 /* s */; - - /** - * mpw: Key ID hash. - */ - MessageDigests mpw_hash = MessageDigests.SHA256; - - /** - * mpw: Site digest. - */ - MessageAuthenticationDigests mpw_digest = MessageAuthenticationDigests.HmacSHA256; - - /** - * mpw: Platform-agnostic byte order. - */ - ByteOrder mpw_byteOrder = ByteOrder.BIG_ENDIAN; - - /** - * mpw: Input character encoding. - */ - Charset mpw_charset = Charsets.UTF_8; - - /** - * mpw: Master key size (byte). - */ - int mpw_dkLen = 64; - - /** - * scrypt: Parallelization parameter. - */ - int scrypt_p = 2; - - /** - * scrypt: Memory cost parameter. - */ - int scrypt_r = 8; - - /** - * scrypt: CPU cost parameter. - */ - int scrypt_N = 32768; - - MPMasterKey.Version getAlgorithmVersion(); - - byte[] masterKey(String fullName, char[] masterPassword); - - byte[] siteKey(byte[] masterKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose, - @Nullable String keyContext); - - String siteResult(byte[] masterKey, final byte[] siteKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose, - @Nullable String keyContext, MPResultType resultType, @Nullable String resultParam); - - String sitePasswordFromTemplate(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam); - - String sitePasswordFromCrypt(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam); - - String sitePasswordFromDerive(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam); - - String siteState(byte[] masterKey, final byte[] siteKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose, - @Nullable String keyContext, MPResultType resultType, String resultParam); -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV0.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV0.java deleted file mode 100644 index c66182f7..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV0.java +++ /dev/null @@ -1,248 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static com.lyndir.masterpassword.MPUtils.*; - -import com.google.common.base.*; -import com.google.common.primitives.Bytes; -import com.google.common.primitives.UnsignedInteger; -import com.lambdaworks.crypto.SCrypt; -import com.lyndir.lhunath.opal.crypto.CryptUtils; -import com.lyndir.lhunath.opal.system.*; -import com.lyndir.lhunath.opal.system.logging.Logger; -import com.lyndir.lhunath.opal.system.util.ConversionUtils; -import java.nio.*; -import java.security.GeneralSecurityException; -import java.util.Arrays; -import javax.annotation.Nullable; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; - - -/** - * @author lhunath, 2014-08-30 - * @see MPMasterKey.Version#V0 - */ -public class MPAlgorithmV0 implements MPAlgorithm { - - protected final Logger logger = Logger.get( getClass() ); - - @Override - public MPMasterKey.Version getAlgorithmVersion() { - - return MPMasterKey.Version.V0; - } - - @Override - public byte[] masterKey(final String fullName, final char[] masterPassword) { - - byte[] fullNameBytes = fullName.getBytes( mpw_charset ); - byte[] fullNameLengthBytes = bytesForInt( fullName.length() ); - - String keyScope = MPKeyPurpose.Authentication.getScope(); - logger.trc( "keyScope: %s", keyScope ); - - // Calculate the master key salt. - logger.trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s", - keyScope, CodeUtils.encodeHex( fullNameLengthBytes ), fullName ); - byte[] masterKeySalt = Bytes.concat( keyScope.getBytes( mpw_charset ), fullNameLengthBytes, fullNameBytes ); - logger.trc( " => masterKeySalt.id: %s", CodeUtils.encodeHex( idForBytes( masterKeySalt ) ) ); - - // Calculate the master key. - logger.trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%d, r=%d, p=%d )", - scrypt_N, scrypt_r, scrypt_p ); - byte[] masterPasswordBytes = bytesForChars( masterPassword ); - byte[] masterKey = scrypt( masterKeySalt, masterPasswordBytes ); - Arrays.fill( masterKeySalt, (byte) 0 ); - Arrays.fill( masterPasswordBytes, (byte) 0 ); - logger.trc( " => masterKey.id: %s", CodeUtils.encodeHex( idForBytes( masterKey ) ) ); - - return masterKey; - } - - protected byte[] scrypt(final byte[] masterKeySalt, final byte[] mpBytes) { - try { - //if (isAllowNative()) - return SCrypt.scrypt( mpBytes, masterKeySalt, scrypt_N, scrypt_r, scrypt_p, mpw_dkLen ); - //else - // return SCrypt.scryptJ( mpBytes, masterKeySalt, scrypt_N, scrypt_r, scrypt_p, mpw_dkLen ); - } - catch (final GeneralSecurityException e) { - throw logger.bug( e ); - } - } - - @Override - public byte[] siteKey(final byte[] masterKey, final String siteName, UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose, - @Nullable final String keyContext) { - - String keyScope = keyPurpose.getScope(); - logger.trc( "keyScope: %s", keyScope ); - - // OTP counter value. - if (siteCounter.longValue() == 0) - siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (mpw_otp_window * 1000)) * mpw_otp_window ); - - // Calculate the site seed. - byte[] siteNameBytes = siteName.getBytes( mpw_charset ); - byte[] siteNameLengthBytes = bytesForInt( siteName.length() ); - byte[] siteCounterBytes = bytesForInt( siteCounter ); - byte[] keyContextBytes = ((keyContext == null) || keyContext.isEmpty())? null: keyContext.getBytes( mpw_charset ); - byte[] keyContextLengthBytes = (keyContextBytes == null)? null: bytesForInt( keyContextBytes.length ); - logger.trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s", - keyScope, CodeUtils.encodeHex( siteNameLengthBytes ), siteName, CodeUtils.encodeHex( siteCounterBytes ), - (keyContextLengthBytes == null)? null: CodeUtils.encodeHex( keyContextLengthBytes ), keyContext ); - - byte[] sitePasswordInfo = Bytes.concat( keyScope.getBytes( mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes ); - if (keyContextBytes != null) - sitePasswordInfo = Bytes.concat( sitePasswordInfo, keyContextLengthBytes, keyContextBytes ); - logger.trc( " => siteSalt.id: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) ); - - logger.trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )", CodeUtils.encodeHex( idForBytes( masterKey ) ) ); - byte[] sitePasswordSeedBytes = mpw_digest.of( masterKey, sitePasswordInfo ); - logger.trc( " => siteKey.id: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeedBytes ) ) ); - - return sitePasswordSeedBytes; - } - - @Override - public String siteResult(final byte[] masterKey, final byte[] siteKey, final String siteName, final UnsignedInteger siteCounter, - final MPKeyPurpose keyPurpose, - @Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam) { - - switch (resultType.getTypeClass()) { - case Template: - return sitePasswordFromTemplate( masterKey, siteKey, resultType, resultParam ); - case Stateful: - return sitePasswordFromCrypt( masterKey, siteKey, resultType, resultParam ); - case Derive: - return sitePasswordFromDerive( masterKey, siteKey, resultType, resultParam ); - } - - throw logger.bug( "Unsupported result type class: %s", resultType.getTypeClass() ); - } - - @Override - public String sitePasswordFromTemplate(final byte[] masterKey, final byte[] siteKey, final MPResultType resultType, - @Nullable final String resultParam) { - - int[] _siteKey = new int[siteKey.length]; - for (int i = 0; i < siteKey.length; ++i) { - ByteBuffer buf = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( mpw_byteOrder ); - Arrays.fill( buf.array(), (byte) ((siteKey[i] > 0)? 0x00: 0xFF) ); - buf.position( 2 ); - buf.put( siteKey[i] ).rewind(); - _siteKey[i] = buf.getInt() & 0xFFFF; - } - - // Determine the template. - Preconditions.checkState( _siteKey.length > 0 ); - int templateIndex = _siteKey[0]; - MPTemplate template = resultType.getTemplateAtRollingIndex( templateIndex ); - logger.trc( "template: %d => %s", templateIndex, template.getTemplateString() ); - - // Encode the password from the seed using the template. - StringBuilder password = new StringBuilder( template.length() ); - for (int i = 0; i < template.length(); ++i) { - int characterIndex = _siteKey[i + 1]; - MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i ); - char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex ); - logger.trc( " - class: %c, index: %5d (0x%2H) => character: %c", - characterClass.getIdentifier(), characterIndex, _siteKey[i + 1], passwordCharacter ); - - password.append( passwordCharacter ); - } - logger.trc( " => password: %s", password ); - - return password.toString(); - } - - @Override - public String sitePasswordFromCrypt(final byte[] masterKey, final byte[] siteKey, final MPResultType resultType, - @Nullable final String resultParam) { - - Preconditions.checkNotNull( resultParam ); - Preconditions.checkArgument( !resultParam.isEmpty() ); - - try { - // Base64-decode - byte[] cipherBuf = CryptUtils.decodeBase64( resultParam ); - logger.trc( "b64 decoded: %d bytes = %s", cipherBuf.length, CodeUtils.encodeHex( cipherBuf ) ); - - // Decrypt - byte[] plainBuf = CryptUtils.decrypt( cipherBuf, masterKey, true ); - String plainText = mpw_charset.decode( ByteBuffer.wrap( plainBuf ) ).toString(); - logger.trc( "decrypted -> plainText: %d bytes = %s = %s", plainBuf.length, plainText, CodeUtils.encodeHex( plainBuf ) ); - - return plainText; - } - catch (final BadPaddingException e) { - throw Throwables.propagate( e ); - } - } - - @Override - public String sitePasswordFromDerive(final byte[] masterKey, final byte[] siteKey, final MPResultType resultType, - @Nullable final String resultParam) { - - if (resultType == MPResultType.DeriveKey) { - int resultParamInt = ConversionUtils.toIntegerNN( resultParam ); - if (resultParamInt == 0) - resultParamInt = 512; - if ((resultParamInt < 128) || (resultParamInt > 512) || ((resultParamInt % 8) != 0)) - throw logger.bug( "Parameter is not a valid key size (should be 128 - 512): %s", resultParam ); - int keySize = resultParamInt / 8; - logger.trc( "keySize: %d", keySize ); - - // Derive key - byte[] resultKey = null; // TODO: mpw_kdf_blake2b( keySize, siteKey, MPSiteKeySize, NULL, 0, 0, NULL ); - if (resultKey == null) - throw logger.bug( "Could not derive result key." ); - - // Base64-encode - String b64Key = Verify.verifyNotNull( CryptUtils.encodeBase64( resultKey ) ); - logger.trc( "b64 encoded -> key: %s", b64Key ); - - return b64Key; - } else - throw logger.bug( "Unsupported derived password type: %s", resultType ); - } - - @Override - public String siteState(final byte[] masterKey, final byte[] siteKey, final String siteName, final UnsignedInteger siteCounter, - final MPKeyPurpose keyPurpose, - @Nullable final String keyContext, final MPResultType resultType, final String resultParam) { - - try { - // Encrypt - byte[] cipherBuf = CryptUtils.encrypt( resultParam.getBytes( mpw_charset ), masterKey, true ); - logger.trc( "cipherBuf: %d bytes = %s", cipherBuf.length, CodeUtils.encodeHex( cipherBuf ) ); - - // Base64-encode - String cipherText = Verify.verifyNotNull( CryptUtils.encodeBase64( cipherBuf ) ); - logger.trc( "b64 encoded -> cipherText: %s", cipherText ); - - return cipherText; - } - catch (final IllegalBlockSizeException e) { - throw logger.bug( e ); - } - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV1.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV1.java deleted file mode 100644 index 7d1088a0..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV1.java +++ /dev/null @@ -1,62 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import com.google.common.base.Preconditions; -import javax.annotation.Nullable; - - -/** - * @see MPMasterKey.Version#V1 - * - * @author lhunath, 2014-08-30 - */ -public class MPAlgorithmV1 extends MPAlgorithmV0 { - - @Override - public MPMasterKey.Version getAlgorithmVersion() { - - return MPMasterKey.Version.V1; - } - - @Override - public String sitePasswordFromTemplate(final byte[] masterKey, final byte[] siteKey, final MPResultType resultType, @Nullable final String resultParam) { - - // Determine the template. - Preconditions.checkState( siteKey.length > 0 ); - int templateIndex = siteKey[0] & 0xFF; // Convert to unsigned int. - MPTemplate template = resultType.getTemplateAtRollingIndex( templateIndex ); - logger.trc( "template: %d => %s", templateIndex, template.getTemplateString() ); - - // Encode the password from the seed using the template. - StringBuilder password = new StringBuilder( template.length() ); - for (int i = 0; i < template.length(); ++i) { - int characterIndex = siteKey[i + 1] & 0xFF; // Convert to unsigned int. - MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i ); - char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex ); - logger.trc( " - class: %c, index: %3d (0x%2H) => character: %c", - characterClass.getIdentifier(), characterIndex, siteKey[i + 1], passwordCharacter ); - - password.append( passwordCharacter ); - } - logger.trc( " => password: %s", password ); - - return password.toString(); - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV2.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV2.java deleted file mode 100644 index f2560dc9..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV2.java +++ /dev/null @@ -1,74 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static com.lyndir.masterpassword.MPUtils.*; - -import com.google.common.primitives.Bytes; -import com.google.common.primitives.UnsignedInteger; -import com.lyndir.lhunath.opal.system.CodeUtils; -import javax.annotation.Nullable; - - -/** - * @see MPMasterKey.Version#V2 - * - * @author lhunath, 2014-08-30 - */ -public class MPAlgorithmV2 extends MPAlgorithmV1 { - - @Override - public MPMasterKey.Version getAlgorithmVersion() { - - return MPMasterKey.Version.V2; - } - - @Override - public byte[] siteKey(final byte[] masterKey, final String siteName, UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose, - @Nullable final String keyContext) { - - String keyScope = keyPurpose.getScope(); - logger.trc( "keyScope: %s", keyScope ); - - // OTP counter value. - if (siteCounter.longValue() == 0) - siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (MPAlgorithm.mpw_otp_window * 1000)) * MPAlgorithm.mpw_otp_window ); - - // Calculate the site seed. - byte[] siteNameBytes = siteName.getBytes( MPAlgorithm.mpw_charset ); - byte[] siteNameLengthBytes = bytesForInt( siteNameBytes.length ); - byte[] siteCounterBytes = bytesForInt( siteCounter ); - byte[] keyContextBytes = ((keyContext == null) || keyContext.isEmpty())? null: keyContext.getBytes( MPAlgorithm.mpw_charset ); - byte[] keyContextLengthBytes = (keyContextBytes == null)? null: bytesForInt( keyContextBytes.length ); - logger.trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s", - keyScope, CodeUtils.encodeHex( siteNameLengthBytes ), siteName, CodeUtils.encodeHex( siteCounterBytes ), - (keyContextLengthBytes == null)? null: CodeUtils.encodeHex( keyContextLengthBytes ), keyContext ); - - byte[] sitePasswordInfo = Bytes.concat( keyScope.getBytes( MPAlgorithm.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes ); - if (keyContextBytes != null) - sitePasswordInfo = Bytes.concat( sitePasswordInfo, keyContextLengthBytes, keyContextBytes ); - logger.trc( " => siteSalt.id: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) ); - - logger.trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )", CodeUtils.encodeHex( idForBytes( masterKey ) ) ); - byte[] sitePasswordSeedBytes = MPAlgorithm.mpw_digest.of( masterKey, sitePasswordInfo ); - logger.trc( " => siteKey.id: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeedBytes ) ) ); - - return sitePasswordSeedBytes; - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV3.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV3.java deleted file mode 100644 index 0379a491..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPAlgorithmV3.java +++ /dev/null @@ -1,67 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static com.lyndir.masterpassword.MPUtils.*; - -import com.google.common.primitives.Bytes; -import com.lyndir.lhunath.opal.system.CodeUtils; -import java.util.Arrays; - - -/** - * @see MPMasterKey.Version#V3 - * - * @author lhunath, 2014-08-30 - */ -public class MPAlgorithmV3 extends MPAlgorithmV2 { - - @Override - public MPMasterKey.Version getAlgorithmVersion() { - - return MPMasterKey.Version.V3; - } - - @Override - public byte[] masterKey(final String fullName, final char[] masterPassword) { - - byte[] fullNameBytes = fullName.getBytes( MPAlgorithm.mpw_charset ); - byte[] fullNameLengthBytes = MPUtils.bytesForInt( fullNameBytes.length ); - - String keyScope = MPKeyPurpose.Authentication.getScope(); - logger.trc( "keyScope: %s", keyScope ); - - // Calculate the master key salt. - logger.trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s", - keyScope, CodeUtils.encodeHex( fullNameLengthBytes ), fullName ); - byte[] masterKeySalt = Bytes.concat( keyScope.getBytes( MPAlgorithm.mpw_charset ), fullNameLengthBytes, fullNameBytes ); - logger.trc( " => masterKeySalt.id: %s", CodeUtils.encodeHex( idForBytes( masterKeySalt ) ) ); - - // Calculate the master key. - logger.trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%d, r=%d, p=%d )", - MPAlgorithm.scrypt_N, MPAlgorithm.scrypt_r, MPAlgorithm.scrypt_p ); - byte[] mpBytes = bytesForChars( masterPassword ); - byte[] masterKey = scrypt( masterKeySalt, mpBytes ); - Arrays.fill( masterKeySalt, (byte) 0 ); - Arrays.fill( mpBytes, (byte) 0 ); - logger.trc( " => masterKey.id: %s", CodeUtils.encodeHex( idForBytes( masterKey ) ) ); - - return masterKey; - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPConstant.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPConstant.java deleted file mode 100644 index b4d3cc9b..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPConstant.java +++ /dev/null @@ -1,46 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; - - -/** - * @author lhunath, 2016-10-29 - */ -public final class MPConstant { - - /* Environment */ - - /** - * mpw: default path to look for run configuration files if the platform default is not desired. - */ - public static final String env_rcDir = "MPW_RCDIR"; - /** - * mpw: permit automatic update checks. - */ - public static final String env_checkUpdates = "MPW_CHECKUPDATES"; - - /* Algorithm */ - - public static final int MS_PER_S = 1000; - - public static final DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTimeNoMillis(); -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPIdenticon.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPIdenticon.java deleted file mode 100644 index 29b19b0e..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPIdenticon.java +++ /dev/null @@ -1,98 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static com.lyndir.lhunath.opal.system.util.StringUtils.*; - -import com.google.common.base.Charsets; -import com.lyndir.lhunath.opal.system.MessageAuthenticationDigests; -import com.lyndir.lhunath.opal.system.logging.Logger; -import java.nio.*; -import java.nio.charset.Charset; -import java.util.Arrays; - - -/** - * @author lhunath, 15-03-29 - */ -public class MPIdenticon { - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( MPIdenticon.class ); - - private static final Charset charset = Charsets.UTF_8; - private static final Color[] colors = { - Color.RED, Color.GREEN, Color.YELLOW, Color.BLUE, Color.MAGENTA, Color.CYAN, Color.MONO }; - private static final char[] leftArm = { '╔', '╚', '╰', '═' }; - private static final char[] rightArm = { '╗', '╝', '╯', '═' }; - private static final char[] body = { '█', '░', '▒', '▓', '☺', '☻' }; - private static final char[] accessory = { - '◈', '◎', '◐', '◑', '◒', '◓', '☀', '☁', '☂', '☃', '☄', '★', '☆', '☎', '☏', '⎈', '⌂', '☘', '☢', '☣', '☕', '⌚', '⌛', '⏰', '⚡', - '⛄', '⛅', '☔', '♔', '♕', '♖', '♗', '♘', '♙', '♚', '♛', '♜', '♝', '♞', '♟', '♨', '♩', '♪', '♫', '⚐', '⚑', '⚔', '⚖', '⚙', '⚠', - '⌘', '⏎', '✄', '✆', '✈', '✉', '✌' }; - - private final String fullName; - private final Color color; - private final String text; - - public MPIdenticon(final String fullName, final String masterPassword) { - this( fullName, masterPassword.toCharArray() ); - } - - @SuppressWarnings("MethodCanBeVariableArityMethod") - public MPIdenticon(final String fullName, final char[] masterPassword) { - this.fullName = fullName; - - byte[] masterPasswordBytes = charset.encode( CharBuffer.wrap( masterPassword ) ).array(); - ByteBuffer identiconSeedBytes = ByteBuffer.wrap( - MessageAuthenticationDigests.HmacSHA256.of( masterPasswordBytes, fullName.getBytes( charset ) ) ); - Arrays.fill( masterPasswordBytes, (byte) 0 ); - - IntBuffer identiconSeedBuffer = IntBuffer.allocate( identiconSeedBytes.capacity() ); - while (identiconSeedBytes.hasRemaining()) - identiconSeedBuffer.put( identiconSeedBytes.get() & 0xFF ); - int[] identiconSeed = identiconSeedBuffer.array(); - - color = colors[identiconSeed[4] % colors.length]; - text = strf( "%c%c%c%c", leftArm[identiconSeed[0] % leftArm.length], body[identiconSeed[1] % body.length], - rightArm[identiconSeed[2] % rightArm.length], accessory[identiconSeed[3] % accessory.length] ); - } - - public String getFullName() { - return fullName; - } - - public String getText() { - return text; - } - - public Color getColor() { - return color; - } - - public enum Color { - RED, - GREEN, - YELLOW, - BLUE, - MAGENTA, - CYAN, - MONO - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPInvalidatedException.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPInvalidatedException.java deleted file mode 100644 index 53802f37..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPInvalidatedException.java +++ /dev/null @@ -1,25 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -/** - * @author lhunath, 2017-09-21 - */ -public class MPInvalidatedException extends Exception { -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPKeyPurpose.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPKeyPurpose.java deleted file mode 100644 index ac068bcd..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPKeyPurpose.java +++ /dev/null @@ -1,97 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import com.lyndir.lhunath.opal.system.logging.Logger; -import java.util.Locale; -import javax.annotation.Nullable; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NonNls; - - -/** - * @author lhunath, 14-12-02 - */ -public enum MPKeyPurpose { - /** - * Generate a key for authentication. - */ - Authentication( "authentication", "Generate a key for authentication.", "com.lyndir.masterpassword" ), - /** - * Generate a name for identification. - */ - Identification( "identification", "Generate a name for identification.", "com.lyndir.masterpassword.login" ), - /** - * Generate a recovery token. - */ - Recovery( "recovery", "Generate a recovery token.", "com.lyndir.masterpassword.answer" ); - - static final Logger logger = Logger.get( MPResultType.class ); - - private final String shortName; - private final String description; - private final String scope; - - MPKeyPurpose(final String shortName, final String description, @NonNls final String scope) { - this.shortName = shortName; - this.description = description; - this.scope = scope; - } - - public String getShortName() { - return shortName; - } - - public String getDescription() { - return description; - } - - public String getScope() { - return scope; - } - - /** - * @param shortNamePrefix The name for the purpose to look up. It is a case insensitive prefix of the purpose's short name. - * - * @return The purpose registered with the given name. - */ - @Nullable - @Contract("!null -> !null") - public static MPKeyPurpose forName(@Nullable final String shortNamePrefix) { - - if (shortNamePrefix == null) - return null; - - for (final MPKeyPurpose type : values()) - if (type.getShortName().toLowerCase( Locale.ROOT ).startsWith( shortNamePrefix.toLowerCase( Locale.ROOT ) )) - return type; - - throw logger.bug( "No purpose for name: %s", shortNamePrefix ); - } - - public static MPKeyPurpose forInt(final int keyPurpose) { - - return values()[keyPurpose]; - } - - public int toInt() { - - return ordinal(); - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPMasterKey.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPMasterKey.java deleted file mode 100644 index f784a246..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPMasterKey.java +++ /dev/null @@ -1,246 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static com.lyndir.masterpassword.MPUtils.*; - -import com.google.common.base.Preconditions; -import com.google.common.primitives.UnsignedInteger; -import com.lyndir.lhunath.opal.system.CodeUtils; -import com.lyndir.lhunath.opal.system.logging.Logger; -import java.util.Arrays; -import java.util.EnumMap; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - - -/** - * @author lhunath, 2014-08-30 - */ -public class MPMasterKey { - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( MPMasterKey.class ); - - private final EnumMap keyByVersion = new EnumMap<>( Version.class ); - private final String fullName; - private final char[] masterPassword; - - private boolean invalidated; - - /** - * @param masterPassword The characters of the user's master password. Note: this array is held by reference and its contents - * invalidated on {@link #invalidate()}. - */ - @SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter") - public MPMasterKey(final String fullName, final char[] masterPassword) { - - this.fullName = fullName; - this.masterPassword = masterPassword; - } - - /** - * Derive the master key for a user based on their name and master password. - * - * @throws MPInvalidatedException {@link #invalidate()} has been called on this object. - */ - private byte[] masterKey(final Version algorithmVersion) - throws MPInvalidatedException { - Preconditions.checkArgument( masterPassword.length > 0 ); - - if (invalidated) - throw new MPInvalidatedException(); - - byte[] key = keyByVersion.get( algorithmVersion ); - if (key == null) { - logger.trc( "-- mpw_masterKey (algorithm: %d)", algorithmVersion.toInt() ); - logger.trc( "fullName: %s", fullName ); - logger.trc( "masterPassword.id: %s", CodeUtils.encodeHex( idForBytes( bytesForChars( masterPassword ) ) ) ); - - keyByVersion.put( algorithmVersion, key = algorithmVersion.getAlgorithm().masterKey( fullName, masterPassword ) ); - } - - return key; - } - - /** - * Derive the master key for a user based on their name and master password. - * - * @throws MPInvalidatedException {@link #invalidate()} has been called on this object. - */ - private byte[] siteKey(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose, - @Nullable final String keyContext, final Version algorithmVersion) - throws MPInvalidatedException { - Preconditions.checkArgument( !siteName.isEmpty() ); - - byte[] masterKey = masterKey( algorithmVersion ); - - logger.trc( "-- mpw_siteKey (algorithm: %d)", algorithmVersion.toInt() ); - logger.trc( "siteName: %s", siteName ); - logger.trc( "siteCounter: %s", siteCounter ); - logger.trc( "keyPurpose: %d (%s)", keyPurpose.toInt(), keyPurpose.getShortName() ); - logger.trc( "keyContext: %s", keyContext ); - - return algorithmVersion.getAlgorithm().siteKey( masterKey, siteName, siteCounter, keyPurpose, keyContext ); - } - - /** - * Generate a site result token. - * - * @param siteName A site identifier. - * @param siteCounter The result identifier. - * @param keyPurpose The intended purpose for this site result. - * @param keyContext A site-scoped result modifier. - * @param resultType The type of result to generate. - * @param resultParam A parameter for the resultType. For stateful result types, the output of - * {@link #siteState(String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String, Version)}. - * - * @throws MPInvalidatedException {@link #invalidate()} has been called on this object. - */ - public String siteResult(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose, - @Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam, - final Version algorithmVersion) - throws MPInvalidatedException { - - byte[] masterKey = masterKey( algorithmVersion ); - byte[] siteKey = siteKey( siteName, siteCounter, keyPurpose, keyContext, algorithmVersion ); - - logger.trc( "-- mpw_siteResult (algorithm: %d)", algorithmVersion.toInt() ); - logger.trc( "resultType: %d (%s)", resultType.getType(), resultType.getShortName() ); - logger.trc( "resultParam: %s", resultParam ); - - return algorithmVersion.getAlgorithm().siteResult( - masterKey, siteKey, siteName, siteCounter, keyPurpose, keyContext, resultType, resultParam ); - } - - /** - * Encrypt a stateful site token for persistence. - * - * @param siteName A site identifier. - * @param siteCounter The result identifier. - * @param keyPurpose The intended purpose for the site token. - * @param keyContext A site-scoped key modifier. - * @param resultType The type of result token to encrypt. - * @param resultParam The result token desired from - * {@link #siteResult(String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String, Version)}. - * - * @throws MPInvalidatedException {@link #invalidate()} has been called on this object. - */ - public String siteState(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose, - @Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam, - final Version algorithmVersion) - throws MPInvalidatedException { - - Preconditions.checkNotNull( resultParam ); - Preconditions.checkArgument( !resultParam.isEmpty() ); - - byte[] masterKey = masterKey( algorithmVersion ); - byte[] siteKey = siteKey( siteName, siteCounter, keyPurpose, keyContext, algorithmVersion ); - - logger.trc( "-- mpw_siteState (algorithm: %d)", algorithmVersion.toInt() ); - logger.trc( "resultType: %d (%s)", resultType.getType(), resultType.getShortName() ); - logger.trc( "resultParam: %d bytes = %s", resultParam.getBytes( MPAlgorithm.mpw_charset ).length, resultParam ); - - return algorithmVersion.getAlgorithm().siteState( - masterKey, siteKey, siteName, siteCounter, keyPurpose, keyContext, resultType, resultParam ); - } - - @Nonnull - public String getFullName() { - - return fullName; - } - - /** - * Calculate an identifier for the master key. - * - * @throws MPInvalidatedException {@link #invalidate()} has been called on this object. - */ - public byte[] getKeyID(final Version algorithmVersion) - throws MPInvalidatedException { - - return idForBytes( masterKey( algorithmVersion ) ); - } - - /** - * Wipe this key's secrets from memory, making the object permanently unusable. - */ - public void invalidate() { - - invalidated = true; - for (final byte[] key : keyByVersion.values()) - Arrays.fill( key, (byte) 0 ); - Arrays.fill( masterPassword, (char) 0 ); - } - - /** - * The algorithm iterations. - */ - public enum Version { - - /** - * bugs: - * - does math with chars whose signedness was platform-dependent. - * - miscounted the byte-length for multi-byte site names. - * - miscounted the byte-length for multi-byte user names. - */ - V0( new MPAlgorithmV0() ), - - /** - * bugs: - * - miscounted the byte-length for multi-byte site names. - * - miscounted the byte-length for multi-byte user names. - */ - V1( new MPAlgorithmV1() ), - - /** - * bugs: - * - miscounted the byte-length for multi-byte user names. - */ - V2( new MPAlgorithmV2() ), - - /** - * bugs: - * - no known issues. - */ - V3( new MPAlgorithmV3() ); - - public static final Version CURRENT = V3; - - private final MPAlgorithm algorithm; - - Version(final MPAlgorithm algorithm) { - this.algorithm = algorithm; - } - - public MPAlgorithm getAlgorithm() { - return algorithm; - } - - public static Version fromInt(final int algorithmVersion) { - - return values()[algorithmVersion]; - } - - public int toInt() { - - return ordinal(); - } - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPResultType.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPResultType.java deleted file mode 100644 index 1a3ce5eb..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPResultType.java +++ /dev/null @@ -1,252 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -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.*; -import javax.annotation.Nullable; -import org.jetbrains.annotations.Contract; - - -/** - * 07 04, 2012 - * - * @author lhunath - */ -public enum MPResultType { - // bit 0-3 | MPResultTypeClass | MPSiteFeature - - /** - * pg^VMAUBk5x3p%HP%i4= - */ - GeneratedMaximum( "maximum", "20 characters, contains symbols.", // - ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ), - new MPTemplate( "axxxxxxxxxxxxxxxxxno" ) ), // - MPResultTypeClass.Template, 0x0 ), - - /** - * BiroYena8:Kixa - */ - GeneratedLong( "long", "Copy-friendly, 14 characters, contains symbols.", // - ImmutableList.of( new MPTemplate( "CvcvnoCvcvCvcv" ), new MPTemplate( "CvcvCvcvnoCvcv" ), - new MPTemplate( "CvcvCvcvCvcvno" ), new MPTemplate( "CvccnoCvcvCvcv" ), - new MPTemplate( "CvccCvcvnoCvcv" ), new MPTemplate( "CvccCvcvCvcvno" ), - new MPTemplate( "CvcvnoCvccCvcv" ), new MPTemplate( "CvcvCvccnoCvcv" ), - new MPTemplate( "CvcvCvccCvcvno" ), new MPTemplate( "CvcvnoCvcvCvcc" ), - new MPTemplate( "CvcvCvcvnoCvcc" ), new MPTemplate( "CvcvCvcvCvccno" ), - new MPTemplate( "CvccnoCvccCvcv" ), new MPTemplate( "CvccCvccnoCvcv" ), - new MPTemplate( "CvccCvccCvcvno" ), new MPTemplate( "CvcvnoCvccCvcc" ), - new MPTemplate( "CvcvCvccnoCvcc" ), new MPTemplate( "CvcvCvccCvccno" ), - new MPTemplate( "CvccnoCvcvCvcc" ), new MPTemplate( "CvccCvcvnoCvcc" ), - new MPTemplate( "CvccCvcvCvccno" ) ), // - MPResultTypeClass.Template, 0x1 ), - - /** - * BirSuj0- - */ - GeneratedMedium( "medium", "Copy-friendly, 8 characters, contains symbols.", // - ImmutableList.of( new MPTemplate( "CvcnoCvc" ), - new MPTemplate( "CvcCvcno" ) ), // - MPResultTypeClass.Template, 0x2 ), - - /** - * pO98MoD0 - */ - GeneratedBasic( "basic", "8 characters, no symbols.", // - ImmutableList.of( new MPTemplate( "aaanaaan" ), - new MPTemplate( "aannaaan" ), - new MPTemplate( "aaannaaa" ) ), // - MPResultTypeClass.Template, 0x3 ), - - /** - * Bir8 - */ - GeneratedShort( "short", "Copy-friendly, 4 characters, no symbols.", // - ImmutableList.of( new MPTemplate( "Cvcn" ) ), // - MPResultTypeClass.Template, 0x4 ), - - /** - * 2798 - */ - GeneratedPIN( "pin", "4 numbers.", // - ImmutableList.of( new MPTemplate( "nnnn" ) ), // - MPResultTypeClass.Template, 0x5 ), - - /** - * birsujano - */ - GeneratedName( "name", "9 letter name.", // - ImmutableList.of( new MPTemplate( "cvccvcvcv" ) ), // - MPResultTypeClass.Template, 0xE ), - - /** - * bir yennoquce fefi - */ - GeneratedPhrase( "phrase", "20 character sentence.", // - ImmutableList.of( new MPTemplate( "cvcc cvc cvccvcv cvc" ), - new MPTemplate( "cvc cvccvcvcv cvcv" ), - new MPTemplate( "cv cvccv cvc cvcvccv" ) ), // - MPResultTypeClass.Template, 0xF ), - - /** - * Custom saved password. - */ - StoredPersonal( "personal", "AES-encrypted, exportable.", // - ImmutableList.of(), // - MPResultTypeClass.Stateful, 0x0, MPSiteFeature.ExportContent ), - - /** - * Custom saved password that should not be exported from the device. - */ - StoredDevicePrivate( "device", "AES-encrypted, not exported.", // - ImmutableList.of(), // - MPResultTypeClass.Stateful, 0x1, MPSiteFeature.DevicePrivate ), - - /** - * Derive a unique binary key. - */ - DeriveKey( "key", "Encryption key.", // - ImmutableList.of(), // - MPResultTypeClass.Derive, 0x0, MPSiteFeature.Alternative ); - - public static final MPResultType DEFAULT = GeneratedLong; - - static final Logger logger = Logger.get( MPResultType.class ); - - private final String shortName; - private final String description; - private final List templates; - private final MPResultTypeClass typeClass; - private final int typeIndex; - private final Set typeFeatures; - - MPResultType(final String shortName, final String description, final List templates, - final MPResultTypeClass typeClass, final int typeIndex, final MPSiteFeature... typeFeatures) { - - this.shortName = shortName; - this.description = description; - this.templates = templates; - this.typeClass = typeClass; - this.typeIndex = typeIndex; - - ImmutableSet.Builder typeFeaturesBuilder = ImmutableSet.builder(); - for (final MPSiteFeature typeFeature : typeFeatures) { - typeFeaturesBuilder.add( typeFeature ); - } - this.typeFeatures = typeFeaturesBuilder.build(); - } - - public String getShortName() { - return shortName; - } - - public String getDescription() { - - return description; - } - - public MPResultTypeClass getTypeClass() { - - return typeClass; - } - - public Set getTypeFeatures() { - - return typeFeatures; - } - - public int getType() { - int mask = typeIndex | typeClass.getMask(); - for (final MPSiteFeature typeFeature : typeFeatures) - mask |= typeFeature.getMask(); - - return mask; - } - - /** - * @param shortNamePrefix The name for the type to look up. It is a case insensitive prefix of the type's short name. - * - * @return The type registered with the given name. - */ - @Nullable - @Contract("!null -> !null") - public static MPResultType forName(@Nullable final String shortNamePrefix) { - - if (shortNamePrefix == null) - return null; - - for (final MPResultType type : values()) - if (type.getShortName().toLowerCase( Locale.ROOT ).startsWith( shortNamePrefix.toLowerCase( Locale.ROOT ) )) - return type; - - throw logger.bug( "No type for name: %s", shortNamePrefix ); - } - - /** - * @param typeClass The class for which we look up types. - * - * @return All types that support the given class. - */ - public static ImmutableList forClass(final MPResultTypeClass typeClass) { - - ImmutableList.Builder types = ImmutableList.builder(); - for (final MPResultType type : values()) - if (type.getTypeClass() == typeClass) - types.add( type ); - - return types.build(); - } - - /** - * @param type The type for which we look up types. - * - * @return The type registered with the given type. - */ - public static MPResultType forType(final int type) { - - for (final MPResultType resultType : values()) - if (resultType.getType() == type) - return resultType; - - throw logger.bug( "No type: %s", type ); - } - - /** - * @param mask The type mask for which we look up types. - * - * @return All types that support the given mask's class & features. - */ - public static ImmutableList forMask(final int mask) { - - int typeMask = mask & ~0xF; // Ignore resultType bit 0-3 - - ImmutableList.Builder types = ImmutableList.builder(); - for (final MPResultType resultType : values()) - if (((resultType.getType() & ~0xF) & typeMask) != 0) - types.add( resultType ); - - return types.build(); - } - - public MPTemplate getTemplateAtRollingIndex(final int templateIndex) { - return templates.get( templateIndex % templates.size() ); - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPResultTypeClass.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPResultTypeClass.java deleted file mode 100644 index 99d1ac75..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPResultTypeClass.java +++ /dev/null @@ -1,51 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -/** - * 07 04, 2012 - * - * @author lhunath - */ -public enum MPResultTypeClass { - // bit 4 - 9 - - /** - * Use the site key to generate a password from a template. - */ - Template( 1 << 4 ), - /** - * Use the site key to encrypt and decrypt a stateful entity. - */ - Stateful( 1 << 5 ), - /** - * Use the site key to derive a site-specific object. - */ - Derive( 1 << 6 ); - - private final int mask; - - MPResultTypeClass(final int mask) { - this.mask = mask; - } - - public int getMask() { - return mask; - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPSiteFeature.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPSiteFeature.java deleted file mode 100644 index 14c9cf55..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPSiteFeature.java +++ /dev/null @@ -1,53 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -/** - * 07 04, 2012 - * - * @author lhunath - */ -public enum MPSiteFeature { - // bit 10 - 15 - - /** - * Export the key-protected content data. - */ - ExportContent( 1 << 10 ), - - /** - * Never export content. - */ - DevicePrivate( 1 << 11 ), - - /** - * Don't use this as the primary authentication result type. - */ - Alternative( 1 << 12 ); - - MPSiteFeature(final int mask) { - this.mask = mask; - } - - private final int mask; - - public int getMask() { - return mask; - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPTemplate.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPTemplate.java deleted file mode 100644 index 1983ebcc..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPTemplate.java +++ /dev/null @@ -1,70 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static com.lyndir.lhunath.opal.system.util.StringUtils.strf; - -import com.google.common.collect.ImmutableList; -import com.lyndir.lhunath.opal.system.util.MetaObject; -import java.io.Serializable; -import java.util.List; -import org.jetbrains.annotations.NonNls; - - -/** - * 07 04, 2012 - * - * @author lhunath - */ -public class MPTemplate extends MetaObject implements Serializable { - - private static final long serialVersionUID = 1L; - - private final String templateString; - private final List template; - - MPTemplate(@NonNls final String templateString) { - - ImmutableList.Builder builder = ImmutableList.builder(); - for (int i = 0; i < templateString.length(); ++i) - builder.add( MPTemplateCharacterClass.forIdentifier( templateString.charAt( i ) ) ); - - this.templateString = templateString; - template = builder.build(); - } - - public String getTemplateString() { - return templateString; - } - - public MPTemplateCharacterClass getCharacterClassAtIndex(final int index) { - - return template.get( index ); - } - - public int length() { - - return template.size(); - } - - @Override - public String toString() { - return strf( "{MPTemplate: %s}", templateString ); - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPTemplateCharacterClass.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPTemplateCharacterClass.java deleted file mode 100644 index 79a8dff6..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPTemplateCharacterClass.java +++ /dev/null @@ -1,72 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import com.lyndir.lhunath.opal.system.logging.Logger; -import org.jetbrains.annotations.NonNls; - - -/** - * 07 04, 2012 - * - * @author lhunath - */ -public enum MPTemplateCharacterClass { - - UpperVowel( 'V', "AEIOU" ), - UpperConsonant( 'C', "BCDFGHJKLMNPQRSTVWXYZ" ), - LowerVowel( 'v', "aeiou" ), - LowerConsonant( 'c', "bcdfghjklmnpqrstvwxyz" ), - UpperAlphanumeric( 'A', "AEIOUBCDFGHJKLMNPQRSTVWXYZ" ), - Alphanumeric( 'a', "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz" ), - Numeric( 'n', "0123456789" ), - Other( 'o', "@&%?,=[]_:-+*$#!'^~;()/." ), - Any( 'x', "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()" ), - Space( ' ', " " ); - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( MPTemplateCharacterClass.class ); - - private final char identifier; - private final char[] characters; - - MPTemplateCharacterClass(final char identifier, @NonNls final String characters) { - - this.identifier = identifier; - this.characters = characters.toCharArray(); - } - - public char getIdentifier() { - - return identifier; - } - - public char getCharacterAtRollingIndex(final int index) { - - return characters[index % characters.length]; - } - - public static MPTemplateCharacterClass forIdentifier(final char identifier) { - for (final MPTemplateCharacterClass characterClass : values()) - if (characterClass.getIdentifier() == identifier) - return characterClass; - - throw logger.bug( "No character class defined for identifier: %s", identifier ); - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPUtils.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPUtils.java deleted file mode 100644 index 17f3f027..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/MPUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import com.google.common.primitives.UnsignedInteger; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.util.Arrays; - - -/** - * @author lhunath, 2017-09-20 - */ -public final class MPUtils { - - public static byte[] bytesForInt(final int number) { - return ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( MPAlgorithm.mpw_byteOrder ).putInt( number ).array(); - } - - public static byte[] bytesForInt(final UnsignedInteger number) { - return ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( MPAlgorithm.mpw_byteOrder ).putInt( number.intValue() ).array(); - } - - public static byte[] bytesForChars(final char[] characters) { - ByteBuffer byteBuffer = MPAlgorithm.mpw_charset.encode( CharBuffer.wrap( characters ) ); - - byte[] bytes = new byte[byteBuffer.remaining()]; - byteBuffer.get( bytes ); - - Arrays.fill( byteBuffer.array(), (byte) 0 ); - return bytes; - } - - public static byte[] idForBytes(final byte[] bytes) { - return MPAlgorithm.mpw_hash.of( bytes ); - } -} diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/package-info.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/package-info.java deleted file mode 100644 index 0718ec25..00000000 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/package-info.java +++ /dev/null @@ -1,27 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -/** - * - * @author lhunath, 15-02-04 - */ - - -@ParametersAreNonnullByDefault package com.lyndir.masterpassword; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/core/java/model/build.gradle b/core/java/model/build.gradle deleted file mode 100644 index 9c488d26..00000000 --- a/core/java/model/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -plugins { - id 'java' - id 'net.ltgt.apt' version '0.9' -} - -description = 'Master Password Site Model' - -dependencies { - compile project(':masterpassword-algorithm') - - compile group: 'joda-time', name: 'joda-time', version:'2.4' - compileOnly group: 'com.google.auto.value', name: 'auto-value', version: '1.2' - apt group: 'com.google.auto.value', name: 'auto-value', version: '1.2' - - testCompile group: 'org.testng', name: 'testng', version:'6.8.5' - testCompile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2' -} -test.useTestNG() diff --git a/core/java/model/pom.xml b/core/java/model/pom.xml deleted file mode 100644 index 8b22d94c..00000000 --- a/core/java/model/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - 4.0.0 - - - - com.lyndir.masterpassword - masterpassword - GIT-SNAPSHOT - - - Master Password Site Model - A persistence model for Master Password sites. - - masterpassword-model - jar - - - - - - - com.lyndir.masterpassword - masterpassword-algorithm - GIT-SNAPSHOT - - - - - joda-time - joda-time - - - com.google.auto.value - auto-value - 1.0-rc1 - provided - - - - - org.testng - testng - test - - - ch.qos.logback - logback-classic - test - - - - - diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFileSite.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFileSite.java deleted file mode 100644 index a08f9554..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFileSite.java +++ /dev/null @@ -1,205 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import com.google.common.primitives.UnsignedInteger; -import com.lyndir.masterpassword.*; -import javax.annotation.Nullable; -import org.joda.time.Instant; - - -/** - * @author lhunath, 14-12-05 - */ -public class MPFileSite extends MPSite { - - private final MPFileUser user; - private String siteName; - @Nullable - private String siteContent; - private UnsignedInteger siteCounter; - private MPResultType resultType; - private MPMasterKey.Version algorithmVersion; - - @Nullable - private String loginContent; - @Nullable - private MPResultType loginType; - - @Nullable - private String url; - private int uses; - private Instant lastUsed; - - public MPFileSite(final MPFileUser user, final String siteName) { - this( user, siteName, DEFAULT_COUNTER, MPResultType.DEFAULT, MPMasterKey.Version.CURRENT ); - } - - public MPFileSite(final MPFileUser user, final String siteName, final UnsignedInteger siteCounter, final MPResultType resultType, - final MPMasterKey.Version algorithmVersion) { - this.user = user; - this.siteName = siteName; - this.siteCounter = siteCounter; - this.resultType = resultType; - this.algorithmVersion = algorithmVersion; - this.lastUsed = new Instant(); - } - - protected MPFileSite(final MPFileUser user, final String siteName, @Nullable final String siteContent, - final UnsignedInteger siteCounter, - final MPResultType resultType, final MPMasterKey.Version algorithmVersion, - @Nullable final String loginContent, @Nullable final MPResultType loginType, - @Nullable final String url, final int uses, final Instant lastUsed) { - this.user = user; - this.siteName = siteName; - this.siteContent = siteContent; - this.siteCounter = siteCounter; - this.resultType = resultType; - this.algorithmVersion = algorithmVersion; - this.loginContent = loginContent; - this.loginType = loginType; - this.url = url; - this.uses = uses; - this.lastUsed = lastUsed; - } - - public String resultFor(final MPMasterKey masterKey) - throws MPInvalidatedException { - - return resultFor( masterKey, MPKeyPurpose.Authentication, null ); - } - - public String resultFor(final MPMasterKey masterKey, final MPKeyPurpose keyPurpose, @Nullable final String keyContext) - throws MPInvalidatedException { - - return resultFor( masterKey, keyPurpose, keyContext, getSiteContent() ); - } - - public String loginFor(final MPMasterKey masterKey) - throws MPInvalidatedException { - - if (loginType == null) - loginType = MPResultType.GeneratedName; - - return loginFor( masterKey, loginType, loginContent ); - } - - public MPFileUser getUser() { - return user; - } - - @Override - public String getSiteName() { - return siteName; - } - - @Override - public void setSiteName(final String siteName) { - this.siteName = siteName; - } - - @Nullable - public String getSiteContent() { - return siteContent; - } - - public void setSitePassword(final MPMasterKey masterKey, @Nullable final MPResultType resultType, @Nullable final String result) - throws MPInvalidatedException { - this.resultType = resultType; - if (result == null) - this.siteContent = null; - else - this.siteContent = masterKey.siteState( - getSiteName(), getSiteCounter(), MPKeyPurpose.Authentication, null, getResultType(), result, getAlgorithmVersion() ); - } - - @Override - public UnsignedInteger getSiteCounter() { - return siteCounter; - } - - @Override - public void setSiteCounter(final UnsignedInteger siteCounter) { - this.siteCounter = siteCounter; - } - - @Override - public MPResultType getResultType() { - return resultType; - } - - @Override - public void setResultType(final MPResultType resultType) { - this.resultType = resultType; - } - - @Override - public MPMasterKey.Version getAlgorithmVersion() { - return algorithmVersion; - } - - @Override - public void setAlgorithmVersion(final MPMasterKey.Version algorithmVersion) { - this.algorithmVersion = algorithmVersion; - } - - @Nullable - public MPResultType getLoginType() { - return loginType; - } - - @Nullable - public String getLoginContent() { - return loginContent; - } - - public void setLoginName(final MPMasterKey masterKey, @Nullable final MPResultType loginType, @Nullable final String result) - throws MPInvalidatedException { - this.loginType = loginType; - if (this.loginType != null) - if (result == null) - this.loginContent = null; - else - this.loginContent = masterKey.siteState( - siteName, DEFAULT_COUNTER, MPKeyPurpose.Identification, null, this.loginType, result, algorithmVersion ); - } - - @Nullable - public String getUrl() { - return url; - } - - public void setUrl(@Nullable final String url) { - this.url = url; - } - - public int getUses() { - return uses; - } - - public Instant getLastUsed() { - return lastUsed; - } - - public void use() { - uses++; - lastUsed = new Instant(); - user.use(); - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFileUser.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFileUser.java deleted file mode 100755 index e2f428e6..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFileUser.java +++ /dev/null @@ -1,172 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import com.google.common.collect.*; -import com.lyndir.lhunath.opal.system.logging.Logger; -import com.lyndir.masterpassword.*; -import java.util.*; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.joda.time.*; - - -/** - * @author lhunath, 14-12-07 - */ -public class MPFileUser extends MPUser implements Comparable { - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( MPFileUser.class ); - - private final String fullName; - private final Collection sites = Sets.newHashSet(); - - @Nullable - private byte[] keyID; - private MPMasterKey.Version algorithmVersion; - - private int avatar; - private MPResultType defaultType; - private ReadableInstant lastUsed; - - public MPFileUser(final String fullName) { - this( fullName, null, MPMasterKey.Version.CURRENT ); - } - - public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPMasterKey.Version algorithmVersion) { - this( fullName, keyID, algorithmVersion, 0, MPResultType.DEFAULT, new Instant() ); - } - - public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPMasterKey.Version algorithmVersion, final int avatar, - final MPResultType defaultType, final ReadableInstant lastUsed) { - this.fullName = fullName; - this.keyID = (keyID == null)? null: keyID.clone(); - this.algorithmVersion = algorithmVersion; - this.avatar = avatar; - this.defaultType = defaultType; - this.lastUsed = lastUsed; - } - - @Override - public String getFullName() { - return fullName; - } - - @Override - public MPMasterKey.Version getAlgorithmVersion() { - return algorithmVersion; - } - - public void setAlgorithmVersion(final MPMasterKey.Version algorithmVersion) { - this.algorithmVersion = algorithmVersion; - } - - @Override - public int getAvatar() { - return avatar; - } - - public void setAvatar(final int avatar) { - this.avatar = avatar; - } - - public MPResultType getDefaultType() { - return defaultType; - } - - public void setDefaultType(final MPResultType defaultType) { - this.defaultType = defaultType; - } - - public ReadableInstant getLastUsed() { - return lastUsed; - } - - public void use() { - lastUsed = new Instant(); - } - - public Iterable getSites() { - return sites; - } - - @Override - public void addSite(final MPFileSite site) { - sites.add( site ); - } - - @Override - public void deleteSite(final MPFileSite site) { - sites.remove( site ); - } - - @Override - public Collection findSites(final String query) { - ImmutableList.Builder results = ImmutableList.builder(); - for (final MPFileSite site : getSites()) - if (site.getSiteName().startsWith( query )) - results.add( site ); - - return results.build(); - } - - /** - * Performs an authentication attempt against the keyID for this user. - * - * Note: If this user doesn't have a keyID set yet, authentication will always succeed and the key ID will be set as a result. - * - * @param masterPassword The password to authenticate with. - * - * @return The master key for the user if authentication was successful. - * - * @throws MPIncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID. - */ - @Nonnull - @Override - public MPMasterKey authenticate(final char[] masterPassword) - throws MPIncorrectMasterPasswordException { - try { - key = new MPMasterKey( getFullName(), masterPassword ); - if ((keyID == null) || (keyID.length == 0)) - keyID = key.getKeyID( algorithmVersion ); - else if (!Arrays.equals( key.getKeyID( algorithmVersion ), keyID )) - throw new MPIncorrectMasterPasswordException( this ); - - return key; - } - catch (final MPInvalidatedException e) { - throw logger.bug( e ); - } - } - - void save() - throws MPInvalidatedException { - MPFileUserManager.get().save( this, getMasterKey() ); - } - - @Override - public int compareTo(final MPFileUser o) { - int comparison = getLastUsed().compareTo( o.getLastUsed() ); - if (comparison == 0) - comparison = getFullName().compareTo( o.getFullName() ); - - return comparison; - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFileUserManager.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFileUserManager.java deleted file mode 100644 index 2400264d..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFileUserManager.java +++ /dev/null @@ -1,139 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*; - -import com.google.common.base.*; -import com.google.common.collect.*; -import com.google.common.io.CharSink; -import com.lyndir.lhunath.opal.system.logging.Logger; -import com.lyndir.masterpassword.*; -import java.io.*; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - - -/** - * Manages user data stored in user-specific {@code .mpsites} files under {@code .mpw.d}. - * - * @author lhunath, 14-12-07 - */ -public class MPFileUserManager extends MPUserManager { - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( MPFileUserManager.class ); - private static final MPFileUserManager instance; - - static { - String rcDir = System.getenv( MPConstant.env_rcDir ); - if (rcDir != null) - instance = create( new File( rcDir ) ); - else - instance = create( new File( ifNotNullElseNullable( System.getProperty( "user.home" ), System.getenv( "HOME" ) ), ".mpw.d" ) ); - } - - private final File userFilesDirectory; - - public static MPFileUserManager get() { - MPUserManager.instance = instance; - return instance; - } - - public static MPFileUserManager create(final File userFilesDirectory) { - return new MPFileUserManager( userFilesDirectory ); - } - - protected MPFileUserManager(final File userFilesDirectory) { - - super( unmarshallUsers( userFilesDirectory ) ); - this.userFilesDirectory = userFilesDirectory; - } - - private static Iterable unmarshallUsers(final File userFilesDirectory) { - if (!userFilesDirectory.mkdirs() && !userFilesDirectory.isDirectory()) { - logger.err( "Couldn't create directory for user files: %s", userFilesDirectory ); - return ImmutableList.of(); - } - - return FluentIterable.from( listUserFiles( userFilesDirectory ) ).transform( new Function() { - @Nullable - @Override - public MPFileUser apply(@Nullable final File file) { - try { - return new MPFlatUnmarshaller().unmarshall( Preconditions.checkNotNull( file ) ); - } - catch (final IOException e) { - logger.err( e, "Couldn't read user from: %s", file ); - return null; - } - } - } ).filter( Predicates.notNull() ); - } - - private static ImmutableList listUserFiles(final File userFilesDirectory) { - return ImmutableList.copyOf( ifNotNullElse( userFilesDirectory.listFiles( new FilenameFilter() { - @Override - public boolean accept(final File dir, final String name) { - return name.endsWith( ".mpsites" ); - } - } ), new File[0] ) ); - } - - @Override - public void deleteUser(final MPFileUser user) { - super.deleteUser( user ); - - // Remove deleted users. - File userFile = getUserFile( user ); - if (userFile.exists() && !userFile.delete()) - logger.err( "Couldn't delete file: %s", userFile ); - } - - /** - * Write the current user state to disk. - */ - public void save(final MPFileUser user, final MPMasterKey masterKey) - throws MPInvalidatedException { - try { - new CharSink() { - @Override - public Writer openStream() - throws IOException { - return new OutputStreamWriter( new FileOutputStream( getUserFile( user ) ), Charsets.UTF_8 ); - } - }.write( new MPFlatMarshaller().marshall( user, masterKey, MPMarshaller.ContentMode.PROTECTED ) ); - } - catch (final IOException e) { - logger.err( e, "Unable to save sites for user: %s", user ); - } - } - - @Nonnull - private File getUserFile(final MPFileUser user) { - return new File( userFilesDirectory, user.getFullName() + ".mpsites" ); - } - - /** - * @return The location on the file system where the user models are stored. - */ - public File getPath() { - return userFilesDirectory; - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFlatMarshaller.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFlatMarshaller.java deleted file mode 100644 index ac41a400..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFlatMarshaller.java +++ /dev/null @@ -1,80 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse; -import static com.lyndir.lhunath.opal.system.util.StringUtils.strf; - -import com.lyndir.masterpassword.*; -import org.joda.time.Instant; - - -/** - * @author lhunath, 2017-09-20 - */ -public class MPFlatMarshaller implements MPMarshaller { - - private static final int FORMAT = 1; - - @Override - public String marshall(final MPFileUser user, final MPMasterKey masterKey, final ContentMode contentMode) - throws MPInvalidatedException { - StringBuilder content = new StringBuilder(); - content.append( "# Master Password site export\n" ); - content.append( "# " ).append( contentMode.description() ).append( '\n' ); - content.append( "# \n" ); - content.append( "##\n" ); - content.append( "# Format: " ).append( FORMAT ).append( '\n' ); - content.append( "# Date: " ).append( MPConstant.dateTimeFormatter.print( new Instant() ) ).append( '\n' ); - content.append( "# User Name: " ).append( user.getFullName() ).append( '\n' ); - content.append( "# Full Name: " ).append( user.getFullName() ).append( '\n' ); - content.append( "# Avatar: " ).append( user.getAvatar() ).append( '\n' ); - content.append( "# Key ID: " ).append( user.exportKeyID() ).append( '\n' ); - content.append( "# Algorithm: " ).append( MPMasterKey.Version.CURRENT.toInt() ).append( '\n' ); - content.append( "# Default Type: " ).append( user.getDefaultType().getType() ).append( '\n' ); - content.append( "# Passwords: " ).append( contentMode.name() ).append( '\n' ); - content.append( "##\n" ); - content.append( "#\n" ); - content.append( "# Last Times Password Login\t Site\tSite\n" ); - content.append( "# used used type name\t name\tpassword\n" ); - - for (final MPFileSite site : user.getSites()) { - String loginName = site.getLoginContent(); - String password = site.getSiteContent(); - if (!contentMode.isRedacted()) { - loginName = site.loginFor( masterKey ); - password = site.resultFor( masterKey ); - } - - content.append( strf( "%s %8d %8s %25s\t%25s\t%s\n", // - MPConstant.dateTimeFormatter.print( site.getLastUsed() ), // lastUsed - site.getUses(), // uses - strf( "%d:%d:%d", // - site.getResultType().getType(), // type - site.getAlgorithmVersion().toInt(), // algorithm - site.getSiteCounter().intValue() ), // counter - ifNotNullElse( loginName, "" ), // loginName - site.getSiteName(), // siteName - ifNotNullElse( password, "" ) // password - ) ); - } - - return content.toString(); - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFlatUnmarshaller.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFlatUnmarshaller.java deleted file mode 100644 index 639d9b70..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPFlatUnmarshaller.java +++ /dev/null @@ -1,139 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import com.google.common.base.*; -import com.google.common.io.CharStreams; -import com.google.common.primitives.UnsignedInteger; -import com.lyndir.lhunath.opal.system.CodeUtils; -import com.lyndir.lhunath.opal.system.util.ConversionUtils; -import com.lyndir.masterpassword.*; -import java.io.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.annotation.Nonnull; -import org.joda.time.DateTime; - - -/** - * @author lhunath, 14-12-07 - */ -public class MPFlatUnmarshaller implements MPUnmarshaller { - - private static final Pattern[] unmarshallFormats = { - Pattern.compile( "^([^ ]+) +(\\d+) +(\\d+)(:\\d+)? +([^\t]+)\t(.*)" ), - Pattern.compile( "^([^ ]+) +(\\d+) +(\\d+)(:\\d+)?(:\\d+)? +([^\t]*)\t *([^\t]+)\t(.*)" ) }; - private static final Pattern headerFormat = Pattern.compile( "^#\\s*([^:]+): (.*)" ); - private static final Pattern colon = Pattern.compile( ":" ); - - @Nonnull - @Override - public MPFileUser unmarshall(@Nonnull final File file) - throws IOException { - try (Reader reader = new InputStreamReader( new FileInputStream( file ), Charsets.UTF_8 )) { - return unmarshall( CharStreams.toString( reader ) ); - } - } - - @Nonnull - @Override - public MPFileUser unmarshall(@Nonnull final String content) { - MPFileUser user = null; - byte[] keyID = null; - String fullName = null; - int mpVersion = 0, importFormat = 0, avatar = 0; - boolean clearContent = false, headerStarted = false; - MPResultType defaultType = MPResultType.DEFAULT; - - //noinspection HardcodedLineSeparator - for (final String line : Splitter.on( CharMatcher.anyOf( "\r\n" ) ).omitEmptyStrings().split( content )) - // Header delimitor. - if (line.startsWith( "##" )) - if (!headerStarted) - // Starts the header. - headerStarted = true; - else - // Ends the header. - user = new MPFileUser( fullName, keyID, MPMasterKey.Version.fromInt( mpVersion ), avatar, defaultType, new DateTime( 0 ) ); - - // Comment. - else if (line.startsWith( "#" )) { - if (headerStarted && (user == null)) { - // In header. - Matcher headerMatcher = headerFormat.matcher( line ); - if (headerMatcher.matches()) { - String name = headerMatcher.group( 1 ), value = headerMatcher.group( 2 ); - if ("Full Name".equalsIgnoreCase( name ) || "User Name".equalsIgnoreCase( name )) - fullName = value; - else if ("Key ID".equalsIgnoreCase( name )) - keyID = CodeUtils.decodeHex( value ); - else if ("Algorithm".equalsIgnoreCase( name )) - mpVersion = ConversionUtils.toIntegerNN( value ); - else if ("Format".equalsIgnoreCase( name )) - importFormat = ConversionUtils.toIntegerNN( value ); - else if ("Avatar".equalsIgnoreCase( name )) - avatar = ConversionUtils.toIntegerNN( value ); - else if ("Passwords".equalsIgnoreCase( name )) - clearContent = "visible".equalsIgnoreCase( value ); - else if ("Default Type".equalsIgnoreCase( name )) - defaultType = MPResultType.forType( ConversionUtils.toIntegerNN( value ) ); - } - } - } - - // No comment. - else if (user != null) { - Matcher siteMatcher = unmarshallFormats[importFormat].matcher( line ); - if (!siteMatcher.matches()) - return null; - - MPFileSite site; - switch (importFormat) { - case 0: - site = new MPFileSite( user, // - siteMatcher.group( 5 ), siteMatcher.group( 6 ), MPFileSite.DEFAULT_COUNTER, - MPResultType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ), - MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN( - colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ), - null, null, null, ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ), - MPConstant.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() ); - break; - - case 1: - site = new MPFileSite( user, // - siteMatcher.group( 7 ), siteMatcher.group( 8 ), - UnsignedInteger.valueOf( colon.matcher( siteMatcher.group( 5 ) ).replaceAll( "" ) ), - MPResultType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ), - MPMasterKey.Version.fromInt( ConversionUtils.toIntegerNN( - colon.matcher( siteMatcher.group( 4 ) ).replaceAll( "" ) ) ), - siteMatcher.group( 6 ), MPResultType.GeneratedName, null, - ConversionUtils.toIntegerNN( siteMatcher.group( 2 ) ), - MPConstant.dateTimeFormatter.parseDateTime( siteMatcher.group( 1 ) ).toInstant() ); - break; - - default: - throw new UnsupportedOperationException( "Unexpected format: " + importFormat ); - } - - user.addSite( site ); - } - - return Preconditions.checkNotNull( user, "No full header found in import file." ); - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPIncorrectMasterPasswordException.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPIncorrectMasterPasswordException.java deleted file mode 100644 index 7d899b4f..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPIncorrectMasterPasswordException.java +++ /dev/null @@ -1,37 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -/** - * @author lhunath, 14-12-17 - */ -public class MPIncorrectMasterPasswordException extends Exception { - - private final MPFileUser user; - - public MPIncorrectMasterPasswordException(final MPFileUser user) { - super( "Incorrect master password for user: " + user.getFullName() ); - - this.user = user; - } - - public MPFileUser getUser() { - return user; - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPJSONMarshaller.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPJSONMarshaller.java deleted file mode 100644 index 93194bdb..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPJSONMarshaller.java +++ /dev/null @@ -1,34 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import com.lyndir.masterpassword.MPMasterKey; - - -/** - * @author lhunath, 2017-09-20 - */ -public class MPJSONMarshaller implements MPMarshaller { - - @Override - public String marshall(final MPFileUser user, final MPMasterKey masterKey, final ContentMode contentMode) { - // TODO - return null; - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPJSONUnmarshaller.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPJSONUnmarshaller.java deleted file mode 100644 index 8ced1481..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPJSONUnmarshaller.java +++ /dev/null @@ -1,45 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import java.io.File; -import java.io.IOException; -import javax.annotation.Nonnull; - - -/** - * @author lhunath, 2017-09-20 - */ -public class MPJSONUnmarshaller implements MPUnmarshaller { - - @Nonnull - @Override - public MPFileUser unmarshall(@Nonnull final File file) - throws IOException { - // TODO - return null; - } - - @Nonnull - @Override - public MPFileUser unmarshall(@Nonnull final String content) { - // TODO - return null; - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPMarshalFormat.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPMarshalFormat.java deleted file mode 100644 index 0788ff87..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPMarshalFormat.java +++ /dev/null @@ -1,60 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -/** - * @author lhunath, 2017-09-20 - */ -public enum MPMarshalFormat { - /** - * Marshal using the line-based plain-text format. - */ - Flat { - @Override - public MPMarshaller marshaller() { - return new MPFlatMarshaller(); - } - - @Override - public MPUnmarshaller unmarshaller() { - return new MPFlatUnmarshaller(); - } - }, - - /** - * Marshal using the JSON structured format. - */ - JSON { - @Override - public MPMarshaller marshaller() { - return new MPJSONMarshaller(); - } - - @Override - public MPUnmarshaller unmarshaller() { - return new MPJSONUnmarshaller(); - } - }; - - public static final MPMarshalFormat DEFAULT = JSON; - - public abstract MPMarshaller marshaller(); - - public abstract MPUnmarshaller unmarshaller(); -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPMarshaller.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPMarshaller.java deleted file mode 100644 index 609f4ad8..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPMarshaller.java +++ /dev/null @@ -1,52 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import com.lyndir.masterpassword.MPInvalidatedException; -import com.lyndir.masterpassword.MPMasterKey; - - -/** - * @author lhunath, 14-12-07 - */ -public interface MPMarshaller { - - String marshall(MPFileUser user, MPMasterKey masterKey, ContentMode contentMode) - throws MPInvalidatedException; - - enum ContentMode { - PROTECTED( "Export of site names and stored passwords (unless device-private) encrypted with the master key." ), - VISIBLE( "Export of site names and passwords in clear-text." ); - - private final String description; - private boolean redacted; - - ContentMode(final String description) { - this.description = description; - } - - public String description() { - return description; - } - - public boolean isRedacted() { - return redacted; - } - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPSite.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPSite.java deleted file mode 100644 index 9165b55d..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPSite.java +++ /dev/null @@ -1,81 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import static com.lyndir.lhunath.opal.system.util.StringUtils.strf; - -import com.google.common.primitives.UnsignedInteger; -import com.lyndir.masterpassword.*; -import java.util.Objects; -import javax.annotation.Nullable; - - -/** - * @author lhunath, 14-12-16 - */ -public abstract class MPSite { - - public static final UnsignedInteger DEFAULT_COUNTER = UnsignedInteger.ONE; - - public abstract String getSiteName(); - - public abstract void setSiteName(String siteName); - - public abstract UnsignedInteger getSiteCounter(); - - public abstract void setSiteCounter(UnsignedInteger siteCounter); - - public abstract MPResultType getResultType(); - - public abstract void setResultType(MPResultType resultType); - - public abstract MPMasterKey.Version getAlgorithmVersion(); - - public abstract void setAlgorithmVersion(MPMasterKey.Version algorithmVersion); - - public String resultFor(final MPMasterKey masterKey, final MPKeyPurpose keyPurpose, @Nullable final String keyContext, - @Nullable final String siteContent) - throws MPInvalidatedException { - - return masterKey.siteResult( - getSiteName(), getSiteCounter(), keyPurpose, keyContext, getResultType(), siteContent, getAlgorithmVersion() ); - } - - public String loginFor(final MPMasterKey masterKey, final MPResultType loginType, @Nullable final String loginContent) - throws MPInvalidatedException { - - return masterKey.siteResult( - getSiteName(), DEFAULT_COUNTER, MPKeyPurpose.Identification, null, loginType, loginContent, getAlgorithmVersion() ); - } - - @Override - public boolean equals(final Object obj) { - return (this == obj) || ((obj instanceof MPSite) && Objects.equals( getSiteName(), ((MPSite) obj).getSiteName() )); - } - - @Override - public int hashCode() { - return Objects.hashCode( getSiteName() ); - } - - @Override - public String toString() { - return strf( "{%s: %s}", getClass().getSimpleName(), getSiteName() ); - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPSiteResult.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPSiteResult.java deleted file mode 100644 index 646a0f21..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPSiteResult.java +++ /dev/null @@ -1,55 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import static com.lyndir.lhunath.opal.system.util.StringUtils.strf; - -import java.util.Objects; - - -/** - * @author lhunath, 14-12-07 - */ -public class MPSiteResult { - - private final MPFileSite site; - - public MPSiteResult(final MPFileSite site) { - this.site = site; - } - - public MPFileSite getSite() { - return site; - } - - @Override - public boolean equals(final Object obj) { - return (this == obj) || ((obj instanceof MPSiteResult) && Objects.equals( site, ((MPSiteResult) obj).site )); - } - - @Override - public int hashCode() { - return Objects.hashCode( site ); - } - - @Override - public String toString() { - return strf( "{MPSiteResult: %s}", site ); - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUnmarshaller.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUnmarshaller.java deleted file mode 100644 index 97a966a1..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUnmarshaller.java +++ /dev/null @@ -1,36 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import java.io.*; -import javax.annotation.Nonnull; - - -/** - * @author lhunath, 14-12-07 - */ -public interface MPUnmarshaller { - - @Nonnull - MPFileUser unmarshall(@Nonnull File file) - throws IOException; - - @Nonnull - MPFileUser unmarshall(@Nonnull String content); -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java deleted file mode 100755 index 87c0bdde..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java +++ /dev/null @@ -1,86 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import static com.lyndir.lhunath.opal.system.util.StringUtils.strf; - -import com.google.common.base.Preconditions; -import com.lyndir.lhunath.opal.system.CodeUtils; -import com.lyndir.masterpassword.MPInvalidatedException; -import com.lyndir.masterpassword.MPMasterKey; -import java.util.*; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - - -/** - * @author lhunath, 2014-06-08 - */ -public abstract class MPUser { - - @Nullable - protected MPMasterKey key; - - public abstract String getFullName(); - - public boolean isMasterKeyAvailable() { - return key != null; - } - - @Nonnull - public MPMasterKey getMasterKey() { - return Preconditions.checkNotNull( key, "User is not authenticated: " + getFullName() ); - } - - public String exportKeyID() - throws MPInvalidatedException { - return CodeUtils.encodeHex( getMasterKey().getKeyID( getAlgorithmVersion() ) ); - } - - public abstract MPMasterKey.Version getAlgorithmVersion(); - - public int getAvatar() { - return 0; - } - - public abstract void addSite(S site); - - public abstract void deleteSite(S site); - - public abstract Collection findSites(String query); - - @Nonnull - public abstract MPMasterKey authenticate(char[] masterPassword) - throws MPIncorrectMasterPasswordException; - - @Override - public int hashCode() { - return Objects.hashCode( getFullName() ); - } - - @Override - public boolean equals(final Object obj) { - return (this == obj) || ((obj instanceof MPUser) && Objects.equals( getFullName(), ((MPUser) obj).getFullName() )); - } - - @Override - public String toString() { - return strf( "{%s: %s}", getClass().getSimpleName(), getFullName() ); - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUserManager.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUserManager.java deleted file mode 100644 index 8ff40074..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/MPUserManager.java +++ /dev/null @@ -1,58 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword.model; - -import com.google.common.collect.*; -import com.lyndir.masterpassword.MPInvalidatedException; -import java.util.*; - - -/** - * @author lhunath, 14-12-05 - */ -public abstract class MPUserManager { - - private final Map usersByName = Maps.newHashMap(); - static MPUserManager instance; - - public static MPUserManager get() { - return instance; - } - - protected MPUserManager(final Iterable users) { - for (final MPFileUser user : users) - usersByName.put( user.getFullName(), user ); - } - - public SortedSet getUsers() { - return FluentIterable.from( usersByName.values() ).toSortedSet( Ordering.natural() ); - } - - public MPFileUser getUserNamed(final String fullName) { - return usersByName.get( fullName ); - } - - public void addUser(final MPFileUser user) { - usersByName.put( user.getFullName(), user ); - } - - public void deleteUser(final MPFileUser user) { - usersByName.remove( user.getFullName() ); - } -} diff --git a/core/java/model/src/main/java/com/lyndir/masterpassword/model/package-info.java b/core/java/model/src/main/java/com/lyndir/masterpassword/model/package-info.java deleted file mode 100644 index 3bb6e671..00000000 --- a/core/java/model/src/main/java/com/lyndir/masterpassword/model/package-info.java +++ /dev/null @@ -1,27 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -/** - * - * @author lhunath, 15-02-04 - */ - -@ParametersAreNonnullByDefault -package com.lyndir.masterpassword.model; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/core/java/tests/build.gradle b/core/java/tests/build.gradle deleted file mode 100644 index aae837af..00000000 --- a/core/java/tests/build.gradle +++ /dev/null @@ -1,13 +0,0 @@ -plugins { - id 'java' -} - -description = 'Master Password Test Suite' - -dependencies { - compile project(':masterpassword-algorithm') - - testCompile group: 'org.testng', name: 'testng', version:'6.8.5' - testCompile group: 'ch.qos.logback', name: 'logback-classic', version:'1.1.2' -} -test.useTestNG() diff --git a/core/java/tests/pom.xml b/core/java/tests/pom.xml deleted file mode 100644 index cba8d8b8..00000000 --- a/core/java/tests/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - 4.0.0 - - - - com.lyndir.masterpassword - masterpassword - GIT-SNAPSHOT - - - Master Password Test Suite - The standard test suite to ensure the Master Password algorithm is operating as it should - - masterpassword-tests - jar - - - - - - - com.lyndir.masterpassword - masterpassword-algorithm - GIT-SNAPSHOT - - - - - org.testng - testng - test - - - ch.qos.logback - logback-classic - test - - - - - diff --git a/core/java/tests/src/main/java/com/lyndir/masterpassword/MPTestSuite.java b/core/java/tests/src/main/java/com/lyndir/masterpassword/MPTestSuite.java deleted file mode 100644 index 63f5209d..00000000 --- a/core/java/tests/src/main/java/com/lyndir/masterpassword/MPTestSuite.java +++ /dev/null @@ -1,205 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.primitives.UnsignedInteger; -import com.lyndir.lhunath.opal.system.logging.Logger; -import com.lyndir.lhunath.opal.system.util.ConversionUtils; -import java.io.IOException; -import java.util.Deque; -import java.util.List; -import java.util.concurrent.Callable; -import javax.xml.parsers.*; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.ext.DefaultHandler2; - - -/** - * @author lhunath, 2015-12-22 - */ -@SuppressWarnings({ "HardCodedStringLiteral", "ProhibitedExceptionDeclared" }) -public class MPTestSuite implements Callable { - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( MPTestSuite.class ); - private static final String DEFAULT_RESOURCE_NAME = "mpw_tests.xml"; - - private final MPTests tests; - private Listener listener; - - public MPTestSuite() - throws UnavailableException { - this( DEFAULT_RESOURCE_NAME ); - } - - public MPTestSuite(final String resourceName) - throws UnavailableException { - try { - tests = new MPTests(); - tests.cases = Lists.newLinkedList(); - SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); - parser.parse( Thread.currentThread().getContextClassLoader().getResourceAsStream( resourceName ), new DefaultHandler2() { - private final Deque currentTags = Lists.newLinkedList(); - private final Deque currentTexts = Lists.newLinkedList(); - private MPTests.Case currentCase; - - @Override - public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) - throws SAXException { - super.startElement( uri, localName, qName, attributes ); - currentTags.push( qName ); - currentTexts.push( new StringBuilder() ); - - if ("case".equals( qName )) { - currentCase = new MPTests.Case(); - currentCase.identifier = attributes.getValue( "id" ); - currentCase.parent = attributes.getValue( "parent" ); - } - } - - @Override - public void endElement(final String uri, final String localName, final String qName) - throws SAXException { - super.endElement( uri, localName, qName ); - Preconditions.checkState( qName.equals( currentTags.pop() ) ); - String text = currentTexts.pop().toString(); - - if ("case".equals( qName )) - tests.cases.add( currentCase ); - if ("algorithm".equals( qName )) - currentCase.algorithm = ConversionUtils.toInteger( text ).orNull(); - if ("fullName".equals( qName )) - currentCase.fullName = text; - if ("masterPassword".equals( qName )) - currentCase.masterPassword = text; - if ("keyID".equals( qName )) - currentCase.keyID = text; - if ("siteName".equals( qName )) - currentCase.siteName = text; - if ("siteCounter".equals( qName )) - currentCase.siteCounter = text.isEmpty()? null: UnsignedInteger.valueOf( text ); - if ("resultType".equals( qName )) - currentCase.resultType = text; - if ("keyPurpose".equals( qName )) - currentCase.keyPurpose = text; - if ("keyContext".equals( qName )) - currentCase.keyContext = text; - if ("result".equals( qName )) - currentCase.result = text; - } - - @Override - public void characters(final char[] ch, final int start, final int length) - throws SAXException { - super.characters( ch, start, length ); - - currentTexts.peek().append( ch, start, length ); - } - } ); - } - catch (IllegalArgumentException | ParserConfigurationException | SAXException | IOException e) { - throw new UnavailableException( e ); - } - - for (final MPTests.Case testCase : tests.getCases()) - testCase.initializeParentHierarchy( tests ); - } - - public void setListener(final Listener listener) { - this.listener = listener; - } - - public MPTests getTests() { - return tests; - } - - public boolean forEach(final String testName, final TestCase testFunction) - throws Exception { - List cases = tests.getCases(); - for (int c = 0; c < cases.size(); c++) { - MPTests.Case testCase = cases.get( c ); - if (testCase.getResult().isEmpty()) - continue; - - progress( Logger.Target.INFO, c, cases.size(), // - "[%s] on %s...", testName, testCase.getIdentifier() ); - - if (!testFunction.run( testCase )) { - progress( Logger.Target.ERROR, cases.size(), cases.size(), // - "[%s] on %s: FAILED!", testName, testCase.getIdentifier() ); - - return false; - } - - progress( Logger.Target.INFO, c + 1, cases.size(), // - "[%s] on %s: passed!", testName, testCase.getIdentifier() ); - } - - return true; - } - - private void progress(final Logger.Target target, final int current, final int max, final String format, final Object... args) { - logger.log( target, format, args ); - - if (listener != null) - listener.progress( current, max, format, args ); - } - - @Override - public Boolean call() - throws Exception { - return forEach( "mpw", new TestCase() { - @Override - public boolean run(final MPTests.Case testCase) - throws Exception { - MPMasterKey masterKey = new MPMasterKey( testCase.getFullName(), testCase.getMasterPassword().toCharArray() ); - String sitePassword = masterKey.siteResult( testCase.getSiteName(), testCase.getSiteCounter(), testCase.getKeyPurpose(), - testCase.getKeyContext(), testCase.getResultType(), - null, testCase.getAlgorithm() ); - - return testCase.getResult().equals( sitePassword ); - } - } ); - } - - public static class UnavailableException extends Exception { - - private static final long serialVersionUID = 1L; - - public UnavailableException(final Throwable cause) { - super( cause ); - } - } - - - public interface Listener { - - void progress(int current, int max, String messageFormat, Object... args); - } - - - public interface TestCase { - - boolean run(MPTests.Case testCase) - throws Exception; - } -} diff --git a/core/java/tests/src/main/java/com/lyndir/masterpassword/MPTests.java b/core/java/tests/src/main/java/com/lyndir/masterpassword/MPTests.java deleted file mode 100644 index 54670904..00000000 --- a/core/java/tests/src/main/java/com/lyndir/masterpassword/MPTests.java +++ /dev/null @@ -1,227 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*; -import static com.lyndir.lhunath.opal.system.util.StringUtils.strf; - -import com.google.common.primitives.UnsignedInteger; -import com.lyndir.lhunath.opal.system.logging.Logger; -import com.lyndir.lhunath.opal.system.util.*; -import java.util.List; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - - -/** - * @author lhunath, 14-12-05 - */ -public class MPTests { - - private static final String ID_DEFAULT = "default"; - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( MPTests.class ); - - List cases; - - @Nonnull - public List getCases() { - return checkNotNull( cases ); - } - - public Case getCase(final String identifier) { - for (final Case testCase : getCases()) - if (identifier.equals( testCase.getIdentifier() )) - return testCase; - - throw new IllegalArgumentException( strf( "No case for identifier: %s", identifier ) ); - } - - public Case getDefaultCase() { - try { - return getCase( ID_DEFAULT ); - } - catch (final IllegalArgumentException e) { - throw new IllegalStateException( strf( "Missing default case in test suite. Add a case with id: %d", ID_DEFAULT ), e ); - } - } - - public static class Case { - - String identifier; - String parent; - Integer algorithm; - String fullName; - String masterPassword; - String keyID; - String siteName; - UnsignedInteger siteCounter; - String resultType; - String keyPurpose; - String keyContext; - String result; - - private transient Case parentCase; - - public void initializeParentHierarchy(final MPTests tests) { - - if (parent != null) { - parentCase = tests.getCase( parent ); - parentCase.initializeParentHierarchy( tests ); - } - - algorithm = ifNotNullElse( algorithm, new NNSupplier() { - @Nonnull - @Override - public Integer get() { - return checkNotNull( parentCase.algorithm ); - } - } ); - fullName = ifNotNullElse( fullName, new NNSupplier() { - @Nonnull - @Override - public String get() { - return checkNotNull( parentCase.fullName ); - } - } ); - masterPassword = ifNotNullElse( masterPassword, new NNSupplier() { - @Nonnull - @Override - public String get() { - return checkNotNull( parentCase.masterPassword ); - } - } ); - keyID = ifNotNullElse( keyID, new NNSupplier() { - @Nonnull - @Override - public String get() { - return checkNotNull( parentCase.keyID ); - } - } ); - siteName = ifNotNullElse( siteName, new NNSupplier() { - @Nonnull - @Override - public String get() { - return checkNotNull( parentCase.siteName ); - } - } ); - siteCounter = ifNotNullElse( siteCounter, new NNSupplier() { - @Nonnull - @Override - public UnsignedInteger get() { - return checkNotNull( parentCase.siteCounter ); - } - } ); - resultType = ifNotNullElse( resultType, new NNSupplier() { - @Nonnull - @Override - public String get() { - return checkNotNull( parentCase.resultType ); - } - } ); - keyPurpose = ifNotNullElse( keyPurpose, new NNSupplier() { - @Nonnull - @Override - public String get() { - return checkNotNull( parentCase.keyPurpose ); - } - } ); - keyContext = ifNotNullElse( keyContext, new NNSupplier() { - @Nonnull - @Override - public String get() { - return (parentCase == null)? "": checkNotNull( parentCase.keyContext ); - } - } ); - result = ifNotNullElse( result, new NNSupplier() { - @Nonnull - @Override - public String get() { - return (parentCase == null)? "": checkNotNull( parentCase.result ); - } - } ); - } - - @Nonnull - public String getIdentifier() { - return identifier; - } - - @Nullable - public Case getParentCase() { - return parentCase; - } - - @Nonnull - public MPMasterKey.Version getAlgorithm() { - return MPMasterKey.Version.fromInt( checkNotNull( algorithm ) ); - } - - @Nonnull - public String getFullName() { - return checkNotNull( fullName ); - } - - @Nonnull - public String getMasterPassword() { - return checkNotNull( masterPassword ); - } - - @Nonnull - public String getKeyID() { - return checkNotNull( keyID ); - } - - @Nonnull - public String getSiteName() { - return checkNotNull( siteName ); - } - - public UnsignedInteger getSiteCounter() { - return ifNotNullElse( siteCounter, UnsignedInteger.valueOf( 1 ) ); - } - - @Nonnull - public MPResultType getResultType() { - return MPResultType.forName( checkNotNull( resultType ) ); - } - - @Nonnull - public MPKeyPurpose getKeyPurpose() { - return MPKeyPurpose.forName( checkNotNull( keyPurpose ) ); - } - - @Nonnull - public String getKeyContext() { - return checkNotNull( keyContext ); - } - - @Nonnull - public String getResult() { - return checkNotNull( result ); - } - - @Override - public String toString() { - return identifier; - } - } -} diff --git a/core/java/tests/src/main/resources/mpw_tests.xml b/core/java/tests/src/main/resources/mpw_tests.xml deleted file mode 120000 index 0176543d..00000000 --- a/core/java/tests/src/main/resources/mpw_tests.xml +++ /dev/null @@ -1 +0,0 @@ -../../../../../mpw_tests.xml \ No newline at end of file diff --git a/core/java/tests/src/test/java/com/lyndir/masterpassword/MPMasterKeyTest.java b/core/java/tests/src/test/java/com/lyndir/masterpassword/MPMasterKeyTest.java deleted file mode 100644 index 3e7f8722..00000000 --- a/core/java/tests/src/test/java/com/lyndir/masterpassword/MPMasterKeyTest.java +++ /dev/null @@ -1,145 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static org.testng.Assert.*; - -import com.google.common.base.Charsets; -import com.lyndir.lhunath.opal.system.CodeUtils; -import com.lyndir.lhunath.opal.system.logging.Logger; -import java.util.Random; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - - -public class MPMasterKeyTest { - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( MPMasterKeyTest.class ); - - private MPTestSuite testSuite; - - @BeforeMethod - public void setUp() - throws Exception { - - testSuite = new MPTestSuite(); - } - - @Test - public void testMasterKey() - throws Exception { - - testSuite.forEach( "testMasterKey", new MPTestSuite.TestCase() { - @Override - public boolean run(final MPTests.Case testCase) - throws Exception { - char[] masterPassword = testCase.getMasterPassword().toCharArray(); - MPMasterKey masterKey = new MPMasterKey( testCase.getFullName(), masterPassword ); - - // Test key - assertEquals( - CodeUtils.encodeHex( masterKey.getKeyID( testCase.getAlgorithm() ) ), - testCase.getKeyID(), - "[testMasterKey] keyID mismatch: " + testCase ); - - // Test invalidation - masterKey.invalidate(); - try { - masterKey.getKeyID( testCase.getAlgorithm() ); - fail( "[testMasterKey] invalidate ineffective: " + testCase ); - } - catch (final MPInvalidatedException ignored) { - } - assertNotEquals( - masterPassword, - testCase.getMasterPassword().toCharArray(), - "[testMasterKey] masterPassword not wiped: " + testCase ); - - return true; - } - } ); - } - - @Test - public void testSiteResult() - throws Exception { - - testSuite.forEach( "testSiteResult", new MPTestSuite.TestCase() { - @Override - public boolean run(final MPTests.Case testCase) - throws Exception { - char[] masterPassword = testCase.getMasterPassword().toCharArray(); - MPMasterKey masterKey = new MPMasterKey( testCase.getFullName(), masterPassword ); - - // Test site result - assertEquals( - masterKey.siteResult( testCase.getSiteName(), testCase.getSiteCounter(), testCase.getKeyPurpose(), - testCase.getKeyContext(), testCase.getResultType(), - null, testCase.getAlgorithm() ), - testCase.getResult(), - "[testSiteResult] result mismatch: " + testCase ); - - return true; - } - } ); - } - - @Test - public void testSiteState() - throws Exception { - - MPTests.Case testCase = testSuite.getTests().getDefaultCase(); - char[] masterPassword = testCase.getMasterPassword().toCharArray(); - MPMasterKey masterKey = new MPMasterKey( testCase.getFullName(), masterPassword ); - - String password = randomString( 8 ); - for (final MPMasterKey.Version version : MPMasterKey.Version.values()) { - MPResultType resultType = MPResultType.StoredPersonal; - - // Test site state - String state = masterKey.siteState( testCase.getSiteName(), testCase.getSiteCounter(), testCase.getKeyPurpose(), - testCase.getKeyContext(), resultType, password, version ); - String result = masterKey.siteResult( testCase.getSiteName(), testCase.getSiteCounter(), testCase.getKeyPurpose(), - testCase.getKeyContext(), resultType, state, version ); - - assertEquals( - result, - password, - "[testSiteState] state mismatch: " + testCase ); - } - } - - public static String randomString(int length) { - Random random = new Random(); - StringBuilder builder = new StringBuilder(); - - while (length > 0) { - int codePoint = random.nextInt( Character.MAX_CODE_POINT - Character.MIN_CODE_POINT ) + Character.MIN_CODE_POINT; - if (!Character.isDefined( codePoint ) || (Character.getType( codePoint ) == Character.PRIVATE_USE) || Character.isSurrogate( - (char) codePoint )) - continue; - - builder.appendCodePoint( codePoint ); - length--; - } - - return builder.toString(); - } -} diff --git a/core/java/tests/src/test/resources/logback.xml b/core/java/tests/src/test/resources/logback.xml deleted file mode 100644 index dd7f2458..00000000 --- a/core/java/tests/src/test/resources/logback.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - %-8relative %22c{0} [%-5level] %msg%n - - - - - - - - - - diff --git a/core/mpw_tests.xml b/core/mpw_tests.xml deleted file mode 100644 index 320820de..00000000 --- a/core/mpw_tests.xml +++ /dev/null @@ -1,279 +0,0 @@ - - - - -1 - Robert Lee Mitchell - banana colored duckling - 98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302 - masterpasswordapp.com - 1 - Long - Authentication - - - - - - 3 - Jejr5[RepuSosp - - - - 1717AA1F9BF5BA56CD0965CDA3D78E6D2E6A1EA8C067A8EA621F3DDAD4A87EB8 - NopaDajh8=Fene - - - - 351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08 - QesuHirv5-Xepl - - - - LiheCuwhSerz6) - - - Identification - Name - wohzaqage - - - Recovery - Phrase - xin diyjiqoja hubu - - - question - xogx tem cegyiva jab - - - Maximum - W6@692^B1#&@gVdSdLZ@ - - - Medium - Jej2$Quv - - - Basic - WAo2xIg6 - - - Short - Jej2 - - - PIN - 7662 - - - Name - jejraquvo - - - Phrase - jejr quv cabsibu tam - - - 4294967295 - XambHoqo6[Peni - - - - - 2 - Jejr5[RepuSosp - - - - 4D5851D0B093D65DE0CF13D94877270468C0B65A6E42CA50D393AC9B99C457B5 - WaqoGuho2[Xaxw - - - - 351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08 - QesuHirv5-Xepl - - - - LiheCuwhSerz6) - - - Identification - Name - wohzaqage - - - Recovery - Phrase - xin diyjiqoja hubu - - - question - xogx tem cegyiva jab - - - Maximum - W6@692^B1#&@gVdSdLZ@ - - - Medium - Jej2$Quv - - - Basic - WAo2xIg6 - - - Short - Jej2 - - - PIN - 7662 - - - Name - jejraquvo - - - Phrase - jejr quv cabsibu tam - - - 4294967295 - XambHoqo6[Peni - - - - - 1 - Jejr5[RepuSosp - - - - 4D5851D0B093D65DE0CF13D94877270468C0B65A6E42CA50D393AC9B99C457B5 - WaqoGuho2[Xaxw - - - - 351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08 - QesuHirv5-Xepl - - - - WawiYarp2@Kodh - - - Identification - Name - wohzaqage - - - Recovery - Phrase - xin diyjiqoja hubu - - - question - xogx tem cegyiva jab - - - Maximum - W6@692^B1#&@gVdSdLZ@ - - - Medium - Jej2$Quv - - - Basic - WAo2xIg6 - - - Short - Jej2 - - - PIN - 7662 - - - Name - jejraquvo - - - Phrase - jejr quv cabsibu tam - - - 4294967295 - XambHoqo6[Peni - - - - - 0 - Feji5@ReduWosh - - - - 4D5851D0B093D65DE0CF13D94877270468C0B65A6E42CA50D393AC9B99C457B5 - HajrYudo7@Mamh - - - - 351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08 - MewmDini0]Meho - - - - HahiVana2@Nole - - - Identification - Name - lozwajave - - - Recovery - Phrase - miy lirfijoja dubu - - - question - movm bex gevrica jaf - - - Maximum - w1!3bA3icmRAc)SS@lwl - - - Medium - Fej7]Jug - - - Basic - wvH7irC1 - - - Short - Fej7 - - - PIN - 2117 - - - Name - fejrajugo - - - Phrase - fejr jug gabsibu bax - - - 4294967295 - QateDojh1@Hecn - - - diff --git a/public/site/2015-05/css/main.scss b/css/main.scss similarity index 100% rename from public/site/2015-05/css/main.scss rename to css/main.scss diff --git a/gradle/.idea/codeStyleSettings.xml b/gradle/.idea/codeStyleSettings.xml deleted file mode 100644 index 6411f7cf..00000000 --- a/gradle/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/gradle/.idea/copyright/GPLv3.xml b/gradle/.idea/copyright/GPLv3.xml deleted file mode 100644 index 7621717c..00000000 --- a/gradle/.idea/copyright/GPLv3.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/gradle/.idea/copyright/profiles_settings.xml b/gradle/.idea/copyright/profiles_settings.xml deleted file mode 100644 index d516e023..00000000 --- a/gradle/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/gradle/.idea/inspectionProfiles/profiles_settings.xml b/gradle/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 59059c7a..00000000 --- a/gradle/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/gradle/.idea/misc.xml b/gradle/.idea/misc.xml deleted file mode 100644 index cdb95b5a..00000000 --- a/gradle/.idea/misc.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/gradle/.idea/runConfigurations/Android.xml b/gradle/.idea/runConfigurations/Android.xml deleted file mode 100644 index 10cabad7..00000000 --- a/gradle/.idea/runConfigurations/Android.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - \ No newline at end of file diff --git a/gradle/.idea/runConfigurations/GUI.xml b/gradle/.idea/runConfigurations/GUI.xml deleted file mode 100644 index 7c0766a3..00000000 --- a/gradle/.idea/runConfigurations/GUI.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/gradle/.idea/runConfigurations/Tests.xml b/gradle/.idea/runConfigurations/Tests.xml deleted file mode 100644 index ee3efb8f..00000000 --- a/gradle/.idea/runConfigurations/Tests.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/gradle/.idea/scopes/masterpassword.xml b/gradle/.idea/scopes/masterpassword.xml deleted file mode 100644 index 42d84ba4..00000000 --- a/gradle/.idea/scopes/masterpassword.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/gradle/build.gradle b/gradle/build.gradle deleted file mode 100644 index 64267b12..00000000 --- a/gradle/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -allprojects { - //apply plugin: 'findbugs' - - group = 'com.lyndir.masterpassword' - version = 'GIT-SNAPSHOT' - - tasks.withType(JavaCompile) { - sourceCompatibility = '1.7' - targetCompatibility = '1.7' - } - tasks.withType(FindBugs) { - reports { - xml.enabled false - html.enabled true - } - } -} - -buildscript { - repositories { - jcenter() - } - - dependencies { - classpath group: 'com.android.tools.build', name: 'gradle', version: '2.3.0' - } -} - -subprojects { - repositories { - mavenCentral() - maven { url 'http://maven.lyndir.com' } - } -} diff --git a/gradle/external-annotations/com/google/common/base/annotations.xml b/gradle/external-annotations/com/google/common/base/annotations.xml deleted file mode 100644 index b854e2e9..00000000 --- a/gradle/external-annotations/com/google/common/base/annotations.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/gradle/external-annotations/com/google/common/io/annotations.xml b/gradle/external-annotations/com/google/common/io/annotations.xml deleted file mode 100644 index e912cca1..00000000 --- a/gradle/external-annotations/com/google/common/io/annotations.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/gradle/external-annotations/org/testng/annotations.xml b/gradle/external-annotations/org/testng/annotations.xml deleted file mode 100644 index 4c7d5ed8..00000000 --- a/gradle/external-annotations/org/testng/annotations.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/gradle/gradle.properties b/gradle/gradle.properties deleted file mode 100644 index 8bd86f68..00000000 --- a/gradle/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M diff --git a/gradle/gradle/wrapper/gradle-wrapper.jar b/gradle/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 1d1b86c0..00000000 Binary files a/gradle/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/gradle/wrapper/gradle-wrapper.properties b/gradle/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index b5288155..00000000 --- a/gradle/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Sun Mar 26 09:11:08 EDT 2017 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/gradle/gradlew b/gradle/gradlew deleted file mode 100755 index 4453ccea..00000000 --- a/gradle/gradlew +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save ( ) { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/gradle/gradlew.bat b/gradle/gradlew.bat deleted file mode 100644 index e95643d6..00000000 --- a/gradle/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/gradle/homebrew-mpw.rb b/gradle/homebrew-mpw.rb deleted file mode 100644 index cdded4be..00000000 --- a/gradle/homebrew-mpw.rb +++ /dev/null @@ -1,31 +0,0 @@ -class Mpw < Formula - homepage "http://masterpasswordapp.com" - url "https://ssl.masterpasswordapp.com/mpw-2.1-cli4-0-gf6b2287.tar.gz" - sha1 "036b3d8f4bd6f0676ae16e7e9c3de65f6030874f" - version "2.1-cli4" - - depends_on "automake" => :build - depends_on "autoconf" => :build - depends_on "openssl" - - resource "libscrypt" do - url "http://masterpasswordapp.com/libscrypt-b12b554.tar.gz" - sha1 "ee871e0f93a786c4e3622561f34565337cfdb815" - end - - def install - resource("libscrypt").stage buildpath/"lib/scrypt" - touch "lib/scrypt/.unpacked" - - ENV["targets"] = "mpw mpw-tests" - system "./build" - system "./mpw-tests" - - bin.install "mpw" - end - - test do - assert_equal "Jejr5[RepuSosp", - shell_output("mpw -u 'Robert Lee Mitchell' -P 'banana colored duckling' masterpasswordapp.com").strip - end -end diff --git a/gradle/pom.xml b/gradle/pom.xml deleted file mode 100644 index d9abad1e..00000000 --- a/gradle/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - 4.0.0 - - - - com.lyndir.lhunath - lyndir - 1.22 - - - Master Password - A Java implementation of the Master Password algorithm. - - com.lyndir.masterpassword - masterpassword - GIT-SNAPSHOT - pom - - - masterpassword-tests - masterpassword-algorithm - masterpassword-model - masterpassword-gui - - - - - release - - masterpassword-android - - - - mod:android - - masterpassword-android - - - - - - - - lyndir - Lyndir Repository - http://maven.lyndir.com - - - true - never - - - true - never - - - - diff --git a/gradle/settings.gradle b/gradle/settings.gradle deleted file mode 100644 index 669df3c9..00000000 --- a/gradle/settings.gradle +++ /dev/null @@ -1,26 +0,0 @@ -rootProject.name = 'masterpassword' - -def local = new Properties(); -try { - local.load(file('local.properties').newDataInputStream()) -} catch (FileNotFoundException ignored) { -} - -include 'masterpassword-algorithm' -project(':masterpassword-algorithm').projectDir = new File( '../core/java/algorithm' ) - -include 'masterpassword-model' -project(':masterpassword-model').projectDir = new File( '../core/java/model' ) - -include 'masterpassword-tests' -project(':masterpassword-tests').projectDir = new File( '../core/java/tests' ) - -include 'masterpassword-gui' -project(':masterpassword-gui').projectDir = new File( '../platform-independent/gui-java' ) - -if (local.containsKey('sdk.dir')) { - include 'masterpassword-android' - project(':masterpassword-android').projectDir = new File( '../platform-android' ) -} else { - logger.warn( "Skipping masterpassword-android since sdk.dir is not defined in local.properties." ) -} diff --git a/public/site/2015-05/how.html b/how.html similarity index 100% rename from public/site/2015-05/how.html rename to how.html diff --git a/public/site/2013-05/img/favicon.png b/img/favicon.png similarity index 100% rename from public/site/2013-05/img/favicon.png rename to img/favicon.png diff --git a/public/site/2015-05/img/frustrated_625996.svg b/img/frustrated_625996.svg similarity index 100% rename from public/site/2015-05/img/frustrated_625996.svg rename to img/frustrated_625996.svg diff --git a/public/site/2015-05/img/getting_started_162761.svg b/img/getting_started_162761.svg similarity index 100% rename from public/site/2015-05/img/getting_started_162761.svg rename to img/getting_started_162761.svg diff --git a/public/site/2015-05/img/head_key_336882.svg b/img/head_key_336882.svg similarity index 100% rename from public/site/2015-05/img/head_key_336882.svg rename to img/head_key_336882.svg diff --git a/public/site/2015-05/img/hero_cli.jpg b/img/hero_cli.jpg similarity index 100% rename from public/site/2015-05/img/hero_cli.jpg rename to img/hero_cli.jpg diff --git a/public/site/2015-05/img/hero_desktop.jpg b/img/hero_desktop.jpg similarity index 100% rename from public/site/2015-05/img/hero_desktop.jpg rename to img/hero_desktop.jpg diff --git a/public/site/2015-05/img/hero_ios.jpg b/img/hero_ios.jpg similarity index 100% rename from public/site/2015-05/img/hero_ios.jpg rename to img/hero_ios.jpg diff --git a/public/site/2015-05/img/hero_mac.jpg b/img/hero_mac.jpg similarity index 100% rename from public/site/2015-05/img/hero_mac.jpg rename to img/hero_mac.jpg diff --git a/public/site/2015-05/img/hero_main.jpg b/img/hero_main.jpg similarity index 100% rename from public/site/2015-05/img/hero_main.jpg rename to img/hero_main.jpg diff --git a/public/site/2015-05/img/hero_web.jpg b/img/hero_web.jpg similarity index 100% rename from public/site/2015-05/img/hero_web.jpg rename to img/hero_web.jpg diff --git a/public/site/2013-05/img/howto-mp-copy.png b/img/howto-mp-copy.png similarity index 100% rename from public/site/2013-05/img/howto-mp-copy.png rename to img/howto-mp-copy.png diff --git a/public/site/2013-05/img/howto-mp-copy@2x.png b/img/howto-mp-copy@2x.png similarity index 100% rename from public/site/2013-05/img/howto-mp-copy@2x.png rename to img/howto-mp-copy@2x.png diff --git a/public/site/2013-05/img/howto-mp-create-confirm.png b/img/howto-mp-create-confirm.png similarity index 100% rename from public/site/2013-05/img/howto-mp-create-confirm.png rename to img/howto-mp-create-confirm.png diff --git a/public/site/2013-05/img/howto-mp-create-confirm@2x.png b/img/howto-mp-create-confirm@2x.png similarity index 100% rename from public/site/2013-05/img/howto-mp-create-confirm@2x.png rename to img/howto-mp-create-confirm@2x.png diff --git a/public/site/2013-05/img/howto-mp-create.png b/img/howto-mp-create.png similarity index 100% rename from public/site/2013-05/img/howto-mp-create.png rename to img/howto-mp-create.png diff --git a/public/site/2013-05/img/howto-mp-create@2x.png b/img/howto-mp-create@2x.png similarity index 100% rename from public/site/2013-05/img/howto-mp-create@2x.png rename to img/howto-mp-create@2x.png diff --git a/public/site/2013-05/img/howto-mp-login.png b/img/howto-mp-login.png similarity index 100% rename from public/site/2013-05/img/howto-mp-login.png rename to img/howto-mp-login.png diff --git a/public/site/2013-05/img/howto-mp-login@2x.png b/img/howto-mp-login@2x.png similarity index 100% rename from public/site/2013-05/img/howto-mp-login@2x.png rename to img/howto-mp-login@2x.png diff --git a/public/site/2013-05/img/howto-mp-type-basic.png b/img/howto-mp-type-basic.png similarity index 100% rename from public/site/2013-05/img/howto-mp-type-basic.png rename to img/howto-mp-type-basic.png diff --git a/public/site/2013-05/img/howto-mp-type-basic@2x.png b/img/howto-mp-type-basic@2x.png similarity index 100% rename from public/site/2013-05/img/howto-mp-type-basic@2x.png rename to img/howto-mp-type-basic@2x.png diff --git a/public/site/2013-05/img/howto-mp-type-change.png b/img/howto-mp-type-change.png similarity index 100% rename from public/site/2013-05/img/howto-mp-type-change.png rename to img/howto-mp-type-change.png diff --git a/public/site/2013-05/img/howto-mp-type-change@2x.png b/img/howto-mp-type-change@2x.png similarity index 100% rename from public/site/2013-05/img/howto-mp-type-change@2x.png rename to img/howto-mp-type-change@2x.png diff --git a/public/site/2013-05/img/howto-twitter-done.png b/img/howto-twitter-done.png similarity index 100% rename from public/site/2013-05/img/howto-twitter-done.png rename to img/howto-twitter-done.png diff --git a/public/site/2013-05/img/howto-twitter-done@2x.png b/img/howto-twitter-done@2x.png similarity index 100% rename from public/site/2013-05/img/howto-twitter-done@2x.png rename to img/howto-twitter-done@2x.png diff --git a/public/site/2013-05/img/howto-twitter-paste.png b/img/howto-twitter-paste.png similarity index 100% rename from public/site/2013-05/img/howto-twitter-paste.png rename to img/howto-twitter-paste.png diff --git a/public/site/2013-05/img/howto-twitter-paste@2x.png b/img/howto-twitter-paste@2x.png similarity index 100% rename from public/site/2013-05/img/howto-twitter-paste@2x.png rename to img/howto-twitter-paste@2x.png diff --git a/public/site/2013-05/img/howto-twitter-signup.png b/img/howto-twitter-signup.png similarity index 100% rename from public/site/2013-05/img/howto-twitter-signup.png rename to img/howto-twitter-signup.png diff --git a/public/site/2013-05/img/howto-twitter-signup@2x.png b/img/howto-twitter-signup@2x.png similarity index 100% rename from public/site/2013-05/img/howto-twitter-signup@2x.png rename to img/howto-twitter-signup@2x.png diff --git a/public/site/2015-05/img/password_app_667404.svg b/img/password_app_667404.svg similarity index 100% rename from public/site/2015-05/img/password_app_667404.svg rename to img/password_app_667404.svg diff --git a/public/site/2015-05/img/password_forgot_882804.svg b/img/password_forgot_882804.svg similarity index 100% rename from public/site/2015-05/img/password_forgot_882804.svg rename to img/password_forgot_882804.svg diff --git a/public/site/2015-05/img/password_generate_861293.svg b/img/password_generate_861293.svg similarity index 100% rename from public/site/2015-05/img/password_generate_861293.svg rename to img/password_generate_861293.svg diff --git a/public/site/2015-05/img/password_head_336886.svg b/img/password_head_336886.svg similarity index 100% rename from public/site/2015-05/img/password_head_336886.svg rename to img/password_head_336886.svg diff --git a/public/site/2015-05/img/password_lost_882789.svg b/img/password_lost_882789.svg similarity index 100% rename from public/site/2015-05/img/password_lost_882789.svg rename to img/password_lost_882789.svg diff --git a/public/site/2015-05/img/password_notebook_4740.svg b/img/password_notebook_4740.svg similarity index 100% rename from public/site/2015-05/img/password_notebook_4740.svg rename to img/password_notebook_4740.svg diff --git a/public/site/2015-05/img/password_offer_944292.svg b/img/password_offer_944292.svg similarity index 100% rename from public/site/2015-05/img/password_offer_944292.svg rename to img/password_offer_944292.svg diff --git a/public/site/2015-05/img/thinking_882797.svg b/img/thinking_882797.svg similarity index 100% rename from public/site/2015-05/img/thinking_882797.svg rename to img/thinking_882797.svg diff --git a/public/site/2013-05/img/thumb-authenticate.png b/img/thumb-authenticate.png similarity index 100% rename from public/site/2013-05/img/thumb-authenticate.png rename to img/thumb-authenticate.png diff --git a/public/site/2013-05/img/thumb-iphone-broken.png b/img/thumb-iphone-broken.png similarity index 100% rename from public/site/2013-05/img/thumb-iphone-broken.png rename to img/thumb-iphone-broken.png diff --git a/public/site/2013-05/img/thumb-iphone-mac-sync.png b/img/thumb-iphone-mac-sync.png similarity index 100% rename from public/site/2013-05/img/thumb-iphone-mac-sync.png rename to img/thumb-iphone-mac-sync.png diff --git a/public/site/2013-05/img/thumb-iphone-pw.png b/img/thumb-iphone-pw.png similarity index 100% rename from public/site/2013-05/img/thumb-iphone-pw.png rename to img/thumb-iphone-pw.png diff --git a/public/site/2013-05/img/thumb-iphone-types.png b/img/thumb-iphone-types.png similarity index 100% rename from public/site/2013-05/img/thumb-iphone-types.png rename to img/thumb-iphone-types.png diff --git a/public/site/2013-05/img/thumb-process-black.png b/img/thumb-process-black.png similarity index 100% rename from public/site/2013-05/img/thumb-process-black.png rename to img/thumb-process-black.png diff --git a/public/site/2015-05/index.html b/index.html similarity index 100% rename from public/site/2015-05/index.html rename to index.html diff --git a/public/site/2015-05/js/jquery-3.3.1.min.js b/js/jquery-3.3.1.min.js similarity index 100% rename from public/site/2015-05/js/jquery-3.3.1.min.js rename to js/jquery-3.3.1.min.js diff --git a/public/site/2015-05/js/jquery.paroller.min.js b/js/jquery.paroller.min.js similarity index 100% rename from public/site/2015-05/js/jquery.paroller.min.js rename to js/jquery.paroller.min.js diff --git a/public/site/2015-05/js/main.js b/js/main.js similarity index 100% rename from public/site/2015-05/js/main.js rename to js/main.js diff --git a/public/site/2015-05/masterpassword-algorithm.pdf b/masterpassword-algorithm.pdf similarity index 100% rename from public/site/2015-05/masterpassword-algorithm.pdf rename to masterpassword-algorithm.pdf diff --git a/public/site/2013-05/masterpassword-android-2.2.apk b/masterpassword-android-2.2.apk similarity index 100% rename from public/site/2013-05/masterpassword-android-2.2.apk rename to masterpassword-android-2.2.apk diff --git a/public/site/2013-05/masterpassword-android-2.3.apk b/masterpassword-android-2.3.apk similarity index 100% rename from public/site/2013-05/masterpassword-android-2.3.apk rename to masterpassword-android-2.3.apk diff --git a/public/site/2013-05/masterpassword-android-2.4-java.apk b/masterpassword-android-2.4-java.apk similarity index 100% rename from public/site/2013-05/masterpassword-android-2.4-java.apk rename to masterpassword-android-2.4-java.apk diff --git a/public/site/2013-05/masterpassword-android-2.4.1.apk b/masterpassword-android-2.4.1.apk similarity index 100% rename from public/site/2013-05/masterpassword-android-2.4.1.apk rename to masterpassword-android-2.4.1.apk diff --git a/public/site/2013-05/masterpassword-android.apk b/masterpassword-android.apk similarity index 100% rename from public/site/2013-05/masterpassword-android.apk rename to masterpassword-android.apk diff --git a/public/site/2013-05/masterpassword-cli.tar.gz b/masterpassword-cli.tar.gz similarity index 100% rename from public/site/2013-05/masterpassword-cli.tar.gz rename to masterpassword-cli.tar.gz diff --git a/public/site/2013-05/masterpassword-cli.tar.gz.sig b/masterpassword-cli.tar.gz.sig similarity index 100% rename from public/site/2013-05/masterpassword-cli.tar.gz.sig rename to masterpassword-cli.tar.gz.sig diff --git a/public/site/2013-05/masterpassword-gui-2.2.jar b/masterpassword-gui-2.2.jar similarity index 100% rename from public/site/2013-05/masterpassword-gui-2.2.jar rename to masterpassword-gui-2.2.jar diff --git a/public/site/2013-05/masterpassword-gui-2.3.jar b/masterpassword-gui-2.3.jar similarity index 100% rename from public/site/2013-05/masterpassword-gui-2.3.jar rename to masterpassword-gui-2.3.jar diff --git a/public/site/2013-05/masterpassword-gui.jar b/masterpassword-gui.jar similarity index 100% rename from public/site/2013-05/masterpassword-gui.jar rename to masterpassword-gui.jar diff --git a/public/site/2013-05/masterpassword-gui.jar.rev b/masterpassword-gui.jar.rev similarity index 100% rename from public/site/2013-05/masterpassword-gui.jar.rev rename to masterpassword-gui.jar.rev diff --git a/public/site/2013-05/masterpassword-mac.zip b/masterpassword-mac.zip similarity index 100% rename from public/site/2013-05/masterpassword-mac.zip rename to masterpassword-mac.zip diff --git a/public/site/2015-05/masterpassword-primer.pdf b/masterpassword-primer.pdf similarity index 100% rename from public/site/2015-05/masterpassword-primer.pdf rename to masterpassword-primer.pdf diff --git a/public/site/2013-05/mpw-2.1-cli1-0-g10f1001.tar.gz b/mpw-2.1-cli1-0-g10f1001.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.1-cli1-0-g10f1001.tar.gz rename to mpw-2.1-cli1-0-g10f1001.tar.gz diff --git a/public/site/2013-05/mpw-2.1-cli2-2-g82c96dd.tar.gz b/mpw-2.1-cli2-2-g82c96dd.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.1-cli2-2-g82c96dd.tar.gz rename to mpw-2.1-cli2-2-g82c96dd.tar.gz diff --git a/public/site/2013-05/mpw-2.1-cli3-0-g438daf2.tar.gz b/mpw-2.1-cli3-0-g438daf2.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.1-cli3-0-g438daf2.tar.gz rename to mpw-2.1-cli3-0-g438daf2.tar.gz diff --git a/public/site/2013-05/mpw-2.1-cli4-0-gf6b2287.tar.gz b/mpw-2.1-cli4-0-gf6b2287.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.1-cli4-0-gf6b2287.tar.gz rename to mpw-2.1-cli4-0-gf6b2287.tar.gz diff --git a/public/site/2013-05/mpw-2.5-cli-1-0-gb01e370f.tar.gz b/mpw-2.5-cli-1-0-gb01e370f.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.5-cli-1-0-gb01e370f.tar.gz rename to mpw-2.5-cli-1-0-gb01e370f.tar.gz diff --git a/public/site/2013-05/mpw-2.5-cli-1-0-gb01e370f.tar.gz.sig b/mpw-2.5-cli-1-0-gb01e370f.tar.gz.sig similarity index 100% rename from public/site/2013-05/mpw-2.5-cli-1-0-gb01e370f.tar.gz.sig rename to mpw-2.5-cli-1-0-gb01e370f.tar.gz.sig diff --git a/public/site/2013-05/mpw-2.5-cli-2-0-g3ed6b937.tar.gz b/mpw-2.5-cli-2-0-g3ed6b937.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.5-cli-2-0-g3ed6b937.tar.gz rename to mpw-2.5-cli-2-0-g3ed6b937.tar.gz diff --git a/public/site/2013-05/mpw-2.5-cli-2-0-g3ed6b937.tar.gz.sig b/mpw-2.5-cli-2-0-g3ed6b937.tar.gz.sig similarity index 100% rename from public/site/2013-05/mpw-2.5-cli-2-0-g3ed6b937.tar.gz.sig rename to mpw-2.5-cli-2-0-g3ed6b937.tar.gz.sig diff --git a/public/site/2013-05/mpw-2.6-cli-1-0-g895df637.tar.gz b/mpw-2.6-cli-1-0-g895df637.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.6-cli-1-0-g895df637.tar.gz rename to mpw-2.6-cli-1-0-g895df637.tar.gz diff --git a/public/site/2013-05/mpw-2.6-cli-1-0-g895df637.tar.gz.sig b/mpw-2.6-cli-1-0-g895df637.tar.gz.sig similarity index 100% rename from public/site/2013-05/mpw-2.6-cli-1-0-g895df637.tar.gz.sig rename to mpw-2.6-cli-1-0-g895df637.tar.gz.sig diff --git a/public/site/2013-05/mpw-2.6-cli-2-0-g30fdb54e.tar.gz b/mpw-2.6-cli-2-0-g30fdb54e.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.6-cli-2-0-g30fdb54e.tar.gz rename to mpw-2.6-cli-2-0-g30fdb54e.tar.gz diff --git a/public/site/2013-05/mpw-2.6-cli-2-0-g30fdb54e.tar.gz.sig b/mpw-2.6-cli-2-0-g30fdb54e.tar.gz.sig similarity index 100% rename from public/site/2013-05/mpw-2.6-cli-2-0-g30fdb54e.tar.gz.sig rename to mpw-2.6-cli-2-0-g30fdb54e.tar.gz.sig diff --git a/public/site/2013-05/mpw-2.6-cli-3-0-ga85eff42.tar.gz b/mpw-2.6-cli-3-0-ga85eff42.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.6-cli-3-0-ga85eff42.tar.gz rename to mpw-2.6-cli-3-0-ga85eff42.tar.gz diff --git a/public/site/2013-05/mpw-2.6-cli-3-0-ga85eff42.tar.gz.sig b/mpw-2.6-cli-3-0-ga85eff42.tar.gz.sig similarity index 100% rename from public/site/2013-05/mpw-2.6-cli-3-0-ga85eff42.tar.gz.sig rename to mpw-2.6-cli-3-0-ga85eff42.tar.gz.sig diff --git a/public/site/2013-05/mpw-2.6-cli-4-0-gf8043ae1.tar.gz b/mpw-2.6-cli-4-0-gf8043ae1.tar.gz similarity index 100% rename from public/site/2013-05/mpw-2.6-cli-4-0-gf8043ae1.tar.gz rename to mpw-2.6-cli-4-0-gf8043ae1.tar.gz diff --git a/public/site/2013-05/mpw-2.6-cli-4-0-gf8043ae1.tar.gz.sig b/mpw-2.6-cli-4-0-gf8043ae1.tar.gz.sig similarity index 100% rename from public/site/2013-05/mpw-2.6-cli-4-0-gf8043ae1.tar.gz.sig rename to mpw-2.6-cli-4-0-gf8043ae1.tar.gz.sig diff --git a/platform-android/README b/platform-android/README deleted file mode 100644 index 95c5a204..00000000 --- a/platform-android/README +++ /dev/null @@ -1,13 +0,0 @@ -To build this module, please ensure you've done the following setup: - -1. Installed the Android SDK and fully downloaded the Android SDK platform 21 in it. -2. Set the environment variable ANDROID_HOME in your shell or in ~/.mavenrc to point to the root of your Android SDK install. -3. Installed the Android SDK into your Maven's local repository. - 3a. Clone the maven-android-sdk-deployer available from here: https://github.com/mosabua/maven-android-sdk-deployer.git - 3b. In the root of this project, run: mvn install -P 5.0 - -To build this module: - -1. Build the parent, by going into 'MasterPassword/Java' and running: mvn clean install -2. Build this module, by going into 'MasterPassword/Java/masterpassword-android' and running: mvn clean install -3. You can then find the APK in: 'MasterPassword/Java/masterpassword-android/target' diff --git a/platform-android/build.gradle b/platform-android/build.gradle deleted file mode 100644 index 6dac70eb..00000000 --- a/platform-android/build.gradle +++ /dev/null @@ -1,46 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 25 - buildToolsVersion '25.0.0' - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - - defaultConfig { - applicationId 'com.lyndir.masterpassword' - minSdkVersion 19 - targetSdkVersion 25 - versionCode 20401 - versionName '2.4.1' - } - - // release with: STORE_PW=$(mpw masterpassword.keystore) KEY_PW=$(mpw masterpassword-android) gradle assembleRelease - signingConfigs { - release { - storeFile file( 'masterpassword.keystore' ) - storePassword System.getenv( 'STORE_PW' ) - - keyAlias 'masterpassword-android' - keyPassword System.getenv( 'KEY_PW' ) - } - } - buildTypes { - release { - if (System.getenv( 'STORE_PW' ) != null) - signingConfig signingConfigs.release - } - } -} - -dependencies { - compile project( ':masterpassword-algorithm' ) - compile project( ':masterpassword-tests' ) - - compile group: 'org.slf4j', name: 'slf4j-android', version:'1.7.13-underscore' - compile group: 'com.jakewharton', name: 'butterknife', version:'8.5.1' - annotationProcessor group: 'com.jakewharton', name: 'butterknife-compiler', version:'8.5.1' - compile files( 'libs/scrypt-1.4.0-native.jar' ) -} diff --git a/platform-android/libs/scrypt-1.4.0-native.jar b/platform-android/libs/scrypt-1.4.0-native.jar deleted file mode 100644 index 94702568..00000000 Binary files a/platform-android/libs/scrypt-1.4.0-native.jar and /dev/null differ diff --git a/platform-android/masterpassword.keystore b/platform-android/masterpassword.keystore deleted file mode 120000 index 8e3ba215..00000000 --- a/platform-android/masterpassword.keystore +++ /dev/null @@ -1 +0,0 @@ -/Users/lhunath/annex/secret/masterpassword.keystore \ No newline at end of file diff --git a/platform-android/pom.xml b/platform-android/pom.xml deleted file mode 100644 index 0e54568d..00000000 --- a/platform-android/pom.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - - 4.0.0 - - - - com.lyndir.masterpassword - masterpassword - GIT-SNAPSHOT - - - Master Password Android - An Android application to the Master Password algorithm - - masterpassword-android - apk - - - - - - com.jayway.maven.plugins.android.generation2 - android-maven-plugin - - - - true - false - - - 21 - - - - - - - - - release - - - - com.jayway.maven.plugins.android.generation2 - android-maven-plugin - - - - false - - - - - - manifest-update - process-resources - - manifest-update - - - true - - - - - - org.apache.maven.plugins - maven-jarsigner-plugin - 1.4 - - - signing - - sign - - package - true - - - - target/*.apk - - release.jks - ${env.PASSWORD} - ${env.PASSWORD} - masterpassword-android - - -sigalgMD5withRSA - -digestalgSHA1 - - - - - - - - - - - - - - - - com.lyndir.masterpassword - masterpassword-algorithm - GIT-SNAPSHOT - - - - com.lyndir.masterpassword - masterpassword-tests - GIT-SNAPSHOT - - - - - com.jakewharton - butterknife - - - - org.slf4j - slf4j-android - 1.7.13-underscore - - - - android - android - 5.0.1_r2 - - - - com.lambdaworks - scrypt - 1.4.0-android - jar - native - - - - - diff --git a/platform-android/proguard.cfg b/platform-android/proguard.cfg deleted file mode 100644 index 251d06bd..00000000 --- a/platform-android/proguard.cfg +++ /dev/null @@ -1,5 +0,0 @@ --ignorewarnings --dontoptimize --dontobfuscate --dontskipnonpubliclibraryclasses --dontskipnonpubliclibraryclassmembers diff --git a/platform-android/src/main/AndroidManifest.xml b/platform-android/src/main/AndroidManifest.xml deleted file mode 100644 index e778f911..00000000 --- a/platform-android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/platform-android/src/main/assets/Exo2.0-Bold.otf b/platform-android/src/main/assets/Exo2.0-Bold.otf deleted file mode 100644 index 1e7072dd..00000000 Binary files a/platform-android/src/main/assets/Exo2.0-Bold.otf and /dev/null differ diff --git a/platform-android/src/main/assets/Exo2.0-ExtraBold.otf b/platform-android/src/main/assets/Exo2.0-ExtraBold.otf deleted file mode 100644 index 32dadb3f..00000000 Binary files a/platform-android/src/main/assets/Exo2.0-ExtraBold.otf and /dev/null differ diff --git a/platform-android/src/main/assets/Exo2.0-Regular.otf b/platform-android/src/main/assets/Exo2.0-Regular.otf deleted file mode 100644 index 4bd82f98..00000000 Binary files a/platform-android/src/main/assets/Exo2.0-Regular.otf and /dev/null differ diff --git a/platform-android/src/main/assets/Exo2.0-Thin.otf b/platform-android/src/main/assets/Exo2.0-Thin.otf deleted file mode 100644 index 768f03f3..00000000 Binary files a/platform-android/src/main/assets/Exo2.0-Thin.otf and /dev/null differ diff --git a/platform-android/src/main/assets/SourceCodePro-Black.otf b/platform-android/src/main/assets/SourceCodePro-Black.otf deleted file mode 100644 index ba47f3db..00000000 Binary files a/platform-android/src/main/assets/SourceCodePro-Black.otf and /dev/null differ diff --git a/platform-android/src/main/assets/SourceCodePro-ExtraLight.otf b/platform-android/src/main/assets/SourceCodePro-ExtraLight.otf deleted file mode 100644 index 5cb8e5fb..00000000 Binary files a/platform-android/src/main/assets/SourceCodePro-ExtraLight.otf and /dev/null differ diff --git a/platform-android/src/main/java/com/lyndir/masterpassword/EmergencyActivity.java b/platform-android/src/main/java/com/lyndir/masterpassword/EmergencyActivity.java deleted file mode 100644 index cb3f35d9..00000000 --- a/platform-android/src/main/java/com/lyndir/masterpassword/EmergencyActivity.java +++ /dev/null @@ -1,416 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static com.lyndir.lhunath.opal.system.util.StringUtils.strf; - -import android.app.*; -import android.content.*; -import android.content.ClipboardManager; -import android.graphics.Paint; -import android.os.Build; -import android.os.Bundle; -import android.text.*; -import android.text.method.PasswordTransformationMethod; -import android.view.View; -import android.view.WindowManager; -import android.widget.*; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.google.common.collect.ImmutableList; -import com.google.common.primitives.UnsignedInteger; -import com.google.common.util.concurrent.*; -import com.lyndir.lhunath.opal.system.logging.Logger; -import java.text.MessageFormat; -import java.util.*; -import java.util.concurrent.*; -import javax.annotation.Nullable; - - -public class EmergencyActivity extends Activity { - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( EmergencyActivity.class ); - private static final ClipData EMPTY_CLIP = new ClipData( new ClipDescription( "", new String[0] ), new ClipData.Item( "" ) ); - private static final int PASSWORD_NOTIFICATION = 0; - public static final int CLIPBOARD_CLEAR_DELAY = 20 /* s */ * MPConstant.MS_PER_S; - - private final Preferences preferences = Preferences.get( this ); - private final ListeningExecutorService executor = MoreExecutors.listeningDecorator( Executors.newSingleThreadExecutor() ); - private final ImmutableList allResultTypes = ImmutableList.copyOf( MPResultType.forClass( MPResultTypeClass.Template ) ); - private final ImmutableList allVersions = ImmutableList.copyOf( MPMasterKey.Version.values() ); - - private MPMasterKey masterKey; - - @BindView(R.id.progressView) - ProgressBar progressView; - - @BindView(R.id.fullNameField) - EditText fullNameField; - - @BindView(R.id.masterPasswordField) - EditText masterPasswordField; - - @BindView(R.id.siteNameField) - EditText siteNameField; - - @BindView(R.id.resultTypeButton) - Button resultTypeButton; - - @BindView(R.id.counterField) - Button siteCounterButton; - - @BindView(R.id.siteVersionButton) - Button siteVersionButton; - - @BindView(R.id.sitePasswordField) - Button sitePasswordField; - - @BindView(R.id.sitePasswordTip) - TextView sitePasswordTip; - - @BindView(R.id.rememberFullNameField) - CheckBox rememberFullNameField; - - @BindView(R.id.rememberPasswordField) - CheckBox forgetPasswordField; - - @BindView(R.id.maskPasswordField) - CheckBox maskPasswordField; - - private int id_userName; - private int id_masterPassword; - private String sitePassword; - - public static void start(final Context context) { - context.startActivity( new Intent( context, EmergencyActivity.class ) ); - } - - @Override - public void onCreate(@Nullable final Bundle savedInstanceState) { - super.onCreate( savedInstanceState ); - - getWindow().setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE ); - setContentView( R.layout.activity_emergency ); - ButterKnife.bind( this ); - - fullNameField.setOnFocusChangeListener( new ValueChangedListener() { - @Override - void update() { - updateMasterKey(); - } - } ); - masterPasswordField.setOnFocusChangeListener( new ValueChangedListener() { - @Override - void update() { - updateMasterKey(); - } - } ); - siteNameField.addTextChangedListener( new ValueChangedListener() { - @Override - void update() { - siteCounterButton.setText( MessageFormat.format( "{0}", 1 ) ); - updateSitePassword(); - } - } ); - resultTypeButton.setOnClickListener( new View.OnClickListener() { - @Override - public void onClick(final View v) { - @SuppressWarnings("SuspiciousMethodCalls") - MPResultType resultType = - allResultTypes.get( (allResultTypes.indexOf( resultTypeButton.getTag() ) + 1) % allResultTypes.size() ); - preferences.setDefaultResultType( resultType ); - resultTypeButton.setTag( resultType ); - resultTypeButton.setText( resultType.getShortName() ); - updateSitePassword(); - } - } ); - siteCounterButton.setOnClickListener( new View.OnClickListener() { - @Override - public void onClick(final View v) { - UnsignedInteger counter = - UnsignedInteger.valueOf( siteCounterButton.getText().toString() ).plus( UnsignedInteger.ONE ); - siteCounterButton.setText( MessageFormat.format( "{0}", counter ) ); - updateSitePassword(); - } - } ); - siteVersionButton.setOnClickListener( new View.OnClickListener() { - @Override - public void onClick(final View v) { - @SuppressWarnings("SuspiciousMethodCalls") - MPMasterKey.Version siteVersion = - allVersions.get( (allVersions.indexOf( siteVersionButton.getTag() ) + 1) % allVersions.size() ); - preferences.setDefaultVersion( siteVersion ); - siteVersionButton.setTag( siteVersion ); - siteVersionButton.setText( siteVersion.name() ); - updateMasterKey(); - } - } ); - sitePasswordField.addTextChangedListener( new ValueChangedListener() { - @Override - void update() { - boolean noPassword = TextUtils.isEmpty( sitePasswordField.getText() ); - sitePasswordTip.setVisibility( noPassword? View.INVISIBLE: View.VISIBLE ); - - if (noPassword) - sitePassword = null; - } - } ); - - fullNameField.setTypeface( Res.get( this ).exo_Thin ); - fullNameField.setPaintFlags( fullNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG ); - masterPasswordField.setTypeface( Res.get( this ).sourceCodePro_ExtraLight ); - masterPasswordField.setPaintFlags( masterPasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG ); - siteNameField.setTypeface( Res.get( this ).exo_Regular ); - siteNameField.setPaintFlags( siteNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG ); - sitePasswordField.setTypeface( Res.get( this ).sourceCodePro_Black ); - sitePasswordField.setPaintFlags( sitePasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG ); - - rememberFullNameField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { - preferences.setRememberFullName( isChecked ); - if (isChecked) - preferences.setFullName( fullNameField.getText().toString() ); - else - preferences.setFullName( null ); - } - } ); - forgetPasswordField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { - preferences.setForgetPassword( isChecked ); - } - } ); - maskPasswordField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { - preferences.setMaskPassword( isChecked ); - sitePasswordField.setTransformationMethod( isChecked? new PasswordTransformationMethod(): null ); - } - } ); - } - - @Override - protected void onResume() { - super.onResume(); - -// FIXME: MasterKey.setAllowNativeByDefault( preferences.isAllowNativeKDF() ); - - fullNameField.setText( preferences.getFullName() ); - rememberFullNameField.setChecked( preferences.isRememberFullName() ); - forgetPasswordField.setChecked( preferences.isForgetPassword() ); - maskPasswordField.setChecked( preferences.isMaskPassword() ); - sitePasswordField.setTransformationMethod( preferences.isMaskPassword()? new PasswordTransformationMethod(): null ); - MPResultType defaultResultType = preferences.getDefaultResultType(); - resultTypeButton.setTag( defaultResultType ); - resultTypeButton.setText( defaultResultType.getShortName() ); - MPMasterKey.Version defaultVersion = preferences.getDefaultVersion(); - siteVersionButton.setTag( defaultVersion ); - siteVersionButton.setText( defaultVersion.name() ); - siteCounterButton.setText( MessageFormat.format( "{0}", 1 ) ); - - if (TextUtils.isEmpty( fullNameField.getText() )) - fullNameField.requestFocus(); - else if (TextUtils.isEmpty( masterPasswordField.getText() )) - masterPasswordField.requestFocus(); - else - siteNameField.requestFocus(); - } - - @Override - protected void onPause() { - if (preferences.isForgetPassword()) { - synchronized (this) { - id_userName = id_masterPassword = 0; - if (masterKey != null) - masterKey = null; - - masterPasswordField.setText( "" ); - } - } - - siteNameField.setText( "" ); - sitePasswordField.setText( "" ); - progressView.setVisibility( View.INVISIBLE ); - - super.onPause(); - } - - private synchronized void updateMasterKey() { - final String fullName = fullNameField.getText().toString(); - final char[] masterPassword = masterPasswordField.getText().toString().toCharArray(); - if ((id_userName == fullName.hashCode()) - && (id_masterPassword == Arrays.hashCode( masterPassword ))) - if (masterKey != null) - return; - - id_userName = fullName.hashCode(); - id_masterPassword = Arrays.hashCode( masterPassword ); - - if (preferences.isRememberFullName()) - preferences.setFullName( fullName ); - - if (fullName.isEmpty() || (masterPassword.length == 0)) { - sitePasswordField.setText( "" ); - progressView.setVisibility( View.INVISIBLE ); - return; - } - - sitePasswordField.setText( "" ); - progressView.setVisibility( View.VISIBLE ); - masterKey = new MPMasterKey( fullName, masterPassword ); - updateSitePassword(); - } - - private void updateSitePassword() { - final String siteName = siteNameField.getText().toString(); - final MPResultType type = (MPResultType) resultTypeButton.getTag(); - final UnsignedInteger counter = UnsignedInteger.valueOf( siteCounterButton.getText().toString() ); - final MPMasterKey.Version version = (MPMasterKey.Version) siteVersionButton.getTag(); - - if ((masterKey == null) || siteName.isEmpty() || (type == null)) { - sitePasswordField.setText( "" ); - progressView.setVisibility( View.INVISIBLE ); - - if (masterKey == null) - updateMasterKey(); - return; - } - - sitePasswordField.setText( "" ); - progressView.setVisibility( View.VISIBLE ); - executor.submit( new Runnable() { - @Override - public void run() { - try { - sitePassword = masterKey.siteResult( siteName, counter, MPKeyPurpose.Authentication, null, type, null, version ); - - runOnUiThread( new Runnable() { - @Override - public void run() { - sitePasswordField.setText( sitePassword ); - progressView.setVisibility( View.INVISIBLE ); - } - } ); - } - catch (final MPInvalidatedException ignored) { - sitePasswordField.setText( "" ); - progressView.setVisibility( View.INVISIBLE ); - } - catch (final RuntimeException e) { - sitePasswordField.setText( "" ); - progressView.setVisibility( View.INVISIBLE ); - logger.err( e, "While generating site password." ); - throw e; - } - } - } ); - } - - public void integrityTests(final View view) { - if (masterKey != null) - masterKey = null; - - TestActivity.startNoSkip( this ); - } - - public void copySitePassword(final View view) { - final String currentSitePassword = sitePassword; - if (TextUtils.isEmpty( currentSitePassword )) - return; - - final ClipboardManager clipboardManager = (ClipboardManager) getSystemService( CLIPBOARD_SERVICE ); - final NotificationManager notificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE ); - - String title = strf( "Password for %s", siteNameField.getText() ); - ClipDescription description = new ClipDescription( title, new String[]{ ClipDescription.MIMETYPE_TEXT_PLAIN } ); - clipboardManager.setPrimaryClip( new ClipData( description, new ClipData.Item( currentSitePassword ) ) ); - - Notification.Builder notificationBuilder = new Notification.Builder( this ).setContentTitle( title ) - .setContentText( "Paste the password into your app." ) - .setSmallIcon( R.drawable.icon ) - .setAutoCancel( true ); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - notificationBuilder.setVisibility( Notification.VISIBILITY_SECRET ) - .setCategory( Notification.CATEGORY_RECOMMENDATION ) - .setLocalOnly( true ); - notificationManager.notify( PASSWORD_NOTIFICATION, notificationBuilder.build() ); - final Timer timer = new Timer(); - timer.schedule( new TimerTask() { - @Override - public void run() { - ClipData clip = clipboardManager.getPrimaryClip(); - for (int i = 0; i < clip.getItemCount(); ++i) - if (currentSitePassword.equals( clip.getItemAt( i ).coerceToText( EmergencyActivity.this ) )) { - clipboardManager.setPrimaryClip( EMPTY_CLIP ); - break; - } - notificationManager.cancel( PASSWORD_NOTIFICATION ); - timer.cancel(); - } - }, CLIPBOARD_CLEAR_DELAY ); - - Intent startMain = new Intent( Intent.ACTION_MAIN ); - startMain.addCategory( Intent.CATEGORY_HOME ); - startMain.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK ); - startActivity( startMain ); - } - - private abstract static class ValueChangedListener - implements TextWatcher, NumberPicker.OnValueChangeListener, AdapterView.OnItemSelectedListener, View.OnFocusChangeListener { - - abstract void update(); - - @Override - public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { - } - - @Override - public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { - } - - @Override - public void afterTextChanged(final Editable s) { - update(); - } - - @Override - public void onValueChange(final NumberPicker picker, final int oldVal, final int newVal) { - update(); - } - - @Override - public void onItemSelected(final AdapterView parent, final View view, final int position, final long id) { - update(); - } - - @Override - public void onNothingSelected(final AdapterView parent) { - update(); - } - - @Override - public void onFocusChange(final View v, final boolean hasFocus) { - if (!hasFocus) - update(); - } - } -} - diff --git a/platform-android/src/main/java/com/lyndir/masterpassword/MainThreadExecutor.java b/platform-android/src/main/java/com/lyndir/masterpassword/MainThreadExecutor.java deleted file mode 100644 index 13456524..00000000 --- a/platform-android/src/main/java/com/lyndir/masterpassword/MainThreadExecutor.java +++ /dev/null @@ -1,100 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import android.os.Handler; -import android.os.Looper; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Sets; -import java.util.*; -import java.util.concurrent.*; - - -/** - * @author lhunath, 2015-12-22 - */ -public class MainThreadExecutor extends AbstractExecutorService { - - private final Handler mHandler = new Handler( Looper.getMainLooper() ); - private final Set commands = Sets.newLinkedHashSet(); - private boolean shutdown; - - @Override - public void execute(final Runnable command) { - if (shutdown) - throw new RejectedExecutionException( "This executor has been shut down" ); - - synchronized (commands) { - commands.add( command ); - - mHandler.post( new Runnable() { - @Override - public void run() { - synchronized (commands) { - if (!commands.remove( command )) - // Command was removed, not executing. - return; - } - - command.run(); - } - } ); - } - } - - @Override - public void shutdown() { - shutdown = true; - } - - @Override - public List shutdownNow() { - shutdown = true; - mHandler.removeCallbacksAndMessages( null ); - - synchronized (commands) { - ImmutableList pendingTasks = ImmutableList.copyOf( commands ); - commands.clear(); - commands.notifyAll(); - return pendingTasks; - } - } - - @Override - public boolean isShutdown() { - return shutdown; - } - - @Override - public boolean isTerminated() { - synchronized (commands) { - return shutdown && commands.isEmpty(); - } - } - - @Override - public boolean awaitTermination(final long timeout, final TimeUnit unit) - throws InterruptedException { - if (isTerminated()) - return true; - - commands.wait( unit.toMillis( timeout ) ); - return isTerminated(); - } -} diff --git a/platform-android/src/main/java/com/lyndir/masterpassword/Preferences.java b/platform-android/src/main/java/com/lyndir/masterpassword/Preferences.java deleted file mode 100644 index 53f10d6a..00000000 --- a/platform-android/src/main/java/com/lyndir/masterpassword/Preferences.java +++ /dev/null @@ -1,166 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import android.content.Context; -import android.content.SharedPreferences; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import java.util.Set; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - - -/** - * @author lhunath, 2016-02-20 - */ -public final class Preferences { - - private static final String PREF_TESTS_PASSED = "integrityTestsPassed"; - private static final String PREF_NATIVE_KDF = "nativeKDF"; - private static final String PREF_REMEMBER_FULL_NAME = "rememberFullName"; - private static final String PREF_FORGET_PASSWORD = "forgetPassword"; - private static final String PREF_MASK_PASSWORD = "maskPassword"; - private static final String PREF_FULL_NAME = "fullName"; - private static final String PREF_RESULT_TYPE = "resultType"; - private static final String PREF_ALGORITHM_VERSION = "algorithmVersion"; - private static Preferences instance; - - private Context context; - @Nullable - private SharedPreferences prefs; - - public static synchronized Preferences get(final Context context) { - if (instance == null) - instance = new Preferences( context ); - - return instance; - } - - private Preferences(final Context context) { - this.context = context; - } - - @Nonnull - private SharedPreferences prefs() { - if (prefs == null) - prefs = (context = context.getApplicationContext()).getSharedPreferences( getClass().getCanonicalName(), Context.MODE_PRIVATE ); - - return prefs; - } - - public boolean setNativeKDFEnabled(final boolean enabled) { - if (isAllowNativeKDF() == enabled) - return false; - - prefs().edit().putBoolean( PREF_NATIVE_KDF, enabled ).apply(); - return true; - } - - public boolean isAllowNativeKDF() { - return prefs().getBoolean( PREF_NATIVE_KDF, true ); - } - - public boolean setTestsPassed(final Set value) { - if (Sets.symmetricDifference( getTestsPassed(), value ).isEmpty()) - return false; - - prefs().edit().putStringSet( PREF_TESTS_PASSED, value ).apply(); - return true; - } - - public Set getTestsPassed() { - return prefs().getStringSet( PREF_TESTS_PASSED, ImmutableSet.of() ); - } - - public boolean setRememberFullName(final boolean enabled) { - if (isRememberFullName() == enabled) - return false; - - prefs().edit().putBoolean( PREF_REMEMBER_FULL_NAME, enabled ).apply(); - return true; - } - - public boolean isRememberFullName() { - return prefs().getBoolean( PREF_REMEMBER_FULL_NAME, false ); - } - - public boolean setForgetPassword(final boolean enabled) { - if (isForgetPassword() == enabled) - return false; - - prefs().edit().putBoolean( PREF_FORGET_PASSWORD, enabled ).apply(); - return true; - } - - public boolean isForgetPassword() { - return prefs().getBoolean( PREF_FORGET_PASSWORD, false ); - } - - public boolean setMaskPassword(final boolean enabled) { - if (isMaskPassword() == enabled) - return false; - - prefs().edit().putBoolean( PREF_MASK_PASSWORD, enabled ).apply(); - return true; - } - - public boolean isMaskPassword() { - return prefs().getBoolean( PREF_MASK_PASSWORD, false ); - } - - public boolean setFullName(@Nullable final String value) { - if (getFullName().equals( value )) - return false; - - prefs().edit().putString( PREF_FULL_NAME, value ).apply(); - return true; - } - - @Nonnull - public String getFullName() { - return prefs().getString( PREF_FULL_NAME, "" ); - } - - public boolean setDefaultResultType(final MPResultType value) { - if (getDefaultResultType() == value) - return false; - - prefs().edit().putInt( PREF_RESULT_TYPE, value.ordinal() ).apply(); - return true; - } - - @Nonnull - public MPResultType getDefaultResultType() { - return MPResultType.values()[prefs().getInt( PREF_RESULT_TYPE, MPResultType.DEFAULT.ordinal() )]; - } - - public boolean setDefaultVersion(final MPMasterKey.Version value) { - if (getDefaultVersion() == value) - return false; - - prefs().edit().putInt( PREF_ALGORITHM_VERSION, value.ordinal() ).apply(); - return true; - } - - @Nonnull - public MPMasterKey.Version getDefaultVersion() { - return MPMasterKey.Version.values()[prefs().getInt( PREF_ALGORITHM_VERSION, MPMasterKey.Version.CURRENT.ordinal() )]; - } -} diff --git a/platform-android/src/main/java/com/lyndir/masterpassword/Res.java b/platform-android/src/main/java/com/lyndir/masterpassword/Res.java deleted file mode 100644 index 1e1fb13b..00000000 --- a/platform-android/src/main/java/com/lyndir/masterpassword/Res.java +++ /dev/null @@ -1,57 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Typeface; - - -/** - * @author lhunath, 2014-08-25 - */ -public final class Res { - - public final Typeface sourceCodePro_Black; - public final Typeface sourceCodePro_ExtraLight; - public final Typeface exo_Bold; - public final Typeface exo_ExtraBold; - public final Typeface exo_Regular; - public final Typeface exo_Thin; - - private static Res res; - - public static synchronized Res get(final Context context) { - if (res == null) - res = new Res( context ); - - return res; - } - - @SuppressWarnings("HardCodedStringLiteral") - private Res(final Context context) { - - sourceCodePro_Black = Typeface.createFromAsset( context.getResources().getAssets(), "SourceCodePro-Black.otf" ); - sourceCodePro_ExtraLight = Typeface.createFromAsset( context.getResources().getAssets(), "SourceCodePro-ExtraLight.otf" ); - exo_Bold = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Bold.otf" ); - exo_ExtraBold = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-ExtraBold.otf" ); - exo_Regular = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Regular.otf" ); - exo_Thin = Typeface.createFromAsset( context.getResources().getAssets(), "Exo2.0-Thin.otf" ); - } -} diff --git a/platform-android/src/main/java/com/lyndir/masterpassword/TestActivity.java b/platform-android/src/main/java/com/lyndir/masterpassword/TestActivity.java deleted file mode 100644 index 9c3f22b5..00000000 --- a/platform-android/src/main/java/com/lyndir/masterpassword/TestActivity.java +++ /dev/null @@ -1,194 +0,0 @@ -//============================================================================== -// This file is part of Master Password. -// Copyright (c) 2011-2017, Maarten Billemont. -// -// Master Password is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Master Password is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You can find a copy of the GNU General Public License in the -// LICENSE file. Alternatively, see . -//============================================================================== - -package com.lyndir.masterpassword; - -import static com.lyndir.lhunath.opal.system.util.StringUtils.strf; - -import android.app.*; -import android.content.Context; -import android.content.Intent; -import android.os.*; -import android.view.View; -import android.widget.*; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.google.common.base.*; -import com.google.common.collect.*; -import com.google.common.util.concurrent.*; -import com.lyndir.lhunath.opal.system.logging.Logger; -import java.util.concurrent.*; -import javax.annotation.Nullable; - - -public class TestActivity extends Activity implements MPTestSuite.Listener { - - @SuppressWarnings("UnusedDeclaration") - private static final Logger logger = Logger.get( TestActivity.class ); - - private final Preferences preferences = Preferences.get( this ); - private final ListeningExecutorService backgroundExecutor = MoreExecutors.listeningDecorator( Executors.newSingleThreadExecutor() ); - private final ListeningExecutorService mainExecutor = MoreExecutors.listeningDecorator( new MainThreadExecutor() ); - - @BindView(R.id.progressView) - ProgressBar progressView; - - @BindView(R.id.statusView) - TextView statusView; - - @BindView(R.id.logView) - TextView logView; - - @BindView(R.id.actionButton) - Button actionButton; - - @BindView(R.id.nativeKDFField) - CheckBox nativeKDFField; - - private MPTestSuite testSuite; - private ListenableFuture testFuture; - private Runnable action; - private ImmutableSet testNames; - - public static void startNoSkip(final Context context) { - context.startActivity( new Intent( context, TestActivity.class ) ); - } - - @Override - public void onCreate(@Nullable final Bundle savedInstanceState) { - super.onCreate( savedInstanceState ); - - setContentView( R.layout.activity_test ); - ButterKnife.bind( this ); - - nativeKDFField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) { - preferences.setNativeKDFEnabled( isChecked ); - // TODO: MasterKey.setAllowNativeByDefault( isChecked ); - } - } ); - - try { - setStatus( 0, 0, null ); - testSuite = new MPTestSuite(); - testSuite.setListener( this ); - testNames = FluentIterable.from( testSuite.getTests().getCases() ).transform( - new Function() { - @Nullable - @Override - public String apply(@Nullable final MPTests.Case input) { - return (input == null)? null: input.identifier; - } - } ).filter( Predicates.notNull() ).toSet(); - } - catch (final MPTestSuite.UnavailableException e) { - logger.err( e, "While loading test suite" ); - setStatus( R.string.tests_unavailable, R.string.tests_btn_unavailable, new Runnable() { - @Override - public void run() { - finish(); - } - } ); - } - } - - @Override - protected void onResume() { - super.onResume(); - - nativeKDFField.setChecked( preferences.isAllowNativeKDF() ); - - if (testFuture == null) - startTestSuite(); - } - - private void startTestSuite() { - if (testFuture != null) - testFuture.cancel( true ); - - // TODO: MasterKey.setAllowNativeByDefault( preferences.isAllowNativeKDF() ); - - setStatus( R.string.tests_testing, R.string.tests_btn_testing, null ); - Futures.addCallback( testFuture = backgroundExecutor.submit( testSuite ), new FutureCallback() { - @Override - public void onSuccess(@Nullable final Boolean result) { - if ((result != null) && result) - setStatus( R.string.tests_passed, R.string.tests_btn_passed, new Runnable() { - @Override - public void run() { - preferences.setTestsPassed( testNames ); - finish(); - } - } ); - else - setStatus( R.string.tests_failed, R.string.tests_btn_failed, new Runnable() { - @Override - public void run() { - startTestSuite(); - } - } ); - } - - @Override - public void onFailure(final Throwable t) { - logger.err( t, "While running test suite" ); - setStatus( R.string.tests_failed, R.string.tests_btn_failed, new Runnable() { - @Override - public void run() { - finish(); - } - } ); - } - }, mainExecutor ); - } - - public void onAction(final View v) { - if (action != null) - action.run(); - } - - private void setStatus(final int statusId, final int buttonId, @Nullable final Runnable action) { - this.action = action; - - if (statusId == 0) - statusView.setText( null ); - else - statusView.setText( statusId ); - - if (buttonId == 0) - actionButton.setText( null ); - else - actionButton.setText( buttonId ); - actionButton.setEnabled( action != null ); - } - - @Override - public void progress(final int current, final int max, final String messageFormat, final Object... args) { - runOnUiThread( new Runnable() { - @Override - public void run() { - logView.append( strf( "%n" + messageFormat, args ) ); - - progressView.setMax( max ); - progressView.setProgress( current ); - } - } ); - } -} - diff --git a/platform-android/src/main/res/drawable-mdpi/background.png b/platform-android/src/main/res/drawable-mdpi/background.png deleted file mode 100644 index 7386cfde..00000000 Binary files a/platform-android/src/main/res/drawable-mdpi/background.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-mdpi/icon.png b/platform-android/src/main/res/drawable-mdpi/icon.png deleted file mode 100644 index 85a067d3..00000000 Binary files a/platform-android/src/main/res/drawable-mdpi/icon.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-mdpi/icon_gears.png b/platform-android/src/main/res/drawable-mdpi/icon_gears.png deleted file mode 100644 index c939369e..00000000 Binary files a/platform-android/src/main/res/drawable-mdpi/icon_gears.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-mdpi/icon_key.png b/platform-android/src/main/res/drawable-mdpi/icon_key.png deleted file mode 100644 index 25ea04cf..00000000 Binary files a/platform-android/src/main/res/drawable-mdpi/icon_key.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-mdpi/icon_plus.png b/platform-android/src/main/res/drawable-mdpi/icon_plus.png deleted file mode 100644 index 53fec014..00000000 Binary files a/platform-android/src/main/res/drawable-mdpi/icon_plus.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-mdpi/img_identity.png b/platform-android/src/main/res/drawable-mdpi/img_identity.png deleted file mode 100644 index 74b24312..00000000 Binary files a/platform-android/src/main/res/drawable-mdpi/img_identity.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-mdpi/img_key.png b/platform-android/src/main/res/drawable-mdpi/img_key.png deleted file mode 100644 index 3156342d..00000000 Binary files a/platform-android/src/main/res/drawable-mdpi/img_key.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-mdpi/img_stats.png b/platform-android/src/main/res/drawable-mdpi/img_stats.png deleted file mode 100644 index 13be8b1d..00000000 Binary files a/platform-android/src/main/res/drawable-mdpi/img_stats.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xhdpi/background.png b/platform-android/src/main/res/drawable-xhdpi/background.png deleted file mode 100644 index afd7ff5c..00000000 Binary files a/platform-android/src/main/res/drawable-xhdpi/background.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xhdpi/icon.png b/platform-android/src/main/res/drawable-xhdpi/icon.png deleted file mode 100644 index 0f755b06..00000000 Binary files a/platform-android/src/main/res/drawable-xhdpi/icon.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xhdpi/icon_gears.png b/platform-android/src/main/res/drawable-xhdpi/icon_gears.png deleted file mode 100644 index e4cbaf04..00000000 Binary files a/platform-android/src/main/res/drawable-xhdpi/icon_gears.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xhdpi/icon_key.png b/platform-android/src/main/res/drawable-xhdpi/icon_key.png deleted file mode 100644 index af6c44cd..00000000 Binary files a/platform-android/src/main/res/drawable-xhdpi/icon_key.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xhdpi/icon_plus.png b/platform-android/src/main/res/drawable-xhdpi/icon_plus.png deleted file mode 100644 index cffdd7d9..00000000 Binary files a/platform-android/src/main/res/drawable-xhdpi/icon_plus.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xhdpi/img_identity.png b/platform-android/src/main/res/drawable-xhdpi/img_identity.png deleted file mode 100644 index 1455cdb9..00000000 Binary files a/platform-android/src/main/res/drawable-xhdpi/img_identity.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xhdpi/img_key.png b/platform-android/src/main/res/drawable-xhdpi/img_key.png deleted file mode 100644 index 336ddd36..00000000 Binary files a/platform-android/src/main/res/drawable-xhdpi/img_key.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xhdpi/img_stats.png b/platform-android/src/main/res/drawable-xhdpi/img_stats.png deleted file mode 100644 index 61bfa3f3..00000000 Binary files a/platform-android/src/main/res/drawable-xhdpi/img_stats.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xxxhdpi/background.png b/platform-android/src/main/res/drawable-xxxhdpi/background.png deleted file mode 100644 index 3213fac7..00000000 Binary files a/platform-android/src/main/res/drawable-xxxhdpi/background.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable-xxxhdpi/icon.png b/platform-android/src/main/res/drawable-xxxhdpi/icon.png deleted file mode 100644 index e17469f8..00000000 Binary files a/platform-android/src/main/res/drawable-xxxhdpi/icon.png and /dev/null differ diff --git a/platform-android/src/main/res/drawable/divider.png b/platform-android/src/main/res/drawable/divider.png deleted file mode 100644 index 35cf2a23..00000000 Binary files a/platform-android/src/main/res/drawable/divider.png and /dev/null differ diff --git a/platform-android/src/main/res/layout/activity_emergency.xml b/platform-android/src/main/res/layout/activity_emergency.xml deleted file mode 100644 index 2c0fb79b..00000000 --- a/platform-android/src/main/res/layout/activity_emergency.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - -