Merge branch 'master' of github.com:Lyndir/MasterPassword
Conflicts: Site/2013-05/index.html
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
# OS-Specific junk.
|
# OS-Specific junk.
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
# IntelliJ
|
# IntelliJ
|
||||||
/MasterPassword/Java/.idea
|
/MasterPassword/Java/.idea
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false">
|
||||||
|
<file url="file://$PROJECT_DIR$/MasterPassword/Java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-algorithm" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-cli" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-gui" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-model" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
@ -218,3 +218,8 @@ OBJC_EXTERN void CLSNSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,
|
|||||||
- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id <CLSCrashReport>)crash;
|
- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id <CLSCrashReport>)crash;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `CrashlyticsKit` can be used as a parameter to `[Fabric with:@[CrashlyticsKit]];` in Objective-C. In Swift, simply use `Crashlytics()`
|
||||||
|
*/
|
||||||
|
#define CrashlyticsKit [Crashlytics sharedInstance]
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>FMWK</string>
|
<string>FMWK</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>2.2.5</string>
|
<string>2.2.9</string>
|
||||||
<key>CFBundleSupportedPlatforms</key>
|
<key>CFBundleSupportedPlatforms</key>
|
||||||
<array>
|
<array>
|
||||||
<string>iPhoneOS</string>
|
<string>iPhoneOS</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>40</string>
|
<string>44</string>
|
||||||
<key>DTPlatformName</key>
|
<key>DTPlatformName</key>
|
||||||
<string>iphoneos</string>
|
<string>iphoneos</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
|
BIN
External/iOS/Crashlytics.framework/run
vendored
BIN
External/iOS/Crashlytics.framework/submit
vendored
@ -39,7 +39,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Optional features.
|
# Optional features.
|
||||||
mpw_color=0 # Colorized Identicon, requires libncurses-dev
|
mpw_color=1 # Colorized Identicon, requires libncurses-dev
|
||||||
|
|
||||||
|
|
||||||
### DEPENDENCIES
|
### DEPENDENCIES
|
||||||
@ -204,11 +204,11 @@ mpw() {
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Building target: $target..."
|
echo "Building target: $target..."
|
||||||
CFLAGS=(
|
local CFLAGS=(
|
||||||
# include paths
|
# include paths
|
||||||
-I"lib/include"
|
-I"lib/include"
|
||||||
)
|
)
|
||||||
LDFLAGS=(
|
local LDFLAGS=(
|
||||||
# scrypt
|
# scrypt
|
||||||
"lib/scrypt/scrypt-crypto_aesctr.o"
|
"lib/scrypt/scrypt-crypto_aesctr.o"
|
||||||
"lib/scrypt/scrypt-sha256.o"
|
"lib/scrypt/scrypt-sha256.o"
|
||||||
@ -240,11 +240,11 @@ mpw-bench() {
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Building target: $target..."
|
echo "Building target: $target..."
|
||||||
CFLAGS=(
|
local CFLAGS=(
|
||||||
# include paths
|
# include paths
|
||||||
-I"lib/include"
|
-I"lib/include"
|
||||||
)
|
)
|
||||||
LDFLAGS=(
|
local LDFLAGS=(
|
||||||
# scrypt
|
# scrypt
|
||||||
"lib/scrypt/scrypt-crypto_aesctr.o"
|
"lib/scrypt/scrypt-crypto_aesctr.o"
|
||||||
"lib/scrypt/scrypt-sha256.o"
|
"lib/scrypt/scrypt-sha256.o"
|
||||||
@ -264,6 +264,9 @@ mpw-bench() {
|
|||||||
-l"crypto"
|
-l"crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc "${CFLAGS[@]}" "$@" -c mpw-algorithm.c -o mpw-algorithm.o
|
||||||
|
cc "${CFLAGS[@]}" "$@" -c mpw-types.c -o mpw-types.o
|
||||||
|
cc "${CFLAGS[@]}" "$@" -c mpw-util.c -o mpw-util.o
|
||||||
cc "${CFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" \
|
cc "${CFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" \
|
||||||
"${LDFLAGS[@]}" "mpw-bench.c" -o "mpw-bench"
|
"${LDFLAGS[@]}" "mpw-bench.c" -o "mpw-bench"
|
||||||
echo "done! Now use ./mpw-bench"
|
echo "done! Now use ./mpw-bench"
|
||||||
@ -276,13 +279,13 @@ mpw-tests() {
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Building target: $target..."
|
echo "Building target: $target..."
|
||||||
CFLAGS=(
|
local CFLAGS=(
|
||||||
# include paths
|
# include paths
|
||||||
-I"lib/include"
|
-I"lib/include"
|
||||||
-I"/usr/include/libxml2"
|
-I"/usr/include/libxml2"
|
||||||
-I"/usr/local/include/libxml2"
|
-I"/usr/local/include/libxml2"
|
||||||
)
|
)
|
||||||
LDFLAGS=(
|
local LDFLAGS=(
|
||||||
# scrypt
|
# scrypt
|
||||||
"lib/scrypt/scrypt-crypto_aesctr.o"
|
"lib/scrypt/scrypt-crypto_aesctr.o"
|
||||||
"lib/scrypt/scrypt-sha256.o"
|
"lib/scrypt/scrypt-sha256.o"
|
||||||
@ -296,7 +299,10 @@ mpw-tests() {
|
|||||||
-l"crypto" -l"xml2"
|
-l"crypto" -l"xml2"
|
||||||
)
|
)
|
||||||
|
|
||||||
cc "${CFLAGS[@]}" "$@" -c mpw-tests-util.c -o mpw-tests-util.o
|
cc "${CFLAGS[@]}" "$@" -c mpw-algorithm.c -o mpw-algorithm.o
|
||||||
|
cc "${CFLAGS[@]}" "$@" -c mpw-types.c -o mpw-types.o
|
||||||
|
cc "${CFLAGS[@]}" "$@" -c mpw-util.c -o mpw-util.o
|
||||||
|
cc "${CFLAGS[@]}" "$@" -c mpw-tests-util.c -o mpw-tests-util.o
|
||||||
cc "${CFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" "mpw-tests-util.o" \
|
cc "${CFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" "mpw-tests-util.o" \
|
||||||
"${LDFLAGS[@]}" "mpw-tests.c" -o "mpw-tests"
|
"${LDFLAGS[@]}" "mpw-tests.c" -o "mpw-tests"
|
||||||
echo "done! Now use ./mpw-tests"
|
echo "done! Now use ./mpw-tests"
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "mpw-types.h"
|
||||||
#include "mpw-util.h"
|
#include "mpw-util.h"
|
||||||
|
|
||||||
#define MP_N 32768
|
#define MP_N 32768
|
||||||
@ -37,7 +38,8 @@ static const char mpw_characterFromClass_v0(char characterClass, uint16_t seedBy
|
|||||||
static const uint8_t *mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) {
|
static const uint8_t *mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) {
|
||||||
|
|
||||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||||
trc( "fullName: %s\n", fullName );
|
trc( "algorithm: v%d\n", 0 );
|
||||||
|
trc( "fullName: %s (%zu)\n", fullName, mpw_charlen( fullName ) );
|
||||||
trc( "masterPassword: %s\n", masterPassword );
|
trc( "masterPassword: %s\n", masterPassword );
|
||||||
trc( "key scope: %s\n", mpKeyScope );
|
trc( "key scope: %s\n", mpKeyScope );
|
||||||
|
|
||||||
@ -71,11 +73,16 @@ static const char *mpw_passwordForSite_v0(const uint8_t *masterKey, const char *
|
|||||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||||
|
|
||||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||||
|
trc( "algorithm: v%d\n", 0 );
|
||||||
trc( "siteName: %s\n", siteName );
|
trc( "siteName: %s\n", siteName );
|
||||||
trc( "siteCounter: %d\n", siteCounter );
|
trc( "siteCounter: %d\n", siteCounter );
|
||||||
trc( "siteVariant: %d\n", siteVariant );
|
trc( "siteVariant: %d\n", siteVariant );
|
||||||
trc( "siteType: %d\n", siteType );
|
trc( "siteType: %d\n", siteType );
|
||||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "<empty>": siteContext );
|
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext );
|
||||||
|
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
|
||||||
|
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
|
||||||
|
mpw_hex_l( htonl( siteCounter ) ),
|
||||||
|
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext );
|
||||||
|
|
||||||
// Calculate the site seed.
|
// Calculate the site seed.
|
||||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "mpw-types.h"
|
||||||
#include "mpw-util.h"
|
#include "mpw-util.h"
|
||||||
|
|
||||||
#define MP_N 32768
|
#define MP_N 32768
|
||||||
@ -21,7 +22,8 @@
|
|||||||
static const uint8_t *mpw_masterKeyForUser_v1(const char *fullName, const char *masterPassword) {
|
static const uint8_t *mpw_masterKeyForUser_v1(const char *fullName, const char *masterPassword) {
|
||||||
|
|
||||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||||
trc( "fullName: %s\n", fullName );
|
trc( "algorithm: v%d\n", 1 );
|
||||||
|
trc( "fullName: %s (%zu)\n", fullName, mpw_charlen( fullName ) );
|
||||||
trc( "masterPassword: %s\n", masterPassword );
|
trc( "masterPassword: %s\n", masterPassword );
|
||||||
trc( "key scope: %s\n", mpKeyScope );
|
trc( "key scope: %s\n", mpKeyScope );
|
||||||
|
|
||||||
@ -55,11 +57,16 @@ static const char *mpw_passwordForSite_v1(const uint8_t *masterKey, const char *
|
|||||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||||
|
|
||||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||||
|
trc( "algorithm: v%d\n", 1 );
|
||||||
trc( "siteName: %s\n", siteName );
|
trc( "siteName: %s\n", siteName );
|
||||||
trc( "siteCounter: %d\n", siteCounter );
|
trc( "siteCounter: %d\n", siteCounter );
|
||||||
trc( "siteVariant: %d\n", siteVariant );
|
trc( "siteVariant: %d\n", siteVariant );
|
||||||
trc( "siteType: %d\n", siteType );
|
trc( "siteType: %d\n", siteType );
|
||||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "<empty>": siteContext );
|
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext );
|
||||||
|
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
|
||||||
|
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
|
||||||
|
mpw_hex_l( htonl( siteCounter ) ),
|
||||||
|
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext );
|
||||||
|
|
||||||
// Calculate the site seed.
|
// Calculate the site seed.
|
||||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "mpw-types.h"
|
||||||
#include "mpw-util.h"
|
#include "mpw-util.h"
|
||||||
|
|
||||||
#define MP_N 32768
|
#define MP_N 32768
|
||||||
@ -21,7 +22,8 @@
|
|||||||
static const uint8_t *mpw_masterKeyForUser_v2(const char *fullName, const char *masterPassword) {
|
static const uint8_t *mpw_masterKeyForUser_v2(const char *fullName, const char *masterPassword) {
|
||||||
|
|
||||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||||
trc( "fullName: %s\n", fullName );
|
trc( "algorithm: v%d\n", 2 );
|
||||||
|
trc( "fullName: %s (%zu)\n", fullName, mpw_charlen( fullName ) );
|
||||||
trc( "masterPassword: %s\n", masterPassword );
|
trc( "masterPassword: %s\n", masterPassword );
|
||||||
trc( "key scope: %s\n", mpKeyScope );
|
trc( "key scope: %s\n", mpKeyScope );
|
||||||
|
|
||||||
@ -55,11 +57,16 @@ static const char *mpw_passwordForSite_v2(const uint8_t *masterKey, const char *
|
|||||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||||
|
|
||||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||||
|
trc( "algorithm: v%d\n", 2 );
|
||||||
trc( "siteName: %s\n", siteName );
|
trc( "siteName: %s\n", siteName );
|
||||||
trc( "siteCounter: %d\n", siteCounter );
|
trc( "siteCounter: %d\n", siteCounter );
|
||||||
trc( "siteVariant: %d\n", siteVariant );
|
trc( "siteVariant: %d\n", siteVariant );
|
||||||
trc( "siteType: %d\n", siteType );
|
trc( "siteType: %d\n", siteType );
|
||||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "<empty>": siteContext );
|
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext );
|
||||||
|
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
|
||||||
|
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
|
||||||
|
mpw_hex_l( htonl( siteCounter ) ),
|
||||||
|
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext );
|
||||||
|
|
||||||
// Calculate the site seed.
|
// Calculate the site seed.
|
||||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include "mpw-types.h"
|
||||||
#include "mpw-util.h"
|
#include "mpw-util.h"
|
||||||
|
|
||||||
#define MP_N 32768
|
#define MP_N 32768
|
||||||
@ -21,7 +22,8 @@
|
|||||||
static const uint8_t *mpw_masterKeyForUser_v3(const char *fullName, const char *masterPassword) {
|
static const uint8_t *mpw_masterKeyForUser_v3(const char *fullName, const char *masterPassword) {
|
||||||
|
|
||||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||||
trc( "fullName: %s\n", fullName );
|
trc( "algorithm: v%d\n", 3 );
|
||||||
|
trc( "fullName: %s (%zu)\n", fullName, strlen( fullName ) );
|
||||||
trc( "masterPassword: %s\n", masterPassword );
|
trc( "masterPassword: %s\n", masterPassword );
|
||||||
trc( "key scope: %s\n", mpKeyScope );
|
trc( "key scope: %s\n", mpKeyScope );
|
||||||
|
|
||||||
@ -55,11 +57,16 @@ static const char *mpw_passwordForSite_v3(const uint8_t *masterKey, const char *
|
|||||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||||
|
|
||||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||||
|
trc( "algorithm: v%d\n", 3 );
|
||||||
trc( "siteName: %s\n", siteName );
|
trc( "siteName: %s\n", siteName );
|
||||||
trc( "siteCounter: %d\n", siteCounter );
|
trc( "siteCounter: %d\n", siteCounter );
|
||||||
trc( "siteVariant: %d\n", siteVariant );
|
trc( "siteVariant: %d\n", siteVariant );
|
||||||
trc( "siteType: %d\n", siteType );
|
trc( "siteType: %d\n", siteType );
|
||||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "<empty>": siteContext );
|
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext );
|
||||||
|
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
|
||||||
|
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
|
||||||
|
mpw_hex_l( htonl( siteCounter ) ),
|
||||||
|
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext );
|
||||||
|
|
||||||
// Calculate the site seed.
|
// Calculate the site seed.
|
||||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
static void usage() {
|
static void usage() {
|
||||||
|
|
||||||
fprintf( stderr, "Usage: mpw [-u name] [-t type] [-c counter] site\n\n" );
|
fprintf( stderr, "Usage: mpw [-u name] [-t type] [-c counter] [-V version] [-v variant] [-C context] [-h] site\n\n" );
|
||||||
fprintf( stderr, " -u name Specify the full name of the user.\n"
|
fprintf( stderr, " -u name Specify the full name of the user.\n"
|
||||||
" Defaults to %s in env.\n\n", MP_env_fullname );
|
" Defaults to %s in env.\n\n", MP_env_fullname );
|
||||||
fprintf( stderr, " -t type Specify the password's template.\n"
|
fprintf( stderr, " -t type Specify the password's template.\n"
|
||||||
|
@ -21,6 +21,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
|
|
||||||
// Read in the test case.
|
// Read in the test case.
|
||||||
xmlChar *id = mpw_xmlTestCaseString( testCase, "id" );
|
xmlChar *id = mpw_xmlTestCaseString( testCase, "id" );
|
||||||
|
uint32_t algorithm = mpw_xmlTestCaseInteger( testCase, "algorithm" );
|
||||||
xmlChar *fullName = mpw_xmlTestCaseString( testCase, "fullName" );
|
xmlChar *fullName = mpw_xmlTestCaseString( testCase, "fullName" );
|
||||||
xmlChar *masterPassword = mpw_xmlTestCaseString( testCase, "masterPassword" );
|
xmlChar *masterPassword = mpw_xmlTestCaseString( testCase, "masterPassword" );
|
||||||
xmlChar *keyID = mpw_xmlTestCaseString( testCase, "keyID" );
|
xmlChar *keyID = mpw_xmlTestCaseString( testCase, "keyID" );
|
||||||
@ -36,16 +37,20 @@ int main(int argc, char *const argv[]) {
|
|||||||
|
|
||||||
// Run the test case.
|
// Run the test case.
|
||||||
fprintf( stdout, "test case %s... ", id );
|
fprintf( stdout, "test case %s... ", id );
|
||||||
|
if (!xmlStrlen( result )) {
|
||||||
|
fprintf( stdout, "abstract.\n" );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. calculate the master key.
|
// 1. calculate the master key.
|
||||||
const uint8_t *masterKey = mpw_masterKeyForUser(
|
const uint8_t *masterKey = mpw_masterKeyForUser(
|
||||||
(char *)fullName, (char *)masterPassword, MPAlgorithmVersionCurrent );
|
(char *)fullName, (char *)masterPassword, algorithm );
|
||||||
if (!masterKey)
|
if (!masterKey)
|
||||||
ftl( "Couldn't derive master key." );
|
ftl( "Couldn't derive master key." );
|
||||||
|
|
||||||
// 2. calculate the site password.
|
// 2. calculate the site password.
|
||||||
const char *sitePassword = mpw_passwordForSite(
|
const char *sitePassword = mpw_passwordForSite(
|
||||||
masterKey, (char *)siteName, siteType, siteCounter, siteVariant, (char *)siteContext, MPAlgorithmVersionCurrent );
|
masterKey, (char *)siteName, siteType, siteCounter, siteVariant, (char *)siteContext, algorithm );
|
||||||
mpw_free( masterKey, MP_dkLen );
|
mpw_free( masterKey, MP_dkLen );
|
||||||
if (!sitePassword)
|
if (!sitePassword)
|
||||||
ftl( "Couldn't derive site password." );
|
ftl( "Couldn't derive site password." );
|
||||||
@ -56,7 +61,7 @@ int main(int argc, char *const argv[]) {
|
|||||||
|
|
||||||
else {
|
else {
|
||||||
++failedTests;
|
++failedTests;
|
||||||
fprintf( stdout, "FAILED! (result %s != expected %s)\n", result, sitePassword );
|
fprintf( stdout, "FAILED! (got %s != expected %s)\n", sitePassword, result );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free test case.
|
// Free test case.
|
||||||
|
@ -21,15 +21,17 @@
|
|||||||
|
|
||||||
const MPSiteType mpw_typeWithName(const char *typeName) {
|
const MPSiteType mpw_typeWithName(const char *typeName) {
|
||||||
|
|
||||||
|
// Lower-case and trim optionally leading "Generated" string from typeName to standardize it.
|
||||||
|
size_t stdTypeNameOffset = 0;
|
||||||
size_t stdTypeNameSize = strlen( typeName );
|
size_t stdTypeNameSize = strlen( typeName );
|
||||||
char stdTypeName[strlen( typeName )];
|
if (strstr(typeName, "Generated" ) == typeName)
|
||||||
if (stdTypeNameSize > strlen( "generated" ))
|
stdTypeNameSize -= (stdTypeNameOffset = strlen( "Generated" ));
|
||||||
strcpy( stdTypeName, typeName + strlen( "generated" ) );
|
char stdTypeName[stdTypeNameSize + 1];
|
||||||
else
|
for (size_t c = 0; c < stdTypeNameSize; ++c)
|
||||||
strcpy( stdTypeName, typeName );
|
stdTypeName[c] = (char)tolower( typeName[c + stdTypeNameOffset] );
|
||||||
for (char *tN = stdTypeName; *tN; ++tN)
|
stdTypeName[stdTypeNameSize] = '\0';
|
||||||
*tN = (char)tolower( *tN );
|
|
||||||
|
|
||||||
|
// Find what site type is represented by the type name.
|
||||||
if (0 == strcmp( stdTypeName, "x" ) || 0 == strcmp( stdTypeName, "max" ) || 0 == strcmp( stdTypeName, "maximum" ))
|
if (0 == strcmp( stdTypeName, "x" ) || 0 == strcmp( stdTypeName, "max" ) || 0 == strcmp( stdTypeName, "maximum" ))
|
||||||
return MPSiteTypeGeneratedMaximum;
|
return MPSiteTypeGeneratedMaximum;
|
||||||
if (0 == strcmp( stdTypeName, "l" ) || 0 == strcmp( stdTypeName, "long" ))
|
if (0 == strcmp( stdTypeName, "l" ) || 0 == strcmp( stdTypeName, "long" ))
|
||||||
@ -47,11 +49,10 @@ const MPSiteType mpw_typeWithName(const char *typeName) {
|
|||||||
if (0 == strcmp( stdTypeName, "p" ) || 0 == strcmp( stdTypeName, "phrase" ))
|
if (0 == strcmp( stdTypeName, "p" ) || 0 == strcmp( stdTypeName, "phrase" ))
|
||||||
return MPSiteTypeGeneratedPhrase;
|
return MPSiteTypeGeneratedPhrase;
|
||||||
|
|
||||||
fprintf( stderr, "Not a generated type name: %s", stdTypeName );
|
ftl( "Not a generated type name: %s", stdTypeName );
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char **mpw_templatesForType(MPSiteType type, size_t *count) {
|
const char **mpw_templatesForType(MPSiteType type, size_t *count) {
|
||||||
|
|
||||||
if (!(type & MPSiteTypeClassGenerated)) {
|
if (!(type & MPSiteTypeClassGenerated)) {
|
||||||
ftl( "Not a generated type: %d", type );
|
ftl( "Not a generated type: %d", type );
|
||||||
@ -61,42 +62,42 @@ inline const char **mpw_templatesForType(MPSiteType type, size_t *count) {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MPSiteTypeGeneratedMaximum: {
|
case MPSiteTypeGeneratedMaximum: {
|
||||||
*count = 2;
|
return alloc_array( *count, const char *,
|
||||||
return (const char *[]){ "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
|
"anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" );
|
||||||
}
|
}
|
||||||
case MPSiteTypeGeneratedLong: {
|
case MPSiteTypeGeneratedLong: {
|
||||||
*count = 21;
|
return alloc_array( *count, const char *,
|
||||||
return (const char *[]){ "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno",
|
"CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno",
|
||||||
"CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno",
|
"CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno",
|
||||||
"CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno",
|
"CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno",
|
||||||
"CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno",
|
"CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno",
|
||||||
"CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno",
|
"CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno",
|
||||||
"CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno",
|
"CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno",
|
||||||
"CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" };
|
"CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" );
|
||||||
}
|
}
|
||||||
case MPSiteTypeGeneratedMedium: {
|
case MPSiteTypeGeneratedMedium: {
|
||||||
*count = 2;
|
return alloc_array( *count, const char *,
|
||||||
return (const char *[]){ "CvcnoCvc", "CvcCvcno" };
|
"CvcnoCvc", "CvcCvcno" );
|
||||||
}
|
}
|
||||||
case MPSiteTypeGeneratedBasic: {
|
case MPSiteTypeGeneratedBasic: {
|
||||||
*count = 3;
|
return alloc_array( *count, const char *,
|
||||||
return (const char *[]){ "aaanaaan", "aannaaan", "aaannaaa" };
|
"aaanaaan", "aannaaan", "aaannaaa" );
|
||||||
}
|
}
|
||||||
case MPSiteTypeGeneratedShort: {
|
case MPSiteTypeGeneratedShort: {
|
||||||
*count = 1;
|
return alloc_array( *count, const char *,
|
||||||
return (const char *[]){"Cvcn"};
|
"Cvcn" );
|
||||||
}
|
}
|
||||||
case MPSiteTypeGeneratedPIN: {
|
case MPSiteTypeGeneratedPIN: {
|
||||||
*count = 1;
|
return alloc_array( *count, const char *,
|
||||||
return (const char *[]){ "nnnn" };
|
"nnnn" );
|
||||||
}
|
}
|
||||||
case MPSiteTypeGeneratedName: {
|
case MPSiteTypeGeneratedName: {
|
||||||
*count = 1;
|
return alloc_array( *count, const char *,
|
||||||
return (const char *[]) {"cvccvcvcv"};
|
"cvccvcvcv" );
|
||||||
}
|
}
|
||||||
case MPSiteTypeGeneratedPhrase: {
|
case MPSiteTypeGeneratedPhrase: {
|
||||||
*count = 3;
|
return alloc_array( *count, const char *,
|
||||||
return (const char *[]){ "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" };
|
"cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" );
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
ftl( "Unknown generated type: %d", type );
|
ftl( "Unknown generated type: %d", type );
|
||||||
@ -113,15 +114,19 @@ const char *mpw_templateForType(MPSiteType type, uint8_t seedByte) {
|
|||||||
if (!count)
|
if (!count)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return templates[seedByte % count];
|
char const *template = templates[seedByte % count];
|
||||||
|
free( templates );
|
||||||
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MPSiteVariant mpw_variantWithName(const char *variantName) {
|
const MPSiteVariant mpw_variantWithName(const char *variantName) {
|
||||||
|
|
||||||
char stdVariantName[strlen( variantName )];
|
// Lower-case and trim optionally leading "generated" string from typeName to standardize it.
|
||||||
strcpy( stdVariantName, variantName );
|
size_t stdVariantNameSize = strlen( variantName );
|
||||||
for (char *vN = stdVariantName; *vN; ++vN)
|
char stdVariantName[stdVariantNameSize + 1];
|
||||||
*vN = (char)tolower( *vN );
|
for (size_t c = 0; c < stdVariantNameSize; ++c)
|
||||||
|
stdVariantName[c] = (char)tolower( variantName[c] );
|
||||||
|
stdVariantName[stdVariantNameSize] = '\0';
|
||||||
|
|
||||||
if (0 == strcmp( stdVariantName, "p" ) || 0 == strcmp( stdVariantName, "password" ))
|
if (0 == strcmp( stdVariantName, "p" ) || 0 == strcmp( stdVariantName, "password" ))
|
||||||
return MPSiteVariantPassword;
|
return MPSiteVariantPassword;
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#ifndef _MPW_TYPES_H
|
||||||
|
#define _MPW_TYPES_H
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -73,9 +75,10 @@ const char *mpw_scopeForVariant(MPSiteVariant variant);
|
|||||||
const MPSiteType mpw_typeWithName(const char *typeName);
|
const MPSiteType mpw_typeWithName(const char *typeName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return An array of internal strings that express the templates to use for the given type.
|
* @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.
|
* 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.
|
* 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(MPSiteType type, size_t *count);
|
const char **mpw_templatesForType(MPSiteType type, size_t *count);
|
||||||
/**
|
/**
|
||||||
@ -93,3 +96,4 @@ const char *mpw_charactersInClass(char characterClass);
|
|||||||
*/
|
*/
|
||||||
const char mpw_characterFromClass(char characterClass, uint8_t seedByte);
|
const char mpw_characterFromClass(char characterClass, uint8_t seedByte);
|
||||||
|
|
||||||
|
#endif // _MPW_TYPES_H
|
||||||
|
@ -9,7 +9,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <locale.h>
|
|
||||||
|
#ifdef COLOR
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <term.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <scrypt/sha256.h>
|
#include <scrypt/sha256.h>
|
||||||
#include <scrypt/crypto_scrypt.h>
|
#include <scrypt/crypto_scrypt.h>
|
||||||
@ -91,20 +96,31 @@ const char *mpw_idForBuf(const void *buf, size_t length) {
|
|||||||
return mpw_hex( hash, 32 );
|
return mpw_hex( hash, 32 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *mpw_hex_buf = NULL;
|
static char **mpw_hex_buf = NULL;
|
||||||
|
static unsigned int mpw_hex_buf_i = 0;
|
||||||
const char *mpw_hex(const void *buf, size_t length) {
|
const char *mpw_hex(const void *buf, size_t length) {
|
||||||
|
|
||||||
mpw_hex_buf = realloc( mpw_hex_buf, length * 2 + 1 );
|
if (!mpw_hex_buf) {
|
||||||
for (size_t kH = 0; kH < length; kH++)
|
mpw_hex_buf = malloc( 10 * sizeof( char* ) );
|
||||||
sprintf( &(mpw_hex_buf[kH * 2]), "%02X", ((const uint8_t *)buf)[kH] );
|
for (uint8_t i = 0; i < 10; ++i)
|
||||||
|
mpw_hex_buf[i] = NULL;
|
||||||
|
}
|
||||||
|
mpw_hex_buf_i = (mpw_hex_buf_i + 1) % 10;
|
||||||
|
|
||||||
return mpw_hex_buf;
|
mpw_hex_buf[mpw_hex_buf_i] = realloc( mpw_hex_buf[mpw_hex_buf_i], 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) {
|
||||||
|
return mpw_hex( &number, sizeof( number ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef COLOR
|
#ifdef COLOR
|
||||||
static int putvari;
|
static int putvari;
|
||||||
static char *putvarc = NULL;
|
static char *putvarc = NULL;
|
||||||
static bool istermsetup = false;
|
static int istermsetup = 0;
|
||||||
static void initputvar() {
|
static void initputvar() {
|
||||||
if (putvarc)
|
if (putvarc)
|
||||||
free(putvarc);
|
free(putvarc);
|
||||||
@ -165,8 +181,33 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) {
|
|||||||
return identicon;
|
return identicon;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t mpw_charlen(const char *string) {
|
/**
|
||||||
|
* @return the amount of bytes used by UTF-8 to encode a single character that starts with the given byte.
|
||||||
|
*/
|
||||||
|
static int mpw_charByteSize(unsigned char utf8Byte) {
|
||||||
|
|
||||||
setlocale( LC_ALL, "en_US.UTF-8" );
|
if (!utf8Byte)
|
||||||
return mbstowcs( NULL, string, strlen( string ) );
|
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_charlen(const char *utf8String) {
|
||||||
|
|
||||||
|
size_t charlen = 0;
|
||||||
|
char *remainingString = (char *)utf8String;
|
||||||
|
for (int charByteSize; (charByteSize = mpw_charByteSize( *remainingString )); remainingString += charByteSize)
|
||||||
|
++charlen;
|
||||||
|
|
||||||
|
return charlen;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,14 @@
|
|||||||
|
|
||||||
//// Buffers and memory.
|
//// Buffers and memory.
|
||||||
|
|
||||||
|
#define alloc_array(_count, _type, ...) ({ \
|
||||||
|
_type stackElements[] = { __VA_ARGS__ }; \
|
||||||
|
_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. */
|
/** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */
|
||||||
void mpw_pushBuf(
|
void mpw_pushBuf(
|
||||||
uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize);
|
uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize);
|
||||||
@ -58,6 +66,7 @@ uint8_t const *mpw_hmac_sha256(
|
|||||||
/** Encode a buffer as a string of hexadecimal characters.
|
/** Encode a buffer as a string of hexadecimal characters.
|
||||||
* @return A C-string in a reused buffer, do not free or store it. */
|
* @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(const void *buf, size_t length);
|
||||||
|
const char *mpw_hex_l(uint32_t number);
|
||||||
/** Encode a fingerprint for a buffer.
|
/** Encode a fingerprint for a buffer.
|
||||||
* @return A C-string in a reused buffer, do not free or store it. */
|
* @return A C-string in a reused buffer, do not free or store it. */
|
||||||
const char *mpw_idForBuf(const void *buf, size_t length);
|
const char *mpw_idForBuf(const void *buf, size_t length);
|
||||||
@ -67,4 +76,5 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword);
|
|||||||
|
|
||||||
//// String utilities.
|
//// String utilities.
|
||||||
|
|
||||||
const size_t mpw_charlen(const char *string);
|
/** @return The amount of display characters in the given UTF-8 string. */
|
||||||
|
const size_t mpw_charlen(const char *utf8String);
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
<name>Master Password Algorithm Implementation</name>
|
<name>Master Password Algorithm Implementation</name>
|
||||||
<description>The implementation of the Master Password algorithm</description>
|
<description>The implementation of the Master Password algorithm</description>
|
||||||
|
|
||||||
<groupId>com.lyndir.masterpassword</groupId>
|
|
||||||
<artifactId>masterpassword-algorithm</artifactId>
|
<artifactId>masterpassword-algorithm</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import com.lyndir.lhunath.opal.system.logging.Logger;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,7 +148,8 @@ public enum MPSiteType {
|
|||||||
*
|
*
|
||||||
* @return The type registered with the given name.
|
* @return The type registered with the given name.
|
||||||
*/
|
*/
|
||||||
public static MPSiteType forName(final String name) {
|
@Contract("!null -> !null, null -> null")
|
||||||
|
public static MPSiteType forName(@Nullable final String name) {
|
||||||
|
|
||||||
if (name == null)
|
if (name == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -3,6 +3,8 @@ package com.lyndir.masterpassword;
|
|||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +67,8 @@ public enum MPSiteVariant {
|
|||||||
*
|
*
|
||||||
* @return The variant registered with the given name.
|
* @return The variant registered with the given name.
|
||||||
*/
|
*/
|
||||||
public static MPSiteVariant forName(final String name) {
|
@Contract("!null -> !null, null -> null")
|
||||||
|
public static MPSiteVariant forName(@Nullable final String name) {
|
||||||
|
|
||||||
if (name == null)
|
if (name == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -3,10 +3,8 @@ package com.lyndir.masterpassword;
|
|||||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.lyndir.lhunath.opal.system.util.MetaObject;
|
import com.lyndir.lhunath.opal.system.util.MetaObject;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.lyndir.masterpassword;
|
package com.lyndir.masterpassword;
|
||||||
|
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import com.lyndir.lhunath.opal.system.util.MetaObject;
|
|
||||||
import com.lyndir.lhunath.opal.system.util.ObjectMeta;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +54,7 @@ public abstract class MasterKey {
|
|||||||
@Nullable
|
@Nullable
|
||||||
protected abstract byte[] deriveKey(final char[] masterPassword);
|
protected abstract byte[] deriveKey(final char[] masterPassword);
|
||||||
|
|
||||||
protected abstract Version getAlgorithm();
|
public abstract Version getAlgorithmVersion();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getFullName() {
|
public String getFullName() {
|
||||||
@ -63,18 +63,18 @@ public abstract class MasterKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
protected byte[] getMasterKey() {
|
protected byte[] getKey() {
|
||||||
|
|
||||||
return Preconditions.checkNotNull( masterKey );
|
return Preconditions.checkNotNull( masterKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getKeyID() {
|
public byte[] getKeyID() {
|
||||||
|
|
||||||
return idForBytes( getMasterKey() );
|
return idForBytes( getKey() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract String encode(@Nonnull final String siteName, final MPSiteType siteType, int siteCounter, final MPSiteVariant siteVariant,
|
public abstract String encode(@Nonnull final String siteName, final MPSiteType siteType, int siteCounter,
|
||||||
@Nullable final String siteContext);
|
final MPSiteVariant siteVariant, @Nullable final String siteContext);
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return masterKey != null;
|
return masterKey != null;
|
||||||
@ -95,8 +95,12 @@ public abstract class MasterKey {
|
|||||||
|
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
masterKey = deriveKey( masterPassword );
|
masterKey = deriveKey( masterPassword );
|
||||||
logger.trc( "masterKey ID: %s (derived in %.2fs)", CodeUtils.encodeHex( idForBytes( masterKey ) ),
|
|
||||||
(System.currentTimeMillis() - start) / 1000D );
|
if (masterKey == null)
|
||||||
|
logger.dbg( "masterKey calculation failed after %.2fs.", (System.currentTimeMillis() - start) / 1000D );
|
||||||
|
else
|
||||||
|
logger.trc( "masterKey ID: %s (derived in %.2fs)", CodeUtils.encodeHex( idForBytes( masterKey ) ),
|
||||||
|
(System.currentTimeMillis() - start) / 1000D );
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ public class MasterKeyV0 extends MasterKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Version getAlgorithm() {
|
public Version getAlgorithmVersion() {
|
||||||
|
|
||||||
return Version.V0;
|
return Version.V0;
|
||||||
}
|
}
|
||||||
@ -89,29 +89,37 @@ public class MasterKeyV0 extends MasterKey {
|
|||||||
byte[] siteNameBytes = siteName.getBytes( MP_charset );
|
byte[] siteNameBytes = siteName.getBytes( MP_charset );
|
||||||
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
|
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
|
||||||
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
||||||
byte[] siteContextBytes = siteContext == null? null: siteContext.getBytes( MP_charset );
|
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MP_charset );
|
||||||
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
||||||
logger.trc( "site scope: %s, context: %s", siteScope, siteContext == null? "<empty>": siteContext );
|
logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
|
||||||
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
|
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
|
||||||
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
||||||
siteContext == null? "(null)": siteContext );
|
siteContextBytes == null? "(null)": siteContext );
|
||||||
|
|
||||||
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MP_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MP_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
||||||
if (siteContextBytes != null)
|
if (siteContextBytes != null)
|
||||||
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
||||||
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
||||||
|
|
||||||
byte[] sitePasswordSeed = MP_mac.of( getMasterKey(), sitePasswordInfo );
|
byte[] sitePasswordSeedBytes = MP_mac.of( getKey(), sitePasswordInfo );
|
||||||
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeed ) ) );
|
int[] sitePasswordSeed = new int[sitePasswordSeedBytes.length];
|
||||||
|
for (int i = 0; i < sitePasswordSeedBytes.length; ++i) {
|
||||||
|
ByteBuffer buf = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( ByteOrder.BIG_ENDIAN );
|
||||||
|
Arrays.fill( buf.array(), sitePasswordSeedBytes[i] > 0? (byte)0x00: (byte) 0xFF );
|
||||||
|
buf.position( 2 );
|
||||||
|
buf.put( sitePasswordSeedBytes[i] ).rewind();
|
||||||
|
sitePasswordSeed[i] = buf.getInt() & 0xFFFF;
|
||||||
|
}
|
||||||
|
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeedBytes ) ) );
|
||||||
|
|
||||||
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
||||||
int templateIndex = sitePasswordSeed[0] & 0xFFFF;
|
int templateIndex = sitePasswordSeed[0];
|
||||||
MPTemplate template = siteType.getTemplateAtRollingIndex( templateIndex );
|
MPTemplate template = siteType.getTemplateAtRollingIndex( templateIndex );
|
||||||
logger.trc( "type %s, template: %s", siteType, template.getTemplateString() );
|
logger.trc( "type %s, template: %s", siteType, template.getTemplateString() );
|
||||||
|
|
||||||
StringBuilder password = new StringBuilder( template.length() );
|
StringBuilder password = new StringBuilder( template.length() );
|
||||||
for (int i = 0; i < template.length(); ++i) {
|
for (int i = 0; i < template.length(); ++i) {
|
||||||
int characterIndex = sitePasswordSeed[i + 1] & 0xFFFF;
|
int characterIndex = sitePasswordSeed[i + 1];
|
||||||
MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i );
|
MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i );
|
||||||
char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex );
|
char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex );
|
||||||
logger.trc( "class %c, index %d (0x%02X) -> character: %c", characterClass.getIdentifier(), characterIndex,
|
logger.trc( "class %c, index %d (0x%02X) -> character: %c", characterClass.getIdentifier(), characterIndex,
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
package com.lyndir.masterpassword;
|
package com.lyndir.masterpassword;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import com.lambdaworks.crypto.SCrypt;
|
|
||||||
import com.lyndir.lhunath.opal.system.*;
|
import com.lyndir.lhunath.opal.system.*;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
@ -30,7 +24,7 @@ public class MasterKeyV1 extends MasterKeyV0 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Version getAlgorithm() {
|
public Version getAlgorithmVersion() {
|
||||||
|
|
||||||
return Version.V1;
|
return Version.V1;
|
||||||
}
|
}
|
||||||
@ -52,19 +46,19 @@ public class MasterKeyV1 extends MasterKeyV0 {
|
|||||||
byte[] siteNameBytes = siteName.getBytes( MP_charset );
|
byte[] siteNameBytes = siteName.getBytes( MP_charset );
|
||||||
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
|
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
|
||||||
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
||||||
byte[] siteContextBytes = siteContext == null? null: siteContext.getBytes( MP_charset );
|
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MP_charset );
|
||||||
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
||||||
logger.trc( "site scope: %s, context: %s", siteScope, siteContext == null? "<empty>": siteContext );
|
logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
|
||||||
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
|
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
|
||||||
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
||||||
siteContext == null? "(null)": siteContext );
|
siteContextBytes == null? "(null)": siteContext );
|
||||||
|
|
||||||
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MP_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MP_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
||||||
if (siteContextBytes != null)
|
if (siteContextBytes != null)
|
||||||
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
||||||
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
||||||
|
|
||||||
byte[] sitePasswordSeed = MP_mac.of( getMasterKey(), sitePasswordInfo );
|
byte[] sitePasswordSeed = MP_mac.of( getKey(), sitePasswordInfo );
|
||||||
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeed ) ) );
|
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeed ) ) );
|
||||||
|
|
||||||
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
||||||
|
@ -23,7 +23,7 @@ public class MasterKeyV2 extends MasterKeyV1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Version getAlgorithm() {
|
public Version getAlgorithmVersion() {
|
||||||
|
|
||||||
return Version.V2;
|
return Version.V2;
|
||||||
}
|
}
|
||||||
@ -45,19 +45,19 @@ public class MasterKeyV2 extends MasterKeyV1 {
|
|||||||
byte[] siteNameBytes = siteName.getBytes( MP_charset );
|
byte[] siteNameBytes = siteName.getBytes( MP_charset );
|
||||||
byte[] siteNameLengthBytes = bytesForInt( siteNameBytes.length );
|
byte[] siteNameLengthBytes = bytesForInt( siteNameBytes.length );
|
||||||
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
||||||
byte[] siteContextBytes = siteContext == null? null: siteContext.getBytes( MP_charset );
|
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MP_charset );
|
||||||
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
||||||
logger.trc( "site scope: %s, context: %s", siteScope, siteContext == null? "<empty>": siteContext );
|
logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
|
||||||
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
|
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
|
||||||
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
||||||
siteContext == null? "(null)": siteContext );
|
siteContextBytes == null? "(null)": siteContext );
|
||||||
|
|
||||||
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MP_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MP_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
||||||
if (siteContextBytes != null)
|
if (siteContextBytes != null)
|
||||||
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
||||||
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
||||||
|
|
||||||
byte[] sitePasswordSeed = MP_mac.of( getMasterKey(), sitePasswordInfo );
|
byte[] sitePasswordSeed = MP_mac.of( getKey(), sitePasswordInfo );
|
||||||
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeed ) ) );
|
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeed ) ) );
|
||||||
|
|
||||||
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
||||||
|
@ -26,7 +26,7 @@ public class MasterKeyV3 extends MasterKeyV2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Version getAlgorithm() {
|
public Version getAlgorithmVersion() {
|
||||||
|
|
||||||
return Version.V3;
|
return Version.V3;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package com.lyndir.masterpassword;
|
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.ObjectUtils.*;
|
||||||
|
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import com.lyndir.lhunath.opal.system.util.NNSupplier;
|
import com.lyndir.lhunath.opal.system.util.*;
|
||||||
import com.lyndir.lhunath.opal.system.util.NSupplier;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -25,8 +25,9 @@ public class MPWTests {
|
|||||||
@XmlElement(name = "case")
|
@XmlElement(name = "case")
|
||||||
private List<Case> cases;
|
private List<Case> cases;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public List<Case> getCases() {
|
public List<Case> getCases() {
|
||||||
return cases;
|
return checkNotNull( cases );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Case getCase(String identifier) {
|
public Case getCase(String identifier) {
|
||||||
@ -45,6 +46,8 @@ public class MPWTests {
|
|||||||
@XmlAttribute
|
@XmlAttribute
|
||||||
private String parent;
|
private String parent;
|
||||||
@XmlElement
|
@XmlElement
|
||||||
|
private String algorithm;
|
||||||
|
@XmlElement
|
||||||
private String fullName;
|
private String fullName;
|
||||||
@XmlElement
|
@XmlElement
|
||||||
private String masterPassword;
|
private String masterPassword;
|
||||||
@ -65,76 +68,86 @@ public class MPWTests {
|
|||||||
|
|
||||||
private transient Case parentCase;
|
private transient Case parentCase;
|
||||||
|
|
||||||
public void setTests(MPWTests tests) {
|
public void initializeParentHierarchy(MPWTests tests) {
|
||||||
|
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parentCase = tests.getCase( parent );
|
parentCase = tests.getCase( parent );
|
||||||
fullName = ifNotNullElse( fullName, new NNSupplier<String>() {
|
parentCase.initializeParentHierarchy( tests );
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return parentCase.getFullName();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
masterPassword = ifNotNullElse( masterPassword, new NNSupplier<String>() {
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return new String( parentCase.getMasterPassword() );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
keyID = ifNotNullElse( keyID, new NNSupplier<String>() {
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return parentCase.getKeyID();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
siteName = ifNotNullElse( siteName, new NNSupplier<String>() {
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return parentCase.getSiteName();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
siteCounter = ifNotNullElse( siteCounter, new NNSupplier<Integer>() {
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public Integer get() {
|
|
||||||
return parentCase.getSiteCounter();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
siteType = ifNotNullElse( siteType, new NNSupplier<String>() {
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return parentCase.getSiteType().name();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
siteVariant = ifNotNullElse( siteVariant, new NNSupplier<String>() {
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return parentCase.getSiteVariant().name();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
siteContext = ifNotNullElseNullable( siteContext, new NSupplier<String>() {
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return parentCase.getSiteContext();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
result = ifNotNullElse( result, new NNSupplier<String>() {
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String get() {
|
|
||||||
return parentCase.getResult();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
algorithm = ifNotNullElse( algorithm, new NNSupplier<String>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return checkNotNull( parentCase.algorithm );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
fullName = ifNotNullElse( fullName, new NNSupplier<String>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return checkNotNull( parentCase.fullName );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
masterPassword = ifNotNullElse( masterPassword, new NNSupplier<String>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return checkNotNull( parentCase.masterPassword );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
keyID = ifNotNullElse( keyID, new NNSupplier<String>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return checkNotNull( parentCase.keyID );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
siteName = ifNotNullElse( siteName, new NNSupplier<String>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return checkNotNull( parentCase.siteName );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
siteCounter = ifNotNullElse( siteCounter, new NNSupplier<Integer>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Integer get() {
|
||||||
|
return checkNotNull( parentCase.siteCounter );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
siteType = ifNotNullElse( siteType, new NNSupplier<String>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return checkNotNull( parentCase.siteType );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
siteVariant = ifNotNullElse( siteVariant, new NNSupplier<String>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return checkNotNull( parentCase.siteVariant );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
siteContext = ifNotNullElse( siteContext, new NNSupplier<String>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return parentCase == null? "": checkNotNull( parentCase.siteContext );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
result = ifNotNullElse( result, new NNSupplier<String>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String get() {
|
||||||
|
return parentCase == null? "": checkNotNull( parentCase.result );
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
@ -144,40 +157,53 @@ public class MPWTests {
|
|||||||
return parentCase;
|
return parentCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public MasterKey.Version getAlgorithm() {
|
||||||
|
return MasterKey.Version.fromInt( ConversionUtils.toIntegerNN( algorithm ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public String getFullName() {
|
public String getFullName() {
|
||||||
return fullName;
|
return checkNotNull( fullName );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public char[] getMasterPassword() {
|
public char[] getMasterPassword() {
|
||||||
return masterPassword.toCharArray();
|
return checkNotNull( masterPassword ).toCharArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public String getKeyID() {
|
public String getKeyID() {
|
||||||
return keyID;
|
return checkNotNull( keyID );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public String getSiteName() {
|
public String getSiteName() {
|
||||||
return siteName;
|
return checkNotNull( siteName );
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSiteCounter() {
|
public int getSiteCounter() {
|
||||||
return siteCounter;
|
return ifNotNullElse( siteCounter, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public MPSiteType getSiteType() {
|
public MPSiteType getSiteType() {
|
||||||
return MPSiteType.forName( siteType );
|
return MPSiteType.forName( checkNotNull( siteType ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public MPSiteVariant getSiteVariant() {
|
public MPSiteVariant getSiteVariant() {
|
||||||
return MPSiteVariant.forName( siteVariant );
|
return MPSiteVariant.forName( checkNotNull( siteVariant ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public String getSiteContext() {
|
public String getSiteContext() {
|
||||||
return siteContext;
|
return checkNotNull( siteContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public String getResult() {
|
public String getResult() {
|
||||||
return result;
|
return checkNotNull( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -5,6 +5,7 @@ import static org.testng.Assert.*;
|
|||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
|
import com.lyndir.lhunath.opal.system.util.StringUtils;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.JAXBContext;
|
||||||
import org.testng.annotations.BeforeMethod;
|
import org.testng.annotations.BeforeMethod;
|
||||||
@ -26,7 +27,7 @@ public class MasterKeyTest {
|
|||||||
URL testCasesResource = Resources.getResource( "mpw_tests.xml" );
|
URL testCasesResource = Resources.getResource( "mpw_tests.xml" );
|
||||||
tests = (MPWTests) JAXBContext.newInstance( MPWTests.class ).createUnmarshaller().unmarshal( testCasesResource );
|
tests = (MPWTests) JAXBContext.newInstance( MPWTests.class ).createUnmarshaller().unmarshal( testCasesResource );
|
||||||
for (MPWTests.Case testCase : tests.getCases())
|
for (MPWTests.Case testCase : tests.getCases())
|
||||||
testCase.setTests( tests );
|
testCase.initializeParentHierarchy( tests );
|
||||||
defaultCase = tests.getCase( MPWTests.ID_DEFAULT );
|
defaultCase = tests.getCase( MPWTests.ID_DEFAULT );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,10 +36,15 @@ public class MasterKeyTest {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
for (MPWTests.Case testCase : tests.getCases()) {
|
for (MPWTests.Case testCase : tests.getCases()) {
|
||||||
MasterKey masterKey = MasterKey.create( testCase.getFullName(), testCase.getMasterPassword() );
|
if (testCase.getResult().isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
logger.inf( "Running test case: %s [testEncode]", testCase.getIdentifier() );
|
||||||
|
MasterKey masterKey = MasterKey.create( testCase.getAlgorithm(), testCase.getFullName(), testCase.getMasterPassword() );
|
||||||
assertEquals(
|
assertEquals(
|
||||||
masterKey.encode( testCase.getSiteName(), testCase.getSiteType(), testCase.getSiteCounter(), testCase.getSiteVariant(),
|
masterKey.encode( testCase.getSiteName(), testCase.getSiteType(), testCase.getSiteCounter(), testCase.getSiteVariant(),
|
||||||
testCase.getSiteContext() ), testCase.getResult(), "Failed test case: " + testCase );
|
testCase.getSiteContext() ), testCase.getResult(), "Failed test case: " + testCase );
|
||||||
|
logger.inf( "passed!" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,8 +61,13 @@ public class MasterKeyTest {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
for (MPWTests.Case testCase : tests.getCases()) {
|
for (MPWTests.Case testCase : tests.getCases()) {
|
||||||
|
if (testCase.getResult().isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
logger.inf( "Running test case: %s [testGetKeyID]", testCase.getIdentifier() );
|
||||||
MasterKey masterKey = MasterKey.create( testCase.getFullName(), testCase.getMasterPassword() );
|
MasterKey masterKey = MasterKey.create( testCase.getFullName(), testCase.getMasterPassword() );
|
||||||
assertEquals( CodeUtils.encodeHex( masterKey.getKeyID() ), testCase.getKeyID(), "Failed test case: " + testCase );
|
assertEquals( CodeUtils.encodeHex( masterKey.getKeyID() ), testCase.getKeyID(), "Failed test case: " + testCase );
|
||||||
|
logger.inf( "passed!" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<tests>
|
<tests>
|
||||||
|
<!-- Default values for all parameters. -->
|
||||||
<case id="default">
|
<case id="default">
|
||||||
|
<algorithm><!-- current --></algorithm>
|
||||||
<fullName>Robert Lee Mitchell</fullName>
|
<fullName>Robert Lee Mitchell</fullName>
|
||||||
<masterPassword>banana colored duckling</masterPassword>
|
<masterPassword>banana colored duckling</masterPassword>
|
||||||
<keyID>98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302</keyID>
|
<keyID>98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302</keyID>
|
||||||
@ -7,67 +9,271 @@
|
|||||||
<siteCounter>1</siteCounter>
|
<siteCounter>1</siteCounter>
|
||||||
<siteType>GeneratedLong</siteType>
|
<siteType>GeneratedLong</siteType>
|
||||||
<siteVariant>Password</siteVariant>
|
<siteVariant>Password</siteVariant>
|
||||||
|
<result><!-- abstract --></result>
|
||||||
|
</case>
|
||||||
|
|
||||||
|
<!-- Algorithm 3 -->
|
||||||
|
<case id="v3" parent="default">
|
||||||
|
<algorithm>3</algorithm>
|
||||||
<result>Jejr5[RepuSosp</result>
|
<result>Jejr5[RepuSosp</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="mb_fullName" parent="default">
|
<case id="v3_mb_fullName" parent="v3">
|
||||||
<fullName>⛄</fullName>
|
<fullName>⛄</fullName>
|
||||||
<keyID>1717AA1F9BF5BA56CD0965CDA3D78E6D2E6A1EA8C067A8EA621F3DDAD4A87EB8</keyID>
|
<keyID>1717AA1F9BF5BA56CD0965CDA3D78E6D2E6A1EA8C067A8EA621F3DDAD4A87EB8</keyID>
|
||||||
<result>NopaDajh8=Fene</result>
|
<result>NopaDajh8=Fene</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="mb_masterPassword" parent="default">
|
<case id="v3_mb_masterPassword" parent="v3">
|
||||||
<masterPassword>⛄</masterPassword>
|
<masterPassword>⛄</masterPassword>
|
||||||
<keyID>351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08</keyID>
|
<keyID>351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08</keyID>
|
||||||
<result>QesuHirv5-Xepl</result>
|
<result>QesuHirv5-Xepl</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="mb_siteName" parent="default">
|
<case id="v3_mb_siteName" parent="v3">
|
||||||
<siteName>⛄</siteName>
|
<siteName>⛄</siteName>
|
||||||
<result>LiheCuwhSerz6)</result>
|
<result>LiheCuwhSerz6)</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="loginName" parent="default">
|
<case id="v3_loginName" parent="v3">
|
||||||
<siteVariant>Login</siteVariant>
|
<siteVariant>Login</siteVariant>
|
||||||
<siteType>GeneratedName</siteType>
|
<siteType>GeneratedName</siteType>
|
||||||
<result>wohzaqage</result>
|
<result>wohzaqage</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="securityAnswer" parent="default">
|
<case id="v3_securityAnswer" parent="v3">
|
||||||
<siteVariant>Answer</siteVariant>
|
<siteVariant>Answer</siteVariant>
|
||||||
<siteType>GeneratedPhrase</siteType>
|
<siteType>GeneratedPhrase</siteType>
|
||||||
<result>xin diyjiqoja hubu</result>
|
<result>xin diyjiqoja hubu</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="securityAnswer_context" parent="securityAnswer">
|
<case id="v3_securityAnswer_context" parent="v3_securityAnswer">
|
||||||
<siteContext>question</siteContext>
|
<siteContext>question</siteContext>
|
||||||
<result>xogx tem cegyiva jab</result>
|
<result>xogx tem cegyiva jab</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="type_maximum" parent="default">
|
<case id="v3_type_maximum" parent="v3">
|
||||||
<siteType>GeneratedMaximum</siteType>
|
<siteType>GeneratedMaximum</siteType>
|
||||||
<result>W6@692^B1#&@gVdSdLZ@</result>
|
<result>W6@692^B1#&@gVdSdLZ@</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="type_medium" parent="default">
|
<case id="v3_type_medium" parent="v3">
|
||||||
<siteType>GeneratedMedium</siteType>
|
<siteType>GeneratedMedium</siteType>
|
||||||
<result>Jej2$Quv</result>
|
<result>Jej2$Quv</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="type_basic" parent="default">
|
<case id="v3_type_basic" parent="v3">
|
||||||
<siteType>GeneratedBasic</siteType>
|
<siteType>GeneratedBasic</siteType>
|
||||||
<result>WAo2xIg6</result>
|
<result>WAo2xIg6</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="type_short" parent="default">
|
<case id="v3_type_short" parent="v3">
|
||||||
<siteType>GeneratedShort</siteType>
|
<siteType>GeneratedShort</siteType>
|
||||||
<result>Jej2</result>
|
<result>Jej2</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="type_pin" parent="default">
|
<case id="v3_type_pin" parent="v3">
|
||||||
<siteType>GeneratedPIN</siteType>
|
<siteType>GeneratedPIN</siteType>
|
||||||
<result>7662</result>
|
<result>7662</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="type_name" parent="default">
|
<case id="v3_type_name" parent="v3">
|
||||||
<siteType>GeneratedName</siteType>
|
<siteType>GeneratedName</siteType>
|
||||||
<result>jejraquvo</result>
|
<result>jejraquvo</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="type_phrase" parent="default">
|
<case id="v3_type_phrase" parent="v3">
|
||||||
<siteType>GeneratedPhrase</siteType>
|
<siteType>GeneratedPhrase</siteType>
|
||||||
<result>jejr quv cabsibu tam</result>
|
<result>jejr quv cabsibu tam</result>
|
||||||
</case>
|
</case>
|
||||||
<case id="counter_ceiling" parent="default">
|
<case id="v3_counter_ceiling" parent="v3">
|
||||||
<siteCounter>4294967295</siteCounter>
|
<siteCounter>4294967295</siteCounter>
|
||||||
<result>XambHoqo6[Peni</result>
|
<result>XambHoqo6[Peni</result>
|
||||||
</case>
|
</case>
|
||||||
|
|
||||||
|
<!-- Algorithm 2 -->
|
||||||
|
<case id="v2" parent="default">
|
||||||
|
<algorithm>2</algorithm>
|
||||||
|
<result>Jejr5[RepuSosp</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_mb_fullName" parent="v2">
|
||||||
|
<fullName>⛄</fullName>
|
||||||
|
<keyID>1717AA1F9BF5BA56CD0965CDA3D78E6D2E6A1EA8C067A8EA621F3DDAD4A87EB8</keyID>
|
||||||
|
<result>WaqoGuho2[Xaxw</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_mb_masterPassword" parent="v2">
|
||||||
|
<masterPassword>⛄</masterPassword>
|
||||||
|
<keyID>351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08</keyID>
|
||||||
|
<result>QesuHirv5-Xepl</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_mb_siteName" parent="v2">
|
||||||
|
<siteName>⛄</siteName>
|
||||||
|
<result>LiheCuwhSerz6)</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_loginName" parent="v2">
|
||||||
|
<siteVariant>Login</siteVariant>
|
||||||
|
<siteType>GeneratedName</siteType>
|
||||||
|
<result>wohzaqage</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_securityAnswer" parent="v2">
|
||||||
|
<siteVariant>Answer</siteVariant>
|
||||||
|
<siteType>GeneratedPhrase</siteType>
|
||||||
|
<result>xin diyjiqoja hubu</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_securityAnswer_context" parent="v2_securityAnswer">
|
||||||
|
<siteContext>question</siteContext>
|
||||||
|
<result>xogx tem cegyiva jab</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_type_maximum" parent="v2">
|
||||||
|
<siteType>GeneratedMaximum</siteType>
|
||||||
|
<result>W6@692^B1#&@gVdSdLZ@</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_type_medium" parent="v2">
|
||||||
|
<siteType>GeneratedMedium</siteType>
|
||||||
|
<result>Jej2$Quv</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_type_basic" parent="v2">
|
||||||
|
<siteType>GeneratedBasic</siteType>
|
||||||
|
<result>WAo2xIg6</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_type_short" parent="v2">
|
||||||
|
<siteType>GeneratedShort</siteType>
|
||||||
|
<result>Jej2</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_type_pin" parent="v2">
|
||||||
|
<siteType>GeneratedPIN</siteType>
|
||||||
|
<result>7662</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_type_name" parent="v2">
|
||||||
|
<siteType>GeneratedName</siteType>
|
||||||
|
<result>jejraquvo</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_type_phrase" parent="v2">
|
||||||
|
<siteType>GeneratedPhrase</siteType>
|
||||||
|
<result>jejr quv cabsibu tam</result>
|
||||||
|
</case>
|
||||||
|
<case id="v2_counter_ceiling" parent="v2">
|
||||||
|
<siteCounter>4294967295</siteCounter>
|
||||||
|
<result>XambHoqo6[Peni</result>
|
||||||
|
</case>
|
||||||
|
|
||||||
|
<!-- Algorithm 1 -->
|
||||||
|
<case id="v1" parent="default">
|
||||||
|
<algorithm>1</algorithm>
|
||||||
|
<result>Jejr5[RepuSosp</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_mb_fullName" parent="v1">
|
||||||
|
<fullName>⛄</fullName>
|
||||||
|
<keyID>1717AA1F9BF5BA56CD0965CDA3D78E6D2E6A1EA8C067A8EA621F3DDAD4A87EB8</keyID>
|
||||||
|
<result>WaqoGuho2[Xaxw</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_mb_masterPassword" parent="v1">
|
||||||
|
<masterPassword>⛄</masterPassword>
|
||||||
|
<keyID>351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08</keyID>
|
||||||
|
<result>QesuHirv5-Xepl</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_mb_siteName" parent="v1">
|
||||||
|
<siteName>⛄</siteName>
|
||||||
|
<result>WawiYarp2@Kodh</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_loginName" parent="v1">
|
||||||
|
<siteVariant>Login</siteVariant>
|
||||||
|
<siteType>GeneratedName</siteType>
|
||||||
|
<result>wohzaqage</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_securityAnswer" parent="v1">
|
||||||
|
<siteVariant>Answer</siteVariant>
|
||||||
|
<siteType>GeneratedPhrase</siteType>
|
||||||
|
<result>xin diyjiqoja hubu</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_securityAnswer_context" parent="v1_securityAnswer">
|
||||||
|
<siteContext>question</siteContext>
|
||||||
|
<result>xogx tem cegyiva jab</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_type_maximum" parent="v1">
|
||||||
|
<siteType>GeneratedMaximum</siteType>
|
||||||
|
<result>W6@692^B1#&@gVdSdLZ@</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_type_medium" parent="v1">
|
||||||
|
<siteType>GeneratedMedium</siteType>
|
||||||
|
<result>Jej2$Quv</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_type_basic" parent="v1">
|
||||||
|
<siteType>GeneratedBasic</siteType>
|
||||||
|
<result>WAo2xIg6</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_type_short" parent="v1">
|
||||||
|
<siteType>GeneratedShort</siteType>
|
||||||
|
<result>Jej2</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_type_pin" parent="v1">
|
||||||
|
<siteType>GeneratedPIN</siteType>
|
||||||
|
<result>7662</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_type_name" parent="v1">
|
||||||
|
<siteType>GeneratedName</siteType>
|
||||||
|
<result>jejraquvo</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_type_phrase" parent="v1">
|
||||||
|
<siteType>GeneratedPhrase</siteType>
|
||||||
|
<result>jejr quv cabsibu tam</result>
|
||||||
|
</case>
|
||||||
|
<case id="v1_counter_ceiling" parent="v1">
|
||||||
|
<siteCounter>4294967295</siteCounter>
|
||||||
|
<result>XambHoqo6[Peni</result>
|
||||||
|
</case>
|
||||||
|
|
||||||
|
<!-- Algorithm 0 -->
|
||||||
|
<case id="v0" parent="default">
|
||||||
|
<algorithm>0</algorithm>
|
||||||
|
<result>Feji5@ReduWosh</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_mb_fullName" parent="v0">
|
||||||
|
<fullName>⛄</fullName>
|
||||||
|
<keyID>1717AA1F9BF5BA56CD0965CDA3D78E6D2E6A1EA8C067A8EA621F3DDAD4A87EB8</keyID>
|
||||||
|
<result>HajrYudo7@Mamh</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_mb_masterPassword" parent="v0">
|
||||||
|
<masterPassword>⛄</masterPassword>
|
||||||
|
<keyID>351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08</keyID>
|
||||||
|
<result>MewmDini0]Meho</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_mb_siteName" parent="v0">
|
||||||
|
<siteName>⛄</siteName>
|
||||||
|
<result>HahiVana2@Nole</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_loginName" parent="v0">
|
||||||
|
<siteVariant>Login</siteVariant>
|
||||||
|
<siteType>GeneratedName</siteType>
|
||||||
|
<result>lozwajave</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_securityAnswer" parent="v0">
|
||||||
|
<siteVariant>Answer</siteVariant>
|
||||||
|
<siteType>GeneratedPhrase</siteType>
|
||||||
|
<result>miy lirfijoja dubu</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_securityAnswer_context" parent="v0_securityAnswer">
|
||||||
|
<siteContext>question</siteContext>
|
||||||
|
<result>movm bex gevrica jaf</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_type_maximum" parent="v0">
|
||||||
|
<siteType>GeneratedMaximum</siteType>
|
||||||
|
<result>w1!3bA3icmRAc)SS@lwl</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_type_medium" parent="v0">
|
||||||
|
<siteType>GeneratedMedium</siteType>
|
||||||
|
<result>Fej7]Jug</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_type_basic" parent="v0">
|
||||||
|
<siteType>GeneratedBasic</siteType>
|
||||||
|
<result>wvH7irC1</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_type_short" parent="v0">
|
||||||
|
<siteType>GeneratedShort</siteType>
|
||||||
|
<result>Fej7</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_type_pin" parent="v0">
|
||||||
|
<siteType>GeneratedPIN</siteType>
|
||||||
|
<result>2117</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_type_name" parent="v0">
|
||||||
|
<siteType>GeneratedName</siteType>
|
||||||
|
<result>fejrajugo</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_type_phrase" parent="v0">
|
||||||
|
<siteType>GeneratedPhrase</siteType>
|
||||||
|
<result>fejr jug gabsibu bax</result>
|
||||||
|
</case>
|
||||||
|
<case id="v0_counter_ceiling" parent="v0">
|
||||||
|
<siteCounter>4294967295</siteCounter>
|
||||||
|
<result>QateDojh1@Hecn</result>
|
||||||
|
</case>
|
||||||
</tests>
|
</tests>
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.lyndir.masterpassword"
|
package="com.lyndir.masterpassword"
|
||||||
android:versionCode="1"
|
android:versionCode="1"
|
||||||
android:versionName="GIT-SNAPSHOT">
|
android:versionName="2.2">
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="19"
|
android:minSdkVersion="19"
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
# File used by Eclipse to determine the target system
|
|
||||||
# Project target.
|
|
||||||
target=android-16
|
|
@ -13,7 +13,6 @@
|
|||||||
<name>Master Password Android</name>
|
<name>Master Password Android</name>
|
||||||
<description>An Android application to the Master Password algorithm</description>
|
<description>An Android application to the Master Password algorithm</description>
|
||||||
|
|
||||||
<groupId>com.lyndir.masterpassword</groupId>
|
|
||||||
<artifactId>masterpassword-android</artifactId>
|
<artifactId>masterpassword-android</artifactId>
|
||||||
<packaging>apk</packaging>
|
<packaging>apk</packaging>
|
||||||
|
|
||||||
@ -30,7 +29,7 @@
|
|||||||
<skip>false</skip>
|
<skip>false</skip>
|
||||||
</zipalign>
|
</zipalign>
|
||||||
<sdk>
|
<sdk>
|
||||||
<platform>19</platform>
|
<platform>21</platform>
|
||||||
</sdk>
|
</sdk>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
@ -39,9 +38,32 @@
|
|||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>sign</id>
|
<id>release</id>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
||||||
|
<artifactId>android-maven-plugin</artifactId>
|
||||||
|
|
||||||
|
<configuration>
|
||||||
|
<sign>
|
||||||
|
<debug>false</debug>
|
||||||
|
</sign>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>manifest-update</id>
|
||||||
|
<phase>process-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>manifest-update</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<manifestVersionCodeUpdateFromVersion>true</manifestVersionCodeUpdateFromVersion>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jarsigner-plugin</artifactId>
|
<artifactId>maven-jarsigner-plugin</artifactId>
|
||||||
@ -54,14 +76,14 @@
|
|||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
<inherited>true</inherited>
|
<inherited>true</inherited>
|
||||||
<configuration>
|
<configuration>
|
||||||
<archiveDirectory></archiveDirectory>
|
<archiveDirectory />
|
||||||
<includes>
|
<includes>
|
||||||
<include>target/*.apk</include>
|
<include>target/*.apk</include>
|
||||||
</includes>
|
</includes>
|
||||||
<keystore>release.jks</keystore>
|
<keystore>release.jks</keystore>
|
||||||
<storepass>${env.PASSWORD}</storepass>
|
<storepass>${env.PASSWORD}</storepass>
|
||||||
<keypass>${env.PASSWORD}</keypass>
|
<keypass>${env.PASSWORD}</keypass>
|
||||||
<alias>android</alias>
|
<alias>masterpassword-android</alias>
|
||||||
<arguments>
|
<arguments>
|
||||||
<argument>-sigalg</argument><argument>MD5withRSA</argument>
|
<argument>-sigalg</argument><argument>MD5withRSA</argument>
|
||||||
<argument>-digestalg</argument><argument>SHA1</argument>
|
<argument>-digestalg</argument><argument>SHA1</argument>
|
||||||
@ -70,16 +92,6 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
|
||||||
<artifactId>android-maven-plugin</artifactId>
|
|
||||||
<inherited>true</inherited>
|
|
||||||
<configuration>
|
|
||||||
<sign>
|
|
||||||
<debug>false</debug>
|
|
||||||
</sign>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
1
MasterPassword/Java/masterpassword-android/release.jks
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
/Users/lhunath/SpiderOak Hive/secret/release-com.lyndir.masterpassword.jks
|
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 244 KiB After Width: | Height: | Size: 292 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 49 KiB |
@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<size
|
|
||||||
android:width="20dp"
|
|
||||||
android:height="20dp" />
|
|
||||||
</shape>
|
|
Before Width: | Height: | Size: 3.6 KiB |
@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@drawable/background">
|
|
||||||
|
|
||||||
<HorizontalScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/users"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:divider="@drawable/divider20"
|
|
||||||
android:showDividers="middle" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp" />
|
|
||||||
</LinearLayout>
|
|
||||||
</HorizontalScrollView>
|
|
||||||
</FrameLayout>
|
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/userName"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:drawableTop="@drawable/avatar0"
|
|
||||||
android:drawablePadding="8dp"
|
|
||||||
android:text="Robert Lee Mitchell" />
|
|
@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Master Password</string>
|
<string name="app_name">Master Password</string>
|
||||||
<string name="avatar">User Avatar</string>
|
|
||||||
<string name="remember">Remember</string>
|
<string name="remember">Remember</string>
|
||||||
<string name="forgetOnClose">Forget on close</string>
|
<string name="forgetOnClose">Forget on close</string>
|
||||||
<string name="maskPassword">Hide password</string>
|
<string name="maskPassword">Hide password</string>
|
||||||
|
@ -205,7 +205,7 @@ public class EmergencyActivity extends Activity {
|
|||||||
final MasterKey.Version version = (MasterKey.Version) siteVersionField.getSelectedItem();
|
final MasterKey.Version version = (MasterKey.Version) siteVersionField.getSelectedItem();
|
||||||
try {
|
try {
|
||||||
if (fullName.hashCode() == hc_userName && Arrays.hashCode( masterPassword ) == hc_masterPassword &&
|
if (fullName.hashCode() == hc_userName && Arrays.hashCode( masterPassword ) == hc_masterPassword &&
|
||||||
masterKeyFuture != null && masterKeyFuture.get().getAlgorithm() == version)
|
masterKeyFuture != null && masterKeyFuture.get().getAlgorithmVersion() == version)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (InterruptedException | ExecutionException e) {
|
catch (InterruptedException | ExecutionException e) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.lyndir.masterpassword;
|
package com.lyndir.masterpassword;
|
||||||
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
package com.lyndir.masterpassword;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.InjectView;
|
|
||||||
import com.lyndir.masterpassword.model.Avatar;
|
|
||||||
import com.lyndir.masterpassword.model.User;
|
|
||||||
import com.lyndir.masterpassword.view.AvatarView;
|
|
||||||
|
|
||||||
|
|
||||||
public class UsersActivity extends Activity {
|
|
||||||
|
|
||||||
@InjectView(R.id.users)
|
|
||||||
LinearLayout users;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate( savedInstanceState );
|
|
||||||
setContentView( R.layout.activity_users );
|
|
||||||
ButterKnife.inject( this );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
|
|
||||||
AvatarView avatarView = new AvatarView( this );
|
|
||||||
avatarView.setUser( new User( "Maarten Billemont", Avatar.EIGHT ) );
|
|
||||||
users.addView( avatarView );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
package com.lyndir.masterpassword.model;
|
|
||||||
|
|
||||||
import com.lyndir.masterpassword.R;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lhunath, 2014-08-20
|
|
||||||
*/
|
|
||||||
public enum Avatar {
|
|
||||||
ZERO( R.drawable.avatar0 ),
|
|
||||||
ONE( R.drawable.avatar1 ),
|
|
||||||
TWO( R.drawable.avatar2 ),
|
|
||||||
THREE( R.drawable.avatar3 ),
|
|
||||||
FOUR( R.drawable.avatar4 ),
|
|
||||||
FIVE( R.drawable.avatar5 ),
|
|
||||||
SIX( R.drawable.avatar6 ),
|
|
||||||
SEVEN( R.drawable.avatar7 ),
|
|
||||||
EIGHT( R.drawable.avatar8 ),
|
|
||||||
NINE( R.drawable.avatar9 ),
|
|
||||||
TEN( R.drawable.avatar10 ),
|
|
||||||
ELEVEN( R.drawable.avatar11 ),
|
|
||||||
TWELVE( R.drawable.avatar12 ),
|
|
||||||
THIRTEEN( R.drawable.avatar13 ),
|
|
||||||
FOURTEEN( R.drawable.avatar14 ),
|
|
||||||
FIFTEEN( R.drawable.avatar15 ),
|
|
||||||
SIXTEEN( R.drawable.avatar16 ),
|
|
||||||
SEVENTEEN( R.drawable.avatar17 ),
|
|
||||||
EIGHTEEN( R.drawable.avatar18 );
|
|
||||||
|
|
||||||
private final int imageResource;
|
|
||||||
|
|
||||||
Avatar(final int imageResource) {
|
|
||||||
this.imageResource = imageResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getImageResource() {
|
|
||||||
return imageResource;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package com.lyndir.masterpassword.model;
|
|
||||||
|
|
||||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lhunath, 2014-08-20
|
|
||||||
*/
|
|
||||||
public class User {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
private Avatar avatar;
|
|
||||||
|
|
||||||
public User(final String name, final Avatar avatar) {
|
|
||||||
this.name = name;
|
|
||||||
this.avatar = avatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Avatar getAvatar() {
|
|
||||||
return avatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(final Object obj) {
|
|
||||||
return this == obj || obj instanceof User && name.equals( ((User) obj).name );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return name.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return strf( "{User: %s}", name );
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package com.lyndir.masterpassword.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import com.lyndir.masterpassword.R;
|
|
||||||
import com.lyndir.masterpassword.model.User;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lhunath, 2014-08-20
|
|
||||||
*/
|
|
||||||
public class AvatarView extends FrameLayout {
|
|
||||||
|
|
||||||
private final TextView userName;
|
|
||||||
|
|
||||||
public AvatarView(final Context context) {
|
|
||||||
super( context );
|
|
||||||
|
|
||||||
addView( userName = (TextView) LayoutInflater.from( context ).inflate( R.layout.view_user_avatar, this, false ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUser(User user) {
|
|
||||||
userName.setText( user.getName() );
|
|
||||||
userName.setCompoundDrawables( null, getResources().getDrawable( user.getAvatar().getImageResource() ), null, null );
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,7 +13,6 @@
|
|||||||
<name>Master Password CLI</name>
|
<name>Master Password CLI</name>
|
||||||
<description>A CLI interface to the Master Password algorithm</description>
|
<description>A CLI interface to the Master Password algorithm</description>
|
||||||
|
|
||||||
<groupId>com.lyndir.masterpassword</groupId>
|
|
||||||
<artifactId>masterpassword-cli</artifactId>
|
<artifactId>masterpassword-cli</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
@ -37,7 +36,7 @@
|
|||||||
<phase>prepare-package</phase>
|
<phase>prepare-package</phase>
|
||||||
<configuration>
|
<configuration>
|
||||||
<target>
|
<target>
|
||||||
<chmod file="${project.build.directory}/install" perm="755"/>
|
<chmod file="${project.build.directory}/install" perm="755" />
|
||||||
</target>
|
</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
<goals>
|
<goals>
|
||||||
|
@ -45,7 +45,7 @@ public class CLI {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
// Read information from the environment.
|
// Read information from the environment.
|
||||||
char[] masterPassword = null;
|
char[] masterPassword;
|
||||||
String siteName = null, context = null;
|
String siteName = null, context = null;
|
||||||
String userName = System.getenv( ENV_USERNAME );
|
String userName = System.getenv( ENV_USERNAME );
|
||||||
String siteTypeName = ifNotNullElse( System.getenv( ENV_SITETYPE ), "" );
|
String siteTypeName = ifNotNullElse( System.getenv( ENV_SITETYPE ), "" );
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
<name>Master Password GUI</name>
|
<name>Master Password GUI</name>
|
||||||
<description>A GUI interface to the Master Password algorithm</description>
|
<description>A GUI interface to the Master Password algorithm</description>
|
||||||
|
|
||||||
<groupId>com.lyndir.masterpassword</groupId>
|
|
||||||
<artifactId>masterpassword-gui</artifactId>
|
<artifactId>masterpassword-gui</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
@ -67,6 +66,67 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>release</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
|
||||||
|
<artifactId>android-maven-plugin</artifactId>
|
||||||
|
|
||||||
|
<configuration>
|
||||||
|
<sign>
|
||||||
|
<debug>false</debug>
|
||||||
|
</sign>
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>manifest-update</id>
|
||||||
|
<phase>process-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>manifest-update</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<manifestVersionCodeUpdateFromVersion>true</manifestVersionCodeUpdateFromVersion>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jarsigner-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>signing</id>
|
||||||
|
<goals>
|
||||||
|
<goal>sign</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>package</phase>
|
||||||
|
<inherited>true</inherited>
|
||||||
|
<configuration>
|
||||||
|
<archiveDirectory />
|
||||||
|
<includes>
|
||||||
|
<include>target/*.jar</include>
|
||||||
|
</includes>
|
||||||
|
<keystore>release.jks</keystore>
|
||||||
|
<storepass>${env.PASSWORD}</storepass>
|
||||||
|
<keypass>${env.PASSWORD}</keypass>
|
||||||
|
<alias>masterpassword-desktop</alias>
|
||||||
|
<arguments>
|
||||||
|
<argument>-sigalg</argument><argument>MD5withRSA</argument>
|
||||||
|
<argument>-digestalg</argument><argument>SHA1</argument>
|
||||||
|
</arguments>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
<!-- DEPENDENCY MANAGEMENT -->
|
<!-- DEPENDENCY MANAGEMENT -->
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
1
MasterPassword/Java/masterpassword-gui/release.jks
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
/Users/lhunath/SpiderOak Hive/secret/release-com.lyndir.masterpassword.jks
|
@ -21,8 +21,7 @@ import com.google.common.base.Charsets;
|
|||||||
import com.google.common.io.*;
|
import com.google.common.io.*;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import com.lyndir.lhunath.opal.system.util.TypeUtils;
|
import com.lyndir.lhunath.opal.system.util.TypeUtils;
|
||||||
import com.lyndir.masterpassword.MasterKey;
|
|
||||||
import com.lyndir.masterpassword.model.IncorrectMasterPasswordException;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -41,7 +40,7 @@ public class GUI implements UnlockFrame.SignInCallback {
|
|||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
private static final Logger logger = Logger.get( GUI.class );
|
private static final Logger logger = Logger.get( GUI.class );
|
||||||
|
|
||||||
private UnlockFrame unlockFrame = new UnlockFrame( this );
|
private final UnlockFrame unlockFrame = new UnlockFrame( this );
|
||||||
private PasswordFrame passwordFrame;
|
private PasswordFrame passwordFrame;
|
||||||
|
|
||||||
public static void main(final String[] args)
|
public static void main(final String[] args)
|
||||||
@ -50,7 +49,13 @@ public class GUI implements UnlockFrame.SignInCallback {
|
|||||||
if (Config.get().checkForUpdates())
|
if (Config.get().checkForUpdates())
|
||||||
checkUpdate();
|
checkUpdate();
|
||||||
|
|
||||||
TypeUtils.<GUI>newInstance( AppleGUI.class ).or( new GUI() ).open();
|
try {
|
||||||
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
|
}
|
||||||
|
catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeUtils.<GUI>newInstance( "com.lyndir.masterpassword.gui.platform.mac.AppleGUI" ).or( new GUI() ).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkUpdate() {
|
private static void checkUpdate() {
|
||||||
@ -82,7 +87,7 @@ public class GUI implements UnlockFrame.SignInCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void open() {
|
protected void open() {
|
||||||
SwingUtilities.invokeLater( new Runnable() {
|
SwingUtilities.invokeLater( new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.lyndir.masterpassword.gui;
|
package com.lyndir.masterpassword.gui;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.*;
|
import com.google.common.collect.*;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import com.lyndir.masterpassword.model.MPUser;
|
import com.lyndir.masterpassword.model.MPUser;
|
||||||
@ -12,6 +13,7 @@ import javax.annotation.Nullable;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
|
import javax.swing.plaf.metal.MetalComboBoxEditor;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,6 +52,15 @@ public class ModelAuthenticationPanel extends AuthenticationPanel implements Ite
|
|||||||
userField.setFont( Res.valueFont().deriveFont( 12f ) );
|
userField.setFont( Res.valueFont().deriveFont( 12f ) );
|
||||||
userField.addItemListener( this );
|
userField.addItemListener( this );
|
||||||
userField.addActionListener( this );
|
userField.addActionListener( this );
|
||||||
|
userField.setEditor(new MetalComboBoxEditor() {
|
||||||
|
@Override
|
||||||
|
protected JTextField createEditorComponent() {
|
||||||
|
JTextField editorComponents = Components.textField();
|
||||||
|
editorComponents.setForeground(Color.red);
|
||||||
|
return editorComponents;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
add( userField );
|
add( userField );
|
||||||
add( Components.stud() );
|
add( Components.stud() );
|
||||||
|
|
||||||
@ -137,8 +148,8 @@ public class ModelAuthenticationPanel extends AuthenticationPanel implements Ite
|
|||||||
return FluentIterable.from( MPUserFileManager.get().getUsers() ).transform( new Function<MPUser, ModelUser>() {
|
return FluentIterable.from( MPUserFileManager.get().getUsers() ).transform( new Function<MPUser, ModelUser>() {
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public ModelUser apply(final MPUser model) {
|
public ModelUser apply(@Nullable final MPUser model) {
|
||||||
return new ModelUser( model );
|
return new ModelUser( Preconditions.checkNotNull( model ) );
|
||||||
}
|
}
|
||||||
} ).toArray( ModelUser.class );
|
} ).toArray( ModelUser.class );
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public class ModelUser extends User {
|
|||||||
|
|
||||||
public void authenticate(final char[] masterPassword)
|
public void authenticate(final char[] masterPassword)
|
||||||
throws IncorrectMasterPasswordException {
|
throws IncorrectMasterPasswordException {
|
||||||
model.authenticate( masterPassword );
|
putKey( model.authenticate( masterPassword ) );
|
||||||
this.masterPassword = masterPassword;
|
this.masterPassword = masterPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +81,7 @@ public class ModelUser extends User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean keySaved() {
|
public boolean keySaved() {
|
||||||
|
// TODO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,11 +149,12 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
// Password
|
// Password
|
||||||
passwordField = new JPasswordField();
|
passwordField = Components.passwordField();
|
||||||
passwordField.setAlignmentX( Component.CENTER_ALIGNMENT );
|
passwordField.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
passwordField.setEditable( false );
|
passwordField.setHorizontalAlignment(JTextField.CENTER);
|
||||||
passwordField.setHorizontalAlignment( JTextField.CENTER );
|
passwordField.putClientProperty("JPasswordField.cutCopyAllowed", true);
|
||||||
passwordField.putClientProperty( "JPasswordField.cutCopyAllowed", true );
|
passwordField.setEditable(false);
|
||||||
|
passwordField.setBackground(null);
|
||||||
passwordField.setBorder( null );
|
passwordField.setBorder( null );
|
||||||
passwordEchoChar = passwordField.getEchoChar();
|
passwordEchoChar = passwordField.getEchoChar();
|
||||||
passwordEchoFont = passwordField.getFont().deriveFont( 40f );
|
passwordEchoFont = passwordField.getFont().deriveFont( 40f );
|
||||||
|