Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b08149ca6 | ||
|
|
58afc19c26 | ||
|
|
b3109187e9 | ||
|
|
a6e7a749bf | ||
|
|
ca5d83d40c | ||
|
|
285813324f | ||
|
|
d4b772b467 | ||
|
|
f392ad4053 | ||
|
|
35990f3bdd | ||
|
|
3932857c21 | ||
|
|
6f771a972b | ||
|
|
806a07135a | ||
|
|
f6b2287778 | ||
|
|
f4e90bb839 | ||
|
|
21630e919b | ||
|
|
ae74ab6906 | ||
|
|
caf361cd10 | ||
|
|
aeedc1946e | ||
|
|
93ae31f679 | ||
|
|
d5ff215da2 | ||
|
|
b34f7377da | ||
|
|
0c2e182039 | ||
|
|
438daf27ee | ||
|
|
aa6634970a | ||
|
|
9052416786 | ||
|
|
9d19eaf667 | ||
|
|
7ae9afa63a | ||
|
|
3d856b3773 | ||
|
|
7617b2382a | ||
|
|
a03dcf6859 | ||
|
|
57769ba199 | ||
|
|
6304b3a619 | ||
|
|
d1649f3c33 | ||
|
|
80f507b4cc | ||
|
|
f8a665db65 | ||
|
|
b15f2a8a26 | ||
|
|
e9094097a2 | ||
|
|
bea6ac5e68 | ||
|
|
778533ac7f | ||
|
|
83fcde5bd0 | ||
|
|
c9ec5874d3 | ||
|
|
4ce5fd25bc | ||
|
|
1ed28ebc9b | ||
|
|
c03199f7e5 | ||
|
|
9f10bcdec4 | ||
|
|
82c96ddfe3 | ||
|
|
c0fea076b9 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -28,9 +28,6 @@ Press/MasterPassword_PressKit/MasterPassword_pressrelease_*.pdf
|
||||
/sendipa/*
|
||||
!/sendipa/sendipa.conf
|
||||
|
||||
# Java
|
||||
MasterPassword/Java/**/target
|
||||
|
||||
# C
|
||||
MasterPassword/C/VERSION
|
||||
MasterPassword/C/*.o
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -18,4 +18,4 @@
|
||||
url = git://github.com/jonmarimba/jrswizzle.git
|
||||
[submodule "Site/mpw-js/js/mpw-js"]
|
||||
path = Site/mpw-js/js/mpw-js
|
||||
url = https://github.com/Lyndir/mpw-js.git
|
||||
url = https://github.com/tmthrgd/mpw-js.git
|
||||
|
||||
2
External/Pearl
vendored
2
External/Pearl
vendored
Submodule External/Pearl updated: 8c646abdae...08c42ba0f9
@@ -81,11 +81,15 @@ unpack() {
|
||||
mv "$files"/* .
|
||||
rmdir "$files"
|
||||
fi
|
||||
touch .unpacked
|
||||
}
|
||||
fetchSource() (
|
||||
source .source
|
||||
|
||||
if [[ $pkg && -e "${pkg##*/}" ]]; then
|
||||
if [[ -e .unpacked ]]; then
|
||||
true
|
||||
|
||||
elif [[ $pkg && -e "${pkg##*/}" ]]; then
|
||||
files=( !("${pkg##*/}") )
|
||||
[[ -e $files ]] || {
|
||||
echo
|
||||
@@ -135,11 +139,14 @@ fetchSource() (
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for patch in "${patches[@]}"; do
|
||||
echo
|
||||
echo "Patching: ${PWD##*/}, for $patch..."
|
||||
patch -p0 < ../"${PWD##*/}-$patch.patch"
|
||||
done
|
||||
if [[ ! -e .patched ]] && (( ${#patches[@]} )); then
|
||||
for patch in "${patches[@]}"; do
|
||||
echo
|
||||
echo "Patching: ${PWD##*/}, for $patch..."
|
||||
patch -p0 < ../"${PWD##*/}-$patch.patch"
|
||||
done
|
||||
touch .patched
|
||||
fi
|
||||
)
|
||||
depend() {
|
||||
|
||||
@@ -220,8 +227,8 @@ mpw() {
|
||||
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[@]}" "${LDFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" \
|
||||
mpw-cli.c -o mpw
|
||||
cc "${CFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" \
|
||||
"${LDFLAGS[@]}" "mpw-cli.c" -o "mpw"
|
||||
echo "done! Now run ./install or use ./mpw"
|
||||
}
|
||||
|
||||
@@ -257,8 +264,8 @@ mpw-bench() {
|
||||
-l"crypto"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" \
|
||||
mpw-bench.c -o mpw-bench
|
||||
cc "${CFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" \
|
||||
"${LDFLAGS[@]}" "mpw-bench.c" -o "mpw-bench"
|
||||
echo "done! Now use ./mpw-bench"
|
||||
}
|
||||
|
||||
@@ -273,6 +280,7 @@ mpw-tests() {
|
||||
# include paths
|
||||
-I"lib/include"
|
||||
-I"/usr/include/libxml2"
|
||||
-I"/usr/local/include/libxml2"
|
||||
)
|
||||
LDFLAGS=(
|
||||
# scrypt
|
||||
@@ -288,9 +296,9 @@ mpw-tests() {
|
||||
-l"crypto" -l"xml2"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-tests-util.c -o mpw-tests-util.o
|
||||
cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" "mpw-tests-util.o" \
|
||||
mpw-tests.c -o mpw-tests
|
||||
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" \
|
||||
"${LDFLAGS[@]}" "mpw-tests.c" -o "mpw-tests"
|
||||
echo "done! Now use ./mpw-tests"
|
||||
}
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@ set -e
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
tag=$(git describe)
|
||||
commit=$(git describe --long --dirty)
|
||||
[[ $tag && $commit = $tag-* ]] || exit 1
|
||||
[[ $tag && $commit = $tag* ]] || exit 1
|
||||
git show --show-signature --pretty=format:%H --quiet "$tag" > VERSION
|
||||
|
||||
mpwArchive=mpw-$commit.tar.gz
|
||||
[[ -e $mpwArchive ]] && echo "WARNING: $mpwArchive already exists. Will overwrite."
|
||||
read -n1 -p "Will prepare and release $mpwArchive. Press a key to continue or ^C to abort."
|
||||
|
||||
git ls-files -z . | xargs -0 tar -cvzf "$mpwArchive"
|
||||
git ls-files -z . | xargs -0 tar -Lcvzf "$mpwArchive"
|
||||
echo "$mpwArchive ready, SHA256: $(openssl sha -sha256 < "$mpwArchive")"
|
||||
|
||||
cd ../../Site/current
|
||||
|
||||
@@ -6,106 +6,48 @@
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
#include "mpw-algorithm.h"
|
||||
#include "mpw-algorithm_v0.c"
|
||||
#include "mpw-algorithm_v1.c"
|
||||
#include "mpw-algorithm_v2.c"
|
||||
#include "mpw-algorithm_v3.c"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPassword) {
|
||||
const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "fullName: %s\n", fullName );
|
||||
trc( "masterPassword: %s\n", masterPassword );
|
||||
trc( "key scope: %s\n", mpKeyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
// masterKeySalt = mpKeyScope . #fullName . fullName
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope );
|
||||
mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( strlen( fullName ) ) );
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||
return NULL;
|
||||
switch (algorithmVersion) {
|
||||
case MPAlgorithmVersion0:
|
||||
return mpw_masterKeyForUser_v0( fullName, masterPassword );
|
||||
case MPAlgorithmVersion1:
|
||||
return mpw_masterKeyForUser_v1( fullName, masterPassword );
|
||||
case MPAlgorithmVersion2:
|
||||
return mpw_masterKeyForUser_v2( fullName, masterPassword );
|
||||
case MPAlgorithmVersion3:
|
||||
return mpw_masterKeyForUser_v3( fullName, masterPassword );
|
||||
default:
|
||||
ftl( "Unsupported version: %d", algorithmVersion );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
const char *mpw_passwordForSite(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
const MPSiteVariant siteVariant, const char *siteContext, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
trc( "siteVariant: %d\n", siteVariant );
|
||||
trc( "siteType: %d\n", siteType );
|
||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "<empty>": siteContext );
|
||||
|
||||
// Calculate the site seed.
|
||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||
size_t sitePasswordInfoSize = 0;
|
||||
uint8_t *sitePasswordInfo = NULL;
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteScope );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteName ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteName );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) );
|
||||
if (siteContext) {
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteContext ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||
switch (algorithmVersion) {
|
||||
case MPAlgorithmVersion0:
|
||||
return mpw_passwordForSite_v0( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext );
|
||||
case MPAlgorithmVersion1:
|
||||
return mpw_passwordForSite_v1( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext );
|
||||
case MPAlgorithmVersion2:
|
||||
return mpw_passwordForSite_v2( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext );
|
||||
case MPAlgorithmVersion3:
|
||||
return mpw_passwordForSite_v3( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext );
|
||||
default:
|
||||
ftl( "Unsupported version: %d", algorithmVersion );
|
||||
return NULL;
|
||||
}
|
||||
if (!sitePasswordInfo) {
|
||||
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType( siteType, sitePasswordSeed[0] );
|
||||
trc( "type %d, template: %s\n", siteType, template );
|
||||
if (strlen( template ) > 32) {
|
||||
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass( template[c], sitePasswordSeed[c + 1] );
|
||||
trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1],
|
||||
sitePassword[c] );
|
||||
}
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
|
||||
return sitePassword;
|
||||
}
|
||||
|
||||
@@ -6,15 +6,27 @@
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#define MP_dkLen 64
|
||||
#include "mpw-types.h"
|
||||
|
||||
typedef enum(unsigned int, MPAlgorithmVersion) {
|
||||
/** V0 did math with chars whose signedness was platform-dependent. */
|
||||
MPAlgorithmVersion0,
|
||||
/** V1 miscounted the byte-length of multi-byte site names. */
|
||||
MPAlgorithmVersion1,
|
||||
/** V2 miscounted the byte-length of multi-byte user names. */
|
||||
MPAlgorithmVersion2,
|
||||
/** V3 is the current version. */
|
||||
MPAlgorithmVersion3,
|
||||
};
|
||||
#define MPAlgorithmVersionCurrent MPAlgorithmVersion3
|
||||
|
||||
/** Derive the master key for a user based on their name and master password.
|
||||
* @return A new MP_dkLen-byte allocated buffer or NULL if an allocation error occurred. */
|
||||
* @return A new MP_dkLen-byte allocated buffer or NULL if an allocation error occurred. */
|
||||
const uint8_t *mpw_masterKeyForUser(
|
||||
const char *fullName, const char *masterPassword);
|
||||
const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion);
|
||||
|
||||
/** Encode a password for the site from the given master key and site parameters.
|
||||
* @return A newly allocated string or NULL if an allocation error occurred. */
|
||||
* @return A newly allocated string or NULL if an allocation error occurred. */
|
||||
const char *mpw_passwordForSite(
|
||||
const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext);
|
||||
const MPSiteVariant siteVariant, const char *siteContext, const MPAlgorithmVersion algorithmVersion);
|
||||
|
||||
125
MasterPassword/C/mpw-algorithm_v0.c
Normal file
125
MasterPassword/C/mpw-algorithm_v0.c
Normal file
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// mpw-algorithm.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const char *mpw_templateForType_v0(MPSiteType type, uint16_t seedByte) {
|
||||
|
||||
size_t count = 0;
|
||||
const char **templates = mpw_templatesForType( type, &count );
|
||||
if (!count)
|
||||
return NULL;
|
||||
|
||||
return templates[seedByte % count];
|
||||
}
|
||||
|
||||
static const char mpw_characterFromClass_v0(char characterClass, uint16_t seedByte) {
|
||||
|
||||
const char *classCharacters = mpw_charactersInClass( characterClass );
|
||||
return classCharacters[seedByte % strlen( classCharacters )];
|
||||
}
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "fullName: %s\n", fullName );
|
||||
trc( "masterPassword: %s\n", masterPassword );
|
||||
trc( "key scope: %s\n", mpKeyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
// masterKeySalt = mpKeyScope . #fullName . fullName
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope );
|
||||
mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( mpw_charlen( fullName ) ) );
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v0(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
trc( "siteVariant: %d\n", siteVariant );
|
||||
trc( "siteType: %d\n", siteType );
|
||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "<empty>": siteContext );
|
||||
|
||||
// Calculate the site seed.
|
||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||
size_t sitePasswordInfoSize = 0;
|
||||
uint8_t *sitePasswordInfo = NULL;
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteScope );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_charlen( siteName ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteName );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) );
|
||||
if (siteContext) {
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_charlen( siteContext ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||
}
|
||||
if (!sitePasswordInfo) {
|
||||
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const char *sitePasswordSeed = (const char *)mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType_v0( siteType, htons( sitePasswordSeed[0] ) );
|
||||
trc( "type %d, template: %s\n", siteType, template );
|
||||
if (strlen( template ) > 32) {
|
||||
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass_v0( template[c], htons( sitePasswordSeed[c + 1] ) );
|
||||
trc( "class %c, index %u (0x%02X) -> character: %c\n",
|
||||
template[c], htons( sitePasswordSeed[c + 1] ), htons( sitePasswordSeed[c + 1] ), sitePassword[c] );
|
||||
}
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
|
||||
return sitePassword;
|
||||
}
|
||||
109
MasterPassword/C/mpw-algorithm_v1.c
Normal file
109
MasterPassword/C/mpw-algorithm_v1.c
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// mpw-algorithm.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v1(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "fullName: %s\n", fullName );
|
||||
trc( "masterPassword: %s\n", masterPassword );
|
||||
trc( "key scope: %s\n", mpKeyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
// masterKeySalt = mpKeyScope . #fullName . fullName
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope );
|
||||
mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( mpw_charlen( fullName ) ) );
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v1(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
trc( "siteVariant: %d\n", siteVariant );
|
||||
trc( "siteType: %d\n", siteType );
|
||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "<empty>": siteContext );
|
||||
|
||||
// Calculate the site seed.
|
||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||
size_t sitePasswordInfoSize = 0;
|
||||
uint8_t *sitePasswordInfo = NULL;
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteScope );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_charlen( siteName ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteName );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) );
|
||||
if (siteContext) {
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_charlen( siteContext ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||
}
|
||||
if (!sitePasswordInfo) {
|
||||
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType( siteType, sitePasswordSeed[0] );
|
||||
trc( "type %d, template: %s\n", siteType, template );
|
||||
if (strlen( template ) > 32) {
|
||||
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass( template[c], sitePasswordSeed[c + 1] );
|
||||
trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1],
|
||||
sitePassword[c] );
|
||||
}
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
|
||||
return sitePassword;
|
||||
}
|
||||
109
MasterPassword/C/mpw-algorithm_v2.c
Normal file
109
MasterPassword/C/mpw-algorithm_v2.c
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// mpw-algorithm.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v2(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "fullName: %s\n", fullName );
|
||||
trc( "masterPassword: %s\n", masterPassword );
|
||||
trc( "key scope: %s\n", mpKeyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
// masterKeySalt = mpKeyScope . #fullName . fullName
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope );
|
||||
mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( mpw_charlen( fullName ) ) );
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v2(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
trc( "siteVariant: %d\n", siteVariant );
|
||||
trc( "siteType: %d\n", siteType );
|
||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "<empty>": siteContext );
|
||||
|
||||
// Calculate the site seed.
|
||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||
size_t sitePasswordInfoSize = 0;
|
||||
uint8_t *sitePasswordInfo = NULL;
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteScope );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteName ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteName );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) );
|
||||
if (siteContext) {
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteContext ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||
}
|
||||
if (!sitePasswordInfo) {
|
||||
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType( siteType, sitePasswordSeed[0] );
|
||||
trc( "type %d, template: %s\n", siteType, template );
|
||||
if (strlen( template ) > 32) {
|
||||
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass( template[c], sitePasswordSeed[c + 1] );
|
||||
trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1],
|
||||
sitePassword[c] );
|
||||
}
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
|
||||
return sitePassword;
|
||||
}
|
||||
109
MasterPassword/C/mpw-algorithm_v3.c
Normal file
109
MasterPassword/C/mpw-algorithm_v3.c
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// mpw-algorithm.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v3(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "fullName: %s\n", fullName );
|
||||
trc( "masterPassword: %s\n", masterPassword );
|
||||
trc( "key scope: %s\n", mpKeyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
// masterKeySalt = mpKeyScope . #fullName . fullName
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope );
|
||||
mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( strlen( fullName ) ) );
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v3(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
trc( "siteVariant: %d\n", siteVariant );
|
||||
trc( "siteType: %d\n", siteType );
|
||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext == NULL? "<empty>": siteContext );
|
||||
|
||||
// Calculate the site seed.
|
||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||
size_t sitePasswordInfoSize = 0;
|
||||
uint8_t *sitePasswordInfo = NULL;
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteScope );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteName ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteName );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) );
|
||||
if (siteContext) {
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteContext ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||
}
|
||||
if (!sitePasswordInfo) {
|
||||
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType( siteType, sitePasswordSeed[0] );
|
||||
trc( "type %d, template: %s\n", siteType, template );
|
||||
if (strlen( template ) > 32) {
|
||||
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass( template[c], sitePasswordSeed[c + 1] );
|
||||
trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1],
|
||||
sitePassword[c] );
|
||||
}
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
|
||||
return sitePassword;
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <scrypt/sha256.h>
|
||||
#include <bcrypt/ow-crypt.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-algorithm.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
@@ -62,10 +61,12 @@ int main(int argc, char *const argv[]) {
|
||||
unsigned int iterations = 100;
|
||||
mpw_getTime( &startTime );
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser( fullName, masterPassword );
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser(
|
||||
fullName, masterPassword, MPAlgorithmVersionCurrent );
|
||||
if (!masterKey)
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
free( (void *)mpw_passwordForSite( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext ) );
|
||||
free( (void *)mpw_passwordForSite(
|
||||
masterKey, siteName, siteType, siteCounter, siteVariant, siteContext, MPAlgorithmVersionCurrent ) );
|
||||
free( (void *)masterKey );
|
||||
|
||||
if (i % 1 == 0)
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
|
||||
#define ftl(...) do { fprintf( stderr, __VA_ARGS__ ); exit(2); } while (0)
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-algorithm.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_env_fullname "MP_FULLNAME"
|
||||
#define MP_env_sitetype "MP_SITETYPE"
|
||||
#define MP_env_sitecounter "MP_SITECOUNTER"
|
||||
#define MP_env_algorithm "MP_ALGORITHM"
|
||||
|
||||
static void usage() {
|
||||
|
||||
@@ -39,7 +39,9 @@ static void usage() {
|
||||
" n, name | 9 letter name.\n"
|
||||
" p, phrase | 20 character sentence.\n\n", MP_env_sitetype );
|
||||
fprintf( stderr, " -c counter The value of the counter.\n"
|
||||
" Defaults to %s in env or '1'.\n\n", MP_env_sitecounter );
|
||||
" Defaults to %s in env or 1.\n\n", MP_env_sitecounter );
|
||||
fprintf( stderr, " -V version The algorithm version to use.\n"
|
||||
" Defaults to %s in env or %d.\n\n", MP_env_algorithm, MPAlgorithmVersionCurrent );
|
||||
fprintf( stderr, " -v variant The kind of content to generate.\n"
|
||||
" Defaults to 'password'.\n"
|
||||
" p, password | The password to log in with.\n"
|
||||
@@ -102,13 +104,23 @@ int main(int argc, char *const argv[]) {
|
||||
const char *siteContextString = NULL;
|
||||
uint32_t siteCounter = 1;
|
||||
const char *siteCounterString = getenv( MP_env_sitecounter );
|
||||
MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent;
|
||||
const char *algorithmVersionString = getenv( MP_env_algorithm );
|
||||
if (algorithmVersionString && strlen( algorithmVersionString ))
|
||||
if (sscanf( algorithmVersionString, "%u", &algorithmVersion ) != 1)
|
||||
ftl( "Invalid %s: %s\n", MP_env_algorithm, algorithmVersionString );
|
||||
|
||||
// Read the options.
|
||||
for (int opt; (opt = getopt( argc, argv, "u:t:c:v:C:h" )) != -1;)
|
||||
for (int opt; (opt = getopt( argc, argv, "u:P:t:c:v:V:C:h" )) != -1;)
|
||||
switch (opt) {
|
||||
case 'u':
|
||||
fullName = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
// Do not use this. Passing your master password via the command-line
|
||||
// is insecure. This is here for non-interactive testing purposes only.
|
||||
masterPassword = strcpy( malloc( strlen( optarg ) + 1 ), optarg );
|
||||
break;
|
||||
case 't':
|
||||
siteTypeString = optarg;
|
||||
break;
|
||||
@@ -118,6 +130,10 @@ int main(int argc, char *const argv[]) {
|
||||
case 'v':
|
||||
siteVariantString = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
if (sscanf( optarg, "%u", &algorithmVersion ) != 1)
|
||||
ftl( "Not a version: %s\n", optarg );
|
||||
break;
|
||||
case 'C':
|
||||
siteContextString = optarg;
|
||||
break;
|
||||
@@ -161,6 +177,7 @@ int main(int argc, char *const argv[]) {
|
||||
siteType = MPSiteTypeGeneratedPhrase;
|
||||
if (siteTypeString)
|
||||
siteType = mpw_typeWithName( siteTypeString );
|
||||
trc( "algorithmVersion: %u\n", algorithmVersion );
|
||||
|
||||
// Read the master password.
|
||||
char *mpwConfigPath = homedir( ".mpw" );
|
||||
@@ -188,12 +205,14 @@ int main(int argc, char *const argv[]) {
|
||||
fprintf( stderr, "%s's password for %s:\n[ %s ]: ", fullName, siteName, mpw_identicon( fullName, masterPassword ) );
|
||||
|
||||
// Output the password.
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser( fullName, masterPassword );
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser(
|
||||
fullName, masterPassword, algorithmVersion );
|
||||
mpw_freeString( masterPassword );
|
||||
if (!masterKey)
|
||||
ftl( "Couldn't derive master key." );
|
||||
|
||||
const char *sitePassword = mpw_passwordForSite( masterKey, siteName, siteType, siteCounter, siteVariant, siteContextString );
|
||||
const char *sitePassword = mpw_passwordForSite(
|
||||
masterKey, siteName, siteType, siteCounter, siteVariant, siteContextString, algorithmVersion );
|
||||
mpw_free( masterKey, MP_dkLen );
|
||||
if (!sitePassword)
|
||||
ftl( "Couldn't derive site password." );
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#define ftl(...) do { fprintf( stderr, __VA_ARGS__ ); exit(2); } while (0)
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-algorithm.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
@@ -40,13 +39,13 @@ int main(int argc, char *const argv[]) {
|
||||
|
||||
// 1. calculate the master key.
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser(
|
||||
(char *)fullName, (char *)masterPassword );
|
||||
(char *)fullName, (char *)masterPassword, MPAlgorithmVersionCurrent );
|
||||
if (!masterKey)
|
||||
ftl( "Couldn't derive master key." );
|
||||
|
||||
// 2. calculate the site password.
|
||||
const char *sitePassword = mpw_passwordForSite(
|
||||
masterKey, (char *)siteName, siteType, siteCounter, siteVariant, (char *)siteContext );
|
||||
masterKey, (char *)siteName, siteType, siteCounter, siteVariant, (char *)siteContext, MPAlgorithmVersionCurrent );
|
||||
mpw_free( masterKey, MP_dkLen );
|
||||
if (!sitePassword)
|
||||
ftl( "Couldn't derive site password." );
|
||||
|
||||
@@ -51,56 +51,71 @@ const MPSiteType mpw_typeWithName(const char *typeName) {
|
||||
abort();
|
||||
}
|
||||
|
||||
const char *mpw_templateForType(MPSiteType type, uint8_t seedByte) {
|
||||
inline const char **mpw_templatesForType(MPSiteType type, size_t *count) {
|
||||
|
||||
if (!(type & MPSiteTypeClassGenerated)) {
|
||||
fprintf( stderr, "Not a generated type: %d", type );
|
||||
abort();
|
||||
ftl( "Not a generated type: %d", type );
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedMaximum: {
|
||||
const char *templates[] = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
|
||||
return templates[seedByte % 2];
|
||||
*count = 2;
|
||||
return (const char *[]){ "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
|
||||
}
|
||||
case MPSiteTypeGeneratedLong: {
|
||||
const char *templates[] = { "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno",
|
||||
*count = 21;
|
||||
return (const char *[]){ "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno",
|
||||
"CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno",
|
||||
"CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno",
|
||||
"CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno",
|
||||
"CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno",
|
||||
"CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno",
|
||||
"CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" };
|
||||
return templates[seedByte % 21];
|
||||
}
|
||||
case MPSiteTypeGeneratedMedium: {
|
||||
const char *templates[] = { "CvcnoCvc", "CvcCvcno" };
|
||||
return templates[seedByte % 2];
|
||||
*count = 2;
|
||||
return (const char *[]){ "CvcnoCvc", "CvcCvcno" };
|
||||
}
|
||||
case MPSiteTypeGeneratedBasic: {
|
||||
const char *templates[] = { "aaanaaan", "aannaaan", "aaannaaa" };
|
||||
return templates[seedByte % 3];
|
||||
*count = 3;
|
||||
return (const char *[]){ "aaanaaan", "aannaaan", "aaannaaa" };
|
||||
}
|
||||
case MPSiteTypeGeneratedShort: {
|
||||
return "Cvcn";
|
||||
*count = 1;
|
||||
return (const char *[]){"Cvcn"};
|
||||
}
|
||||
case MPSiteTypeGeneratedPIN: {
|
||||
return "nnnn";
|
||||
*count = 1;
|
||||
return (const char *[]){ "nnnn" };
|
||||
}
|
||||
case MPSiteTypeGeneratedName: {
|
||||
return "cvccvcvcv";
|
||||
*count = 1;
|
||||
return (const char *[]) {"cvccvcvcv"};
|
||||
}
|
||||
case MPSiteTypeGeneratedPhrase: {
|
||||
const char *templates[] = { "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" };
|
||||
return templates[seedByte % 3];
|
||||
*count = 3;
|
||||
return (const char *[]){ "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" };
|
||||
}
|
||||
default: {
|
||||
fprintf( stderr, "Unknown generated type: %d", type );
|
||||
abort();
|
||||
ftl( "Unknown generated type: %d", type );
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *mpw_templateForType(MPSiteType type, uint8_t seedByte) {
|
||||
|
||||
size_t count = 0;
|
||||
const char **templates = mpw_templatesForType( type, &count );
|
||||
if (!count)
|
||||
return NULL;
|
||||
|
||||
return templates[seedByte % count];
|
||||
}
|
||||
|
||||
const MPSiteVariant mpw_variantWithName(const char *variantName) {
|
||||
|
||||
char stdVariantName[strlen( variantName )];
|
||||
@@ -138,55 +153,38 @@ const char *mpw_scopeForVariant(MPSiteVariant variant) {
|
||||
}
|
||||
}
|
||||
|
||||
const char mpw_characterFromClass(char characterClass, uint8_t seedByte) {
|
||||
const char *mpw_charactersInClass(char characterClass) {
|
||||
|
||||
const char *classCharacters;
|
||||
switch (characterClass) {
|
||||
case 'V': {
|
||||
classCharacters = "AEIOU";
|
||||
break;
|
||||
}
|
||||
case 'C': {
|
||||
classCharacters = "BCDFGHJKLMNPQRSTVWXYZ";
|
||||
break;
|
||||
}
|
||||
case 'v': {
|
||||
classCharacters = "aeiou";
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
classCharacters = "bcdfghjklmnpqrstvwxyz";
|
||||
break;
|
||||
}
|
||||
case 'A': {
|
||||
classCharacters = "AEIOUBCDFGHJKLMNPQRSTVWXYZ";
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
classCharacters = "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz";
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
classCharacters = "0123456789";
|
||||
break;
|
||||
}
|
||||
case 'o': {
|
||||
classCharacters = "@&%?,=[]_:-+*$#!'^~;()/.";
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
classCharacters = "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()";
|
||||
break;
|
||||
}
|
||||
case ' ': {
|
||||
classCharacters = " ";
|
||||
break;
|
||||
}
|
||||
case 'V':
|
||||
return "AEIOU";
|
||||
case 'C':
|
||||
return "BCDFGHJKLMNPQRSTVWXYZ";
|
||||
case 'v':
|
||||
return "aeiou";
|
||||
case 'c':
|
||||
return "bcdfghjklmnpqrstvwxyz";
|
||||
case 'A':
|
||||
return "AEIOUBCDFGHJKLMNPQRSTVWXYZ";
|
||||
case 'a':
|
||||
return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz";
|
||||
case 'n':
|
||||
return "0123456789";
|
||||
case 'o':
|
||||
return "@&%?,=[]_:-+*$#!'^~;()/.";
|
||||
case 'x':
|
||||
return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()";
|
||||
case ' ':
|
||||
return " ";
|
||||
default: {
|
||||
fprintf( stderr, "Unknown character class: %c", characterClass );
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char mpw_characterFromClass(char characterClass, uint8_t seedByte) {
|
||||
|
||||
const char *classCharacters = mpw_charactersInClass( characterClass );
|
||||
return classCharacters[seedByte % strlen( classCharacters )];
|
||||
}
|
||||
|
||||
@@ -6,32 +6,43 @@
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef NS_ENUM
|
||||
#define enum(_type, _name) NS_ENUM(_type, _name)
|
||||
#else
|
||||
#define enum(_type, _name) _type _name; enum
|
||||
#endif
|
||||
|
||||
#define MP_dkLen 64
|
||||
|
||||
//// Types.
|
||||
|
||||
typedef enum {
|
||||
typedef enum( unsigned int, MPSiteVariant ) {
|
||||
/** Generate the password to log in with. */
|
||||
MPSiteVariantPassword,
|
||||
/** Generate the login name to log in as. */
|
||||
MPSiteVariantLogin,
|
||||
/** Generate the answer to a security question. */
|
||||
MPSiteVariantAnswer,
|
||||
} MPSiteVariant;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
typedef enum( unsigned int, MPSiteTypeClass ) {
|
||||
/** Generate the password. */
|
||||
MPSiteTypeClassGenerated = 1 << 4,
|
||||
/** Store the password. */
|
||||
MPSiteTypeClassStored = 1 << 5,
|
||||
} MPSiteTypeClass;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
typedef enum( unsigned int, MPSiteFeature ) {
|
||||
/** Export the key-protected content data. */
|
||||
MPSiteFeatureExportContent = 1 << 10,
|
||||
/** Never export content. */
|
||||
MPSiteFeatureDevicePrivate = 1 << 11,
|
||||
} MPSiteFeature;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
typedef enum( unsigned int, MPSiteType) {
|
||||
MPSiteTypeGeneratedMaximum = 0x0 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedLong = 0x1 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedMedium = 0x2 | MPSiteTypeClassGenerated | 0x0,
|
||||
@@ -43,13 +54,42 @@ typedef enum {
|
||||
|
||||
MPSiteTypeStoredPersonal = 0x0 | MPSiteTypeClassStored | MPSiteFeatureExportContent,
|
||||
MPSiteTypeStoredDevicePrivate = 0x1 | MPSiteTypeClassStored | MPSiteFeatureDevicePrivate,
|
||||
} MPSiteType;
|
||||
};
|
||||
|
||||
//// Type utilities.
|
||||
|
||||
/**
|
||||
* @return The variant represented by the given name.
|
||||
*/
|
||||
const MPSiteVariant mpw_variantWithName(const char *variantName);
|
||||
/**
|
||||
* @return An internal string containing the scope identifier to apply when encoding for the given variant.
|
||||
*/
|
||||
const char *mpw_scopeForVariant(MPSiteVariant variant);
|
||||
|
||||
/**
|
||||
* @return The type represented by the given name.
|
||||
*/
|
||||
const MPSiteType mpw_typeWithName(const char *typeName);
|
||||
|
||||
/**
|
||||
* @return An array of internal strings that express the templates to use for the given type.
|
||||
* The amount of elements in the array is stored in count.
|
||||
* If an unsupported type is given, count will be 0 and will return NULL.
|
||||
*/
|
||||
const char **mpw_templatesForType(MPSiteType type, size_t *count);
|
||||
/**
|
||||
* @return An internal string that contains the password encoding template of the given type
|
||||
* for a seed that starts with the given byte.
|
||||
*/
|
||||
const char *mpw_templateForType(MPSiteType type, uint8_t seedByte);
|
||||
|
||||
/**
|
||||
* @return An internal string that contains all the characters that occur in the given character class.
|
||||
*/
|
||||
const char *mpw_charactersInClass(char characterClass);
|
||||
/**
|
||||
* @return A character from given character class that encodes the given byte.
|
||||
*/
|
||||
const char mpw_characterFromClass(char characterClass, uint8_t seedByte);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include <scrypt/sha256.h>
|
||||
#include <scrypt/crypto_scrypt.h>
|
||||
@@ -163,3 +164,9 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) {
|
||||
free( resetString );
|
||||
return identicon;
|
||||
}
|
||||
|
||||
const size_t mpw_charlen(const char *string) {
|
||||
|
||||
setlocale( LC_ALL, "en_US.UTF-8" );
|
||||
return mbstowcs( NULL, string, strlen( string ) );
|
||||
}
|
||||
|
||||
@@ -6,13 +6,19 @@
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//// Logging.
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifndef trc
|
||||
#define trc(...) fprintf( stderr, __VA_ARGS__ )
|
||||
#endif
|
||||
#else
|
||||
#ifndef trc
|
||||
#define trc(...) do {} while (0)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ftl
|
||||
#define ftl(...) do { fprintf( stderr, __VA_ARGS__ ); abort(); } while (0)
|
||||
#endif
|
||||
@@ -50,11 +56,15 @@ uint8_t const *mpw_hmac_sha256(
|
||||
//// Visualizers.
|
||||
|
||||
/** Encode a buffer as a string of hexadecimal characters.
|
||||
* @return 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);
|
||||
/** Encode a fingerprint for a buffer.
|
||||
* @return 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);
|
||||
/** Encode a visual fingerprint for a user.
|
||||
* @return A newly allocated string. */
|
||||
const char *mpw_identicon(const char *fullName, const char *masterPassword);
|
||||
|
||||
//// String utilities.
|
||||
|
||||
const size_t mpw_charlen(const char *string);
|
||||
|
||||
2
MasterPassword/Java/.gitignore
vendored
Normal file
2
MasterPassword/Java/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target
|
||||
dependency-reduced-pom.xml
|
||||
@@ -24,12 +24,12 @@
|
||||
<dependency>
|
||||
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||
<artifactId>opal-system</artifactId>
|
||||
<version>1.6-p6</version>
|
||||
<version>1.6-p7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||
<artifactId>opal-crypto</artifactId>
|
||||
<version>1.6-p6</version>
|
||||
<version>1.6-p7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- EXTERNAL DEPENDENCIES -->
|
||||
|
||||
@@ -77,15 +77,6 @@ public class MasterKey {
|
||||
return idForBytes( masterKey );
|
||||
}
|
||||
|
||||
private byte[] getSubKey(final int subkeyLength) {
|
||||
|
||||
Preconditions.checkState( valid );
|
||||
byte[] subkey = new byte[Math.min( subkeyLength, masterKey.length )];
|
||||
System.arraycopy( masterKey, 0, subkey, 0, subkey.length );
|
||||
|
||||
return subkey;
|
||||
}
|
||||
|
||||
public String encode(final String siteName, final MPSiteType siteType, int siteCounter, final MPSiteVariant siteVariant,
|
||||
@Nullable final String siteContext) {
|
||||
Preconditions.checkState( valid );
|
||||
|
||||
@@ -114,11 +114,10 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.lambdaworks</groupId>
|
||||
<artifactId>libscrypt</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<type>so</type>
|
||||
<classifier>android</classifier>
|
||||
<scope>runtime</scope>
|
||||
<artifactId>scrypt</artifactId>
|
||||
<version>1.4.0-android</version>
|
||||
<type>jar</type>
|
||||
<classifier>native</classifier>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -12,64 +12,61 @@
|
||||
android:gravity="center">
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="20dp"
|
||||
android:indeterminate="true" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/userNameField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text|textCapWords|textPersonName"
|
||||
android:hint="@string/userName.hint"
|
||||
android:hint="@string/userName_hint"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="26sp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/masterPasswordField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text|textPassword"
|
||||
android:hint="@string/masterPassword.hint"
|
||||
android:password="true"
|
||||
android:hint="@string/masterPassword_hint"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/double_"
|
||||
android:contentDescription="@string/empty" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/siteNameField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text|textNoSuggestions|textUri"
|
||||
android:hint="@string/siteName.hint"
|
||||
android:hint="@string/siteName_hint"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="26sp" />
|
||||
|
||||
<Button
|
||||
<ImageView
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:src="@drawable/double_"
|
||||
android:contentDescription="@string/empty" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sitePasswordField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:background="@null"
|
||||
android:background="@android:color/transparent"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="32sp"
|
||||
android:text="LuxdZozvDuma4["
|
||||
@@ -77,13 +74,30 @@
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/typeField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center" />
|
||||
|
||||
<NumberPicker
|
||||
<EditText
|
||||
android:id="@+id/counterField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:inputType="text|textNoSuggestions"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="26sp"
|
||||
android:text="1" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/rememberPasswordField"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/remember" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
<resources>
|
||||
<string name="app_name">Master Password</string>
|
||||
<string name="avatar">User Avatar</string>
|
||||
<string name="siteName.hint">Site Name</string>
|
||||
<string name="userName.hint">Your Name</string>
|
||||
<string name="masterPassword.hint">Your Master Password</string>
|
||||
<string name="remember">Remember Password</string>
|
||||
<string name="siteName_hint">Site Name</string>
|
||||
<string name="userName_hint">Your Name</string>
|
||||
<string name="masterPassword_hint">Your Master Password</string>
|
||||
<string name="empty" />
|
||||
</resources>
|
||||
|
||||
@@ -9,12 +9,14 @@ import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.*;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.InjectView;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.util.concurrent.*;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.lhunath.opal.system.util.ConversionUtils;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
|
||||
@@ -55,11 +57,14 @@ public class EmergencyActivity extends Activity {
|
||||
Spinner typeField;
|
||||
|
||||
@InjectView(R.id.counterField)
|
||||
NumberPicker counterField;
|
||||
EditText counterField;
|
||||
|
||||
@InjectView(R.id.sitePasswordField)
|
||||
TextView sitePasswordField;
|
||||
|
||||
@InjectView(R.id.rememberPasswordField)
|
||||
CheckBox rememberPasswordField;
|
||||
|
||||
private int hc_userName;
|
||||
private int hc_masterPassword;
|
||||
|
||||
@@ -68,6 +73,7 @@ public class EmergencyActivity extends Activity {
|
||||
super.onCreate( savedInstanceState );
|
||||
Res.init( getResources() );
|
||||
|
||||
getWindow().setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE );
|
||||
setContentView( R.layout.activity_emergency );
|
||||
ButterKnife.inject( this );
|
||||
|
||||
@@ -75,23 +81,26 @@ public class EmergencyActivity extends Activity {
|
||||
masterPasswordField.setOnFocusChangeListener( updateMasterKey );
|
||||
siteNameField.addTextChangedListener( updateSitePassword );
|
||||
typeField.setOnItemSelectedListener( updateSitePassword );
|
||||
counterField.setOnValueChangedListener( updateSitePassword );
|
||||
counterField.addTextChangedListener( updateSitePassword );
|
||||
|
||||
userNameField.setTypeface( Res.exo_Thin );
|
||||
userNameField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
masterPasswordField.setTypeface( Res.sourceCodePro_ExtraLight );
|
||||
masterPasswordField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
masterPasswordField.setPaintFlags( masterPasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
siteNameField.setTypeface( Res.exo_Regular );
|
||||
siteNameField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
siteNameField.setPaintFlags( siteNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
sitePasswordField.setTypeface( Res.sourceCodePro_Black );
|
||||
sitePasswordField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
sitePasswordField.setPaintFlags( sitePasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
|
||||
typeField.setAdapter( new ArrayAdapter<>( this, R.layout.type_item, MPSiteType.forClass( MPSiteTypeClass.Generated ) ) );
|
||||
typeField.setSelection( MPSiteType.GeneratedLong.ordinal() );
|
||||
|
||||
counterField.setMinValue( 1 );
|
||||
counterField.setMaxValue( Integer.MAX_VALUE );
|
||||
counterField.setWrapSelectorWheel( false );
|
||||
rememberPasswordField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
|
||||
getPreferences( MODE_PRIVATE ).edit().putBoolean( "rememberPassword", isChecked ).apply();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,25 +108,32 @@ public class EmergencyActivity extends Activity {
|
||||
super.onResume();
|
||||
|
||||
userNameField.setText( getPreferences( MODE_PRIVATE ).getString( "userName", "" ) );
|
||||
rememberPasswordField.setSelected( isRememberPasswordEnabled() );
|
||||
masterPasswordField.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
synchronized (this) {
|
||||
hc_userName = hc_masterPassword = 0;
|
||||
if (masterKeyFuture != null) {
|
||||
masterKeyFuture.cancel( true );
|
||||
masterKeyFuture = null;
|
||||
if (!isRememberPasswordEnabled()) {
|
||||
synchronized (this) {
|
||||
hc_userName = hc_masterPassword = 0;
|
||||
if (masterKeyFuture != null) {
|
||||
masterKeyFuture.cancel( true );
|
||||
masterKeyFuture = null;
|
||||
}
|
||||
|
||||
sitePasswordField.setText( "" );
|
||||
progressView.setVisibility( View.INVISIBLE );
|
||||
}
|
||||
}
|
||||
|
||||
sitePasswordField.setText( "" );
|
||||
progressView.setVisibility( View.INVISIBLE );
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private boolean isRememberPasswordEnabled() {
|
||||
return getPreferences( MODE_PRIVATE ).getBoolean( "rememberPassword", false );
|
||||
}
|
||||
|
||||
private synchronized void updateMasterKey() {
|
||||
final String userName = userNameField.getText().toString();
|
||||
final String masterPassword = masterPasswordField.getText().toString();
|
||||
@@ -126,9 +142,7 @@ public class EmergencyActivity extends Activity {
|
||||
hc_userName = userName.hashCode();
|
||||
hc_masterPassword = masterPassword.hashCode();
|
||||
|
||||
SharedPreferences.Editor pref = getPreferences( MODE_PRIVATE ).edit();
|
||||
pref.putString( "userName", userName );
|
||||
pref.apply();
|
||||
getPreferences( MODE_PRIVATE ).edit().putString( "userName", userName ).apply();
|
||||
|
||||
if (masterKeyFuture != null)
|
||||
masterKeyFuture.cancel( true );
|
||||
@@ -170,7 +184,7 @@ public class EmergencyActivity extends Activity {
|
||||
private void updateSitePassword() {
|
||||
final String siteName = siteNameField.getText().toString();
|
||||
final MPSiteType type = (MPSiteType) typeField.getSelectedItem();
|
||||
final int counter = counterField.getValue();
|
||||
final int counter = ConversionUtils.toIntegerNN( counterField.getText() );
|
||||
|
||||
if (masterKeyFuture == null || siteName.isEmpty() || type == null) {
|
||||
sitePasswordField.setText( "" );
|
||||
@@ -220,13 +234,13 @@ public class EmergencyActivity extends Activity {
|
||||
|
||||
ClipDescription description = new ClipDescription( strf( "Password for %s", siteNameField.getText() ),
|
||||
new String[]{ ClipDescription.MIMETYPE_TEXT_PLAIN } );
|
||||
((ClipboardManager) getSystemService( CLIPBOARD_SERVICE )).setPrimaryClip(
|
||||
new ClipData( description, new ClipData.Item( sitePassword ) ) );
|
||||
ClipData clipData = new ClipData( description, new ClipData.Item( sitePassword ) );
|
||||
((ClipboardManager) getSystemService( CLIPBOARD_SERVICE )).setPrimaryClip( clipData );
|
||||
|
||||
Intent startMain = new Intent(Intent.ACTION_MAIN);
|
||||
startMain.addCategory(Intent.CATEGORY_HOME);
|
||||
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(startMain);
|
||||
Intent startMain = new Intent( Intent.ACTION_MAIN );
|
||||
startMain.addCategory( Intent.CATEGORY_HOME );
|
||||
startMain.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
|
||||
startActivity( startMain );
|
||||
}
|
||||
|
||||
private abstract class ValueChangedListener
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
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;
|
||||
private Avatar avatar;
|
||||
|
||||
public User(final String name, final Avatar avatar) {
|
||||
this.name = name;
|
||||
@@ -20,4 +25,19 @@ public class User {
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class AppleGUI extends GUI {
|
||||
@Override
|
||||
protected PasswordFrame newPasswordFrame(final User user) {
|
||||
PasswordFrame frame = super.newPasswordFrame( user );
|
||||
frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
|
||||
frame.setDefaultCloseOperation( WindowConstants.HIDE_ON_CLOSE );
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.google.common.base.Charsets;
|
||||
import com.google.common.io.*;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.lhunath.opal.system.util.TypeUtils;
|
||||
import com.lyndir.masterpassword.MasterKey;
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
@@ -117,9 +116,6 @@ public class GUI implements UnlockFrame.SignInCallback {
|
||||
}
|
||||
|
||||
protected PasswordFrame newPasswordFrame(final User user) {
|
||||
PasswordFrame frame = new PasswordFrame( user );
|
||||
frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
|
||||
|
||||
return frame;
|
||||
return new PasswordFrame( user );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,4 +48,9 @@ public class ModelSite extends Site {
|
||||
MPUserFileManager.get().save();
|
||||
}
|
||||
}
|
||||
|
||||
public void use() {
|
||||
model.updateLastUsed();
|
||||
MPUserFileManager.get().save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.lyndir.lhunath.opal.system.util.ObjectUtils;
|
||||
import com.lyndir.masterpassword.MasterKey;
|
||||
import com.lyndir.masterpassword.model.*;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -57,12 +58,21 @@ public class ModelUser extends User {
|
||||
if (!model.hasKeyID()) {
|
||||
model.setKeyID( key.getKeyID() );
|
||||
MPUserFileManager.get().save();
|
||||
} else if (!model.hasKeyID( key.getKeyID() ))
|
||||
} else if (!model.hasKeyID( key.getKeyID() )) {
|
||||
reset();
|
||||
throw new MasterKeyException( strf( "Incorrect master password for user: %s", getFullName() ) );
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
|
||||
masterPassword = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Site> findSitesByName(final String query) {
|
||||
return FluentIterable.from( model.findSitesByName( query ) ).transform( new Function<MPSiteResult, Site>() {
|
||||
@@ -76,7 +86,8 @@ public class ModelUser extends User {
|
||||
|
||||
@Override
|
||||
public void addSite(final Site site) {
|
||||
model.addSite( new MPSite( site.getSiteName(), site.getSiteType(), site.getSiteCounter() ) );
|
||||
model.addSite( new MPSite( model, site.getSiteName(), site.getSiteType(), site.getSiteCounter() ) );
|
||||
model.updateLastUsed();
|
||||
MPUserFileManager.get().save();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.util.concurrent.*;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.masterpassword.*;
|
||||
import com.lyndir.masterpassword.util.Components;
|
||||
import java.awt.*;
|
||||
@@ -27,8 +26,11 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
private final JButton siteAddButton;
|
||||
private final JComboBox<MPSiteType> siteTypeField;
|
||||
private final JSpinner siteCounterField;
|
||||
private final JTextField passwordField;
|
||||
private final JPasswordField passwordField;
|
||||
private final JLabel tipLabel;
|
||||
private final JCheckBox maskPasswordField;
|
||||
private final char passwordEchoChar;
|
||||
private final Font passwordEchoFont;
|
||||
private boolean updatingUI;
|
||||
private Site currentSite;
|
||||
|
||||
@@ -39,6 +41,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
|
||||
JLabel label;
|
||||
|
||||
setDefaultCloseOperation( DISPOSE_ON_CLOSE );
|
||||
setContentPane( new JPanel( new BorderLayout( 20, 20 ) ) {
|
||||
{
|
||||
setBorder( new EmptyBorder( 20, 20, 20, 20 ) );
|
||||
@@ -104,10 +107,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
passwordField.setText( null );
|
||||
siteNameField.setText( null );
|
||||
|
||||
if (getDefaultCloseOperation() == WindowConstants.EXIT_ON_CLOSE)
|
||||
System.exit( 0 );
|
||||
else
|
||||
dispose();
|
||||
dispatchEvent( new WindowEvent( PasswordFrame.this, WindowEvent.WINDOW_CLOSING ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
@@ -153,19 +153,35 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
}
|
||||
} );
|
||||
|
||||
// Mask
|
||||
maskPasswordField = new JCheckBox();
|
||||
maskPasswordField.setFont( Res.exoRegular().deriveFont( 12f ) );
|
||||
maskPasswordField.setAlignmentX( Component.CENTER_ALIGNMENT );
|
||||
maskPasswordField.setText( "Hide Password" );
|
||||
maskPasswordField.setSelected( true );
|
||||
maskPasswordField.addItemListener( new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
updateMask();
|
||||
}
|
||||
} );
|
||||
|
||||
// Password
|
||||
passwordField = new JTextField( " " );
|
||||
passwordField.setFont( Res.sourceCodeProBlack().deriveFont( 40f ) );
|
||||
passwordField = new JPasswordField();
|
||||
passwordField.setHorizontalAlignment( JTextField.CENTER );
|
||||
passwordField.setAlignmentX( Component.CENTER_ALIGNMENT );
|
||||
passwordField.setEditable( false );
|
||||
passwordField.putClientProperty( "JPasswordField.cutCopyAllowed", true );
|
||||
passwordEchoChar = passwordField.getEchoChar();
|
||||
passwordEchoFont = passwordField.getFont().deriveFont( 40f );
|
||||
updateMask();
|
||||
|
||||
// Tip
|
||||
tipLabel = new JLabel( " ", JLabel.CENTER );
|
||||
tipLabel.setFont( Res.exoRegular().deriveFont( 9f ) );
|
||||
tipLabel.setAlignmentX( Component.CENTER_ALIGNMENT );
|
||||
|
||||
add( Components.boxLayout( BoxLayout.PAGE_AXIS, passwordField, tipLabel ), BorderLayout.SOUTH );
|
||||
add( Components.boxLayout( BoxLayout.PAGE_AXIS, maskPasswordField, passwordField, tipLabel ), BorderLayout.SOUTH );
|
||||
|
||||
pack();
|
||||
setMinimumSize( getSize() );
|
||||
@@ -176,6 +192,11 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
setLocationRelativeTo( null );
|
||||
}
|
||||
|
||||
private void updateMask() {
|
||||
passwordField.setEchoChar( maskPasswordField.isSelected()? passwordEchoChar: (char) 0 );
|
||||
passwordField.setFont( maskPasswordField.isSelected()? passwordEchoFont: Res.sourceCodeProBlack().deriveFont( 40f ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private ListenableFuture<String> updatePassword() {
|
||||
|
||||
@@ -183,8 +204,8 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
if (updatingUI)
|
||||
return Futures.immediateCancelledFuture();
|
||||
if (siteNameQuery == null || siteNameQuery.isEmpty() || !user.hasKey()) {
|
||||
passwordField.setText( null );
|
||||
tipLabel.setText( null );
|
||||
passwordField.setText( null );
|
||||
return Futures.immediateCancelledFuture();
|
||||
}
|
||||
|
||||
@@ -198,7 +219,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
site.setSiteCounter( siteCounter );
|
||||
}
|
||||
|
||||
ListenableFuture<String> passwordFuture = Res.execute( new Callable<String>() {
|
||||
ListenableFuture<String> passwordFuture = Res.execute( this, new Callable<String>() {
|
||||
@Override
|
||||
public String call()
|
||||
throws Exception {
|
||||
|
||||
@@ -8,9 +8,11 @@ import com.google.common.io.Resources;
|
||||
import com.google.common.util.concurrent.*;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -22,8 +24,8 @@ import javax.swing.*;
|
||||
*/
|
||||
public abstract class Res {
|
||||
|
||||
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
private static final Logger logger = Logger.get( Res.class );
|
||||
private static final WeakHashMap<Window, ExecutorService> executorByWindow = new WeakHashMap<>();
|
||||
private static final Logger logger = Logger.get( Res.class );
|
||||
|
||||
private static Font sourceCodeProRegular;
|
||||
private static Font sourceCodeProBlack;
|
||||
@@ -32,8 +34,8 @@ public abstract class Res {
|
||||
private static Font exoRegular;
|
||||
private static Font exoThin;
|
||||
|
||||
public static Future<?> execute(final Runnable job) {
|
||||
return executor.submit( new Runnable() {
|
||||
public static Future<?> execute(final Window host, final Runnable job) {
|
||||
return getExecutor( host ).submit( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
@@ -46,7 +48,8 @@ public abstract class Res {
|
||||
} );
|
||||
}
|
||||
|
||||
public static <V> ListenableFuture<V> execute(final Callable<V> job) {
|
||||
public static <V> ListenableFuture<V> execute(final Window host, final Callable<V> job) {
|
||||
ExecutorService executor = getExecutor( host );
|
||||
return JdkFutureAdapters.listenInPoolThread( executor.submit( new Callable<V>() {
|
||||
@Override
|
||||
public V call()
|
||||
@@ -62,6 +65,25 @@ public abstract class Res {
|
||||
} ), executor );
|
||||
}
|
||||
|
||||
private static ExecutorService getExecutor(final Window host) {
|
||||
ExecutorService executor = executorByWindow.get( host );
|
||||
|
||||
if (executor == null) {
|
||||
executorByWindow.put( host, executor = Executors.newSingleThreadExecutor() );
|
||||
|
||||
host.addWindowListener( new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosed(final WindowEvent e) {
|
||||
ExecutorService executor = executorByWindow.remove( host );
|
||||
if (executor != null)
|
||||
executor.shutdownNow();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
return executor;
|
||||
}
|
||||
|
||||
public static Icon iconAdd() {
|
||||
return new RetinaIcon( Resources.getResource( "media/icon_add@2x.png" ) );
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class UnlockFrame extends JFrame {
|
||||
signInButton.setEnabled( false );
|
||||
signInButton.setText( "Signing In..." );
|
||||
|
||||
Res.execute( new Runnable() {
|
||||
Res.execute( this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean success = signInCallback.signedIn( user );
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.lyndir.masterpassword.gui;
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||
|
||||
import com.lyndir.masterpassword.MasterKey;
|
||||
import com.lyndir.masterpassword.model.MPUser;
|
||||
import java.security.KeyException;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
||||
@@ -30,25 +32,38 @@ public abstract class User {
|
||||
@Nonnull
|
||||
public MasterKey getKey() throws MasterKeyException {
|
||||
if (key == null) {
|
||||
if (!hasKey())
|
||||
String masterPassword = getMasterPassword();
|
||||
if (masterPassword == null || masterPassword.isEmpty()) {
|
||||
reset();
|
||||
throw new MasterKeyException( strf( "Master password unknown for user: %s", getFullName() ) );
|
||||
key = new MasterKey( getFullName(), getMasterPassword() );
|
||||
}
|
||||
|
||||
key = new MasterKey( getFullName(), masterPassword );
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
key = null;
|
||||
}
|
||||
|
||||
public abstract Iterable<Site> findSitesByName(final String siteName);
|
||||
|
||||
public abstract void addSite(final Site site);
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return this == obj || obj instanceof User && Objects.equals( getFullName(), ((User) obj).getFullName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getFullName().hashCode();
|
||||
return Objects.hashCode( getFullName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getFullName();
|
||||
}
|
||||
|
||||
public abstract Iterable<Site> findSitesByName(final String siteName);
|
||||
|
||||
public abstract void addSite(final Site site);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
<version>GIT-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.auto.value</groupId>
|
||||
<artifactId>auto-value</artifactId>
|
||||
<version>1.0-rc1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- TESTING -->
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
|
||||
@@ -4,6 +4,7 @@ import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
||||
|
||||
import com.lyndir.masterpassword.*;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Instant;
|
||||
@@ -17,7 +18,8 @@ public class MPSite {
|
||||
public static final MPSiteType DEFAULT_TYPE = MPSiteType.GeneratedLong;
|
||||
public static final int DEFAULT_COUNTER = 1;
|
||||
|
||||
private int mpVersion;
|
||||
private final MPUser user;
|
||||
private int mpVersion;
|
||||
private Instant lastUsed;
|
||||
private String siteName;
|
||||
private MPSiteType siteType;
|
||||
@@ -25,11 +27,12 @@ public class MPSite {
|
||||
private int uses;
|
||||
private String loginName;
|
||||
|
||||
public MPSite(final String siteName) {
|
||||
this( siteName, DEFAULT_TYPE, DEFAULT_COUNTER );
|
||||
public MPSite(final MPUser user, final String siteName) {
|
||||
this( user, siteName, DEFAULT_TYPE, DEFAULT_COUNTER );
|
||||
}
|
||||
|
||||
public MPSite(final String siteName, final MPSiteType siteType, final int siteCounter) {
|
||||
public MPSite(final MPUser user, final String siteName, final MPSiteType siteType, final int siteCounter) {
|
||||
this.user = user;
|
||||
this.mpVersion = MasterKey.ALGORITHM;
|
||||
this.lastUsed = new Instant();
|
||||
this.siteName = siteName;
|
||||
@@ -37,8 +40,9 @@ public class MPSite {
|
||||
this.siteCounter = siteCounter;
|
||||
}
|
||||
|
||||
protected MPSite(final int mpVersion, final Instant lastUsed, final String siteName, final MPSiteType siteType, final int siteCounter,
|
||||
final int uses, final String loginName, final String importContent) {
|
||||
protected MPSite(final MPUser user, final int mpVersion, final Instant lastUsed, final String siteName, final MPSiteType siteType, final int siteCounter,
|
||||
final int uses, final String loginName, final String importContent) {
|
||||
this.user = user;
|
||||
this.mpVersion = mpVersion;
|
||||
this.lastUsed = lastUsed;
|
||||
this.siteName = siteName;
|
||||
@@ -56,6 +60,10 @@ public class MPSite {
|
||||
return masterKey.encode( siteName, siteType, siteCounter, variant, context );
|
||||
}
|
||||
|
||||
public MPUser getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String exportContent() {
|
||||
return null;
|
||||
@@ -73,8 +81,9 @@ public class MPSite {
|
||||
return lastUsed;
|
||||
}
|
||||
|
||||
public void setLastUsed(final Instant lastUsed) {
|
||||
this.lastUsed = lastUsed;
|
||||
public void updateLastUsed() {
|
||||
lastUsed = new Instant();
|
||||
user.updateLastUsed();
|
||||
}
|
||||
|
||||
public String getSiteName() {
|
||||
@@ -116,4 +125,19 @@ public class MPSite {
|
||||
public void setLoginName(final String loginName) {
|
||||
this.loginName = loginName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return this == obj || obj instanceof MPSite && Objects.equals( siteName, ((MPSite) obj).siteName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( siteName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strf( "{MPSite: %s}", siteName );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package com.lyndir.masterpassword.model;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 14-12-07
|
||||
*/
|
||||
@@ -14,4 +19,19 @@ public class MPSiteResult {
|
||||
public MPSite getSite() {
|
||||
return site;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return this == obj || obj instanceof MPSiteResult && Objects.equals( site, ((MPSiteResult) obj).site );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( site );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strf( "{MPSiteResult: %s}", site );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
@@ -123,7 +122,8 @@ public class MPSiteUnmarshaller {
|
||||
MPSite site;
|
||||
switch (importFormat) {
|
||||
case 0:
|
||||
site = new MPSite( ConversionUtils.toIntegerNN( siteMatcher.group( 4 ).replace( ":", "" ) ), //
|
||||
site = new MPSite( user, //
|
||||
ConversionUtils.toIntegerNN( siteMatcher.group( 4 ).replace( ":", "" ) ), //
|
||||
rfc3339.parseDateTime( siteMatcher.group( 1 ) ).toInstant(), //
|
||||
siteMatcher.group( 5 ), //
|
||||
MPSiteType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ),
|
||||
@@ -134,7 +134,8 @@ public class MPSiteUnmarshaller {
|
||||
break;
|
||||
|
||||
case 1:
|
||||
site = new MPSite( ConversionUtils.toIntegerNN( siteMatcher.group( 4 ).replace( ":", "" ) ), //
|
||||
site = new MPSite( user, //
|
||||
ConversionUtils.toIntegerNN( siteMatcher.group( 4 ).replace( ":", "" ) ), //
|
||||
rfc3339.parseDateTime( siteMatcher.group( 1 ) ).toInstant(), //
|
||||
siteMatcher.group( 7 ), //
|
||||
MPSiteType.forType( ConversionUtils.toIntegerNN( siteMatcher.group( 3 ) ) ),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.lyndir.masterpassword.model;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||
@@ -11,7 +13,7 @@ import org.joda.time.*;
|
||||
/**
|
||||
* @author lhunath, 14-12-07
|
||||
*/
|
||||
public class MPUser {
|
||||
public class MPUser implements Comparable<MPUser> {
|
||||
|
||||
private final String fullName;
|
||||
private final Collection<MPSite> sites = Sets.newHashSet();
|
||||
@@ -98,4 +100,28 @@ public class MPUser {
|
||||
public Iterable<MPSite> getSites() {
|
||||
return sites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return this == obj || obj instanceof MPUser && Objects.equals( fullName, ((MPUser) obj).fullName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode( fullName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return strf( "{MPUser: %s}", fullName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final MPUser o) {
|
||||
int comparison = lastUsed.compareTo( o.lastUsed );
|
||||
if (comparison == 0)
|
||||
comparison = fullName.compareTo( o.fullName );
|
||||
|
||||
return comparison;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,17 @@ public class MPUserFileManager extends MPUserManager {
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private static final Logger logger = Logger.get( MPUserFileManager.class );
|
||||
private static final MPUserFileManager instance = create( new File( System.getProperty( "user.home" ), ".mpwrc" ) );
|
||||
private static final File mpwd = new File( System.getProperty( "user.home" ), ".mpw.d" );
|
||||
private static final MPUserFileManager instance;
|
||||
|
||||
static {
|
||||
File mpwrc = new File( System.getProperty( "user.home" ), ".mpwrc" );
|
||||
if (mpwrc.exists() && !mpwd.exists())
|
||||
if (!mpwrc.renameTo( mpwd ))
|
||||
logger.err( "Couldn't migrate: %s -> %s", mpwrc, mpwd );
|
||||
|
||||
instance = create( mpwd );
|
||||
}
|
||||
|
||||
private final File userFilesDirectory;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.lyndir.masterpassword.model;
|
||||
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@@ -23,12 +22,7 @@ public abstract class MPUserManager {
|
||||
}
|
||||
|
||||
public SortedSet<MPUser> getUsers() {
|
||||
return FluentIterable.from( usersByName.values() ).toSortedSet( new Comparator<MPUser>() {
|
||||
@Override
|
||||
public int compare(final MPUser user1, final MPUser user2) {
|
||||
return user1.getLastUsed().compareTo( user2.getLastUsed() );
|
||||
}
|
||||
} );
|
||||
return FluentIterable.from( usersByName.values() ).toSortedSet( Ordering.natural() );
|
||||
}
|
||||
|
||||
public void addUser(final MPUser user) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.lyndir.lhunath</groupId>
|
||||
<artifactId>lyndir</artifactId>
|
||||
<version>1.18</version>
|
||||
<version>1.20</version>
|
||||
</parent>
|
||||
|
||||
<name>Master Password</name>
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
#import "MPStoredSiteEntity.h"
|
||||
#import "MPGeneratedSiteEntity.h"
|
||||
#import "MPSiteQuestionEntity.h"
|
||||
#import "mpw-algorithm.h"
|
||||
|
||||
#define MPAlgorithmDefaultVersion 2
|
||||
#define MPAlgorithmDefaultVersion MPAlgorithmVersionCurrent
|
||||
#define MPAlgorithmDefault MPAlgorithmForVersion(MPAlgorithmDefaultVersion)
|
||||
|
||||
id<MPAlgorithm> MPAlgorithmForVersion(NSUInteger version);
|
||||
@@ -43,7 +44,7 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
|
||||
@protocol MPAlgorithm<NSObject>
|
||||
|
||||
@required
|
||||
- (NSUInteger)version;
|
||||
- (MPAlgorithmVersion)version;
|
||||
- (BOOL)tryMigrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc;
|
||||
- (BOOL)tryMigrateSite:(MPSiteEntity *)site explicit:(BOOL)explicit;
|
||||
|
||||
@@ -51,7 +52,6 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
|
||||
- (MPKey *)keyFromKeyData:(NSData *)keyData;
|
||||
- (NSData *)keyIDForKeyData:(NSData *)keyData;
|
||||
|
||||
- (NSString *)scopeForVariant:(MPSiteVariant)variant;
|
||||
- (NSString *)nameOfType:(MPSiteType)type;
|
||||
- (NSString *)shortNameOfType:(MPSiteType)type;
|
||||
- (NSString *)classNameOfType:(MPSiteType)type;
|
||||
|
||||
@@ -18,11 +18,4 @@
|
||||
#import "MPAlgorithm.h"
|
||||
|
||||
@interface MPAlgorithmV0 : NSObject<MPAlgorithm>
|
||||
|
||||
- (NSDictionary *)allCiphers;
|
||||
- (NSArray *)ciphersForType:(MPSiteType)type;
|
||||
- (NSArray *)cipherClasses;
|
||||
- (NSArray *)cipherClassCharacters;
|
||||
- (NSString *)charactersForCipherClass:(NSString *)cipherClass;
|
||||
|
||||
@end
|
||||
|
||||
@@ -19,16 +19,11 @@
|
||||
#import "MPEntities.h"
|
||||
#import "MPAppDelegate_Shared.h"
|
||||
#import "MPAppDelegate_InApp.h"
|
||||
#import "MPSiteQuestionEntity.h"
|
||||
#import "mpw-util.h"
|
||||
#import "mpw-types.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_dkLen 64
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
/* An AMD HD 7970 calculates 2495M SHA-1 hashes per second at a cost of ~350$ per GPU */
|
||||
#define CRACKING_PER_SECOND 2495000000UL
|
||||
#define CRACKING_PRICE 350
|
||||
@@ -53,9 +48,9 @@
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
- (NSUInteger)version {
|
||||
- (MPAlgorithmVersion)version {
|
||||
|
||||
return 0;
|
||||
return MPAlgorithmVersion0;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
@@ -112,21 +107,13 @@
|
||||
|
||||
- (MPKey *)keyForPassword:(NSString *)password ofUserNamed:(NSString *)userName {
|
||||
|
||||
uint32_t nuserNameLength = htonl( userName.length );
|
||||
NSDate *start = [NSDate date];
|
||||
NSData *keyData = [PearlSCrypt deriveKeyWithLength:MP_dkLen fromPassword:[password dataUsingEncoding:NSUTF8StringEncoding]
|
||||
usingSalt:[NSData dataByConcatenatingDatas:
|
||||
[@"com.lyndir.masterpassword" dataUsingEncoding:NSUTF8StringEncoding],
|
||||
[NSData dataWithBytes:&nuserNameLength
|
||||
length:sizeof( nuserNameLength )],
|
||||
[userName dataUsingEncoding:NSUTF8StringEncoding],
|
||||
nil] N:MP_N r:MP_r p:MP_p];
|
||||
|
||||
MPKey *key = [self keyFromKeyData:keyData];
|
||||
trc( @"User: %@, password: %@ derives to key ID: %@ (took %0.2fs)", userName, password, [key.keyID encodeHex],
|
||||
uint8_t const *masterKeyBytes = mpw_masterKeyForUser( userName.UTF8String, password.UTF8String, [self version] );
|
||||
MPKey *masterKey = [self keyFromKeyData:[NSData dataWithBytes:masterKeyBytes length:MP_dkLen]];
|
||||
mpw_free( masterKeyBytes, MP_dkLen );
|
||||
trc( @"User: %@, password: %@ derives to key ID: %@ (took %0.2fs)", userName, password, [masterKey.keyID encodeHex],
|
||||
-[start timeIntervalSinceNow] );
|
||||
|
||||
return key;
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
- (MPKey *)keyFromKeyData:(NSData *)keyData {
|
||||
@@ -136,21 +123,7 @@
|
||||
|
||||
- (NSData *)keyIDForKeyData:(NSData *)keyData {
|
||||
|
||||
return [keyData hashWith:MP_hash];
|
||||
}
|
||||
|
||||
- (NSString *)scopeForVariant:(MPSiteVariant)variant {
|
||||
|
||||
switch (variant) {
|
||||
case MPSiteVariantPassword:
|
||||
return @"com.lyndir.masterpassword";
|
||||
case MPSiteVariantLogin:
|
||||
return @"com.lyndir.masterpassword.login";
|
||||
case MPSiteVariantAnswer:
|
||||
return @"com.lyndir.masterpassword.answer";
|
||||
}
|
||||
|
||||
Throw( @"Unsupported variant: %ld", (long)variant );
|
||||
return [keyData hashWith:PearlHashSHA256];
|
||||
}
|
||||
|
||||
- (NSString *)nameOfType:(MPSiteType)type {
|
||||
@@ -327,40 +300,6 @@
|
||||
return previousType;
|
||||
}
|
||||
|
||||
- (NSDictionary *)allCiphers {
|
||||
|
||||
static NSDictionary *ciphers = nil;
|
||||
static dispatch_once_t once = 0;
|
||||
dispatch_once( &once, ^{
|
||||
ciphers = [NSDictionary dictionaryWithContentsOfURL:
|
||||
[[NSBundle mainBundle] URLForResource:@"ciphers" withExtension:@"plist"]];
|
||||
} );
|
||||
|
||||
return ciphers;
|
||||
}
|
||||
|
||||
- (NSArray *)ciphersForType:(MPSiteType)type {
|
||||
|
||||
NSString *typeClass = [self classNameOfType:type];
|
||||
NSString *typeName = [self nameOfType:type];
|
||||
return [[[self allCiphers] valueForKey:typeClass] valueForKey:typeName];
|
||||
}
|
||||
|
||||
- (NSArray *)cipherClasses {
|
||||
|
||||
return [[[self allCiphers] valueForKey:@"MPCharacterClasses"] allKeys];
|
||||
}
|
||||
|
||||
- (NSArray *)cipherClassCharacters {
|
||||
|
||||
return [[[self allCiphers] valueForKey:@"MPCharacterClasses"] allValues];
|
||||
}
|
||||
|
||||
- (NSString *)charactersForCipherClass:(NSString *)cipherClass {
|
||||
|
||||
return [NSNullToNil( [NSNullToNil( [[self allCiphers] valueForKey:@"MPCharacterClasses"] ) valueForKey:cipherClass] ) copy];
|
||||
}
|
||||
|
||||
- (NSString *)generateLoginForSiteNamed:(NSString *)name usingKey:(MPKey *)key {
|
||||
|
||||
return [self generateContentForSiteNamed:name ofType:MPSiteTypeGeneratedName withCounter:1
|
||||
@@ -383,44 +322,10 @@
|
||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
|
||||
variant:(MPSiteVariant)variant context:(NSString *)context usingKey:(MPKey *)key {
|
||||
|
||||
// Determine the seed whose bytes will be used for calculating a password
|
||||
uint32_t ncounter = htonl( counter ), nnameLength = htonl( name.length ), ncontextLength = htonl( context.length );
|
||||
NSData *counterBytes = [NSData dataWithBytes:&ncounter length:sizeof( ncounter )];
|
||||
NSData *nameLengthBytes = [NSData dataWithBytes:&nnameLength length:sizeof( nnameLength )];
|
||||
NSData *contextLengthBytes = [NSData dataWithBytes:&ncontextLength length:sizeof( ncontextLength )];
|
||||
NSString *scope = [self scopeForVariant:variant];
|
||||
trc( @"seed from: hmac-sha256(%@, %@ | %@ | %@ | %@ | %@)",
|
||||
[[key keyID] encodeHex], scope, [nameLengthBytes encodeHex], name, [counterBytes encodeHex], context );
|
||||
NSData *seed = [[NSData dataByConcatenatingDatas:
|
||||
[scope dataUsingEncoding:NSUTF8StringEncoding],
|
||||
nameLengthBytes,
|
||||
[name dataUsingEncoding:NSUTF8StringEncoding],
|
||||
counterBytes,
|
||||
context? contextLengthBytes: nil,
|
||||
[context dataUsingEncoding:NSUTF8StringEncoding],
|
||||
nil]
|
||||
hmacWith:PearlHashSHA256 key:key.keyData];
|
||||
trc( @"seed is: %@", [seed encodeHex] );
|
||||
const char *seedBytes = seed.bytes;
|
||||
|
||||
// Determine the cipher from the first seed byte.
|
||||
NSAssert( [seed length], @"Missing seed." );
|
||||
NSArray *typeCiphers = [self ciphersForType:type];
|
||||
NSString *cipher = typeCiphers[htons( seedBytes[0] ) % [typeCiphers count]];
|
||||
trc( @"type %@ (%lu), ciphers: %@, selected: %@", [self nameOfType:type], (unsigned long)type, typeCiphers, cipher );
|
||||
|
||||
// Encode the content, character by character, using subsequent seed bytes and the cipher.
|
||||
NSAssert( [seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher." );
|
||||
NSMutableString *content = [NSMutableString stringWithCapacity:[cipher length]];
|
||||
for (NSUInteger c = 0; c < [cipher length]; ++c) {
|
||||
uint16_t keyByte = htons( seedBytes[c + 1] );
|
||||
NSString *cipherClass = [cipher substringWithRange:NSMakeRange( c, 1 )];
|
||||
NSString *cipherClassCharacters = [self charactersForCipherClass:cipherClass];
|
||||
NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange( keyByte % [cipherClassCharacters length], 1 )];
|
||||
|
||||
trc( @"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character );
|
||||
[content appendString:character];
|
||||
}
|
||||
char const *contentBytes = mpw_passwordForSite( key.keyData.bytes, name.UTF8String, type, (uint32_t)counter,
|
||||
variant, context.UTF8String, [self version] );
|
||||
NSString *content = [NSString stringWithCString:contentBytes encoding:NSUTF8StringEncoding];
|
||||
mpw_freeString( contentBytes );
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -793,6 +698,8 @@
|
||||
|
||||
- (NSString *)decryptContent:(NSData *)encryptedContent usingKey:(MPKey *)key {
|
||||
|
||||
if (!key)
|
||||
return nil;
|
||||
NSData *decryptedContent = nil;
|
||||
if ([encryptedContent length])
|
||||
decryptedContent = [encryptedContent decryptWithSymmetricKey:[key subKeyOfLength:PearlCryptKeySize].keyData padding:YES];
|
||||
@@ -806,21 +713,23 @@
|
||||
|
||||
if (!type)
|
||||
return NO;
|
||||
NSArray *ciphers = [self ciphersForType:type];
|
||||
if (!ciphers)
|
||||
size_t count = 0;
|
||||
const char **templates = mpw_templatesForType( type, &count );
|
||||
if (!templates)
|
||||
return NO;
|
||||
|
||||
BIGNUM *permutations = BN_new(), *cipherPermutations = BN_new();
|
||||
for (NSString *cipher in ciphers) {
|
||||
BN_one( cipherPermutations );
|
||||
BIGNUM *permutations = BN_new(), *templatePermutations = BN_new();
|
||||
for (size_t t = 0; t < count; ++t) {
|
||||
const char *template = templates[t];
|
||||
BN_one( templatePermutations );
|
||||
|
||||
for (NSUInteger c = 0; c < [cipher length]; ++c)
|
||||
BN_mul_word( cipherPermutations,
|
||||
(BN_ULONG)[[self charactersForCipherClass:[cipher substringWithRange:NSMakeRange( c, 1 )]] length] );
|
||||
for (NSUInteger c = 0; c < strlen( template ); ++c)
|
||||
BN_mul_word( templatePermutations,
|
||||
(BN_ULONG)strlen( mpw_charactersInClass( template[c] ) ) );
|
||||
|
||||
BN_add( permutations, permutations, cipherPermutations );
|
||||
BN_add( permutations, permutations, templatePermutations );
|
||||
}
|
||||
BN_free( cipherPermutations );
|
||||
BN_free( templatePermutations );
|
||||
|
||||
return [self timeToCrack:timeToCrack permutations:permutations forAttacker:attacker];
|
||||
}
|
||||
@@ -830,25 +739,21 @@
|
||||
BIGNUM *permutations = BN_new();
|
||||
BN_one( permutations );
|
||||
|
||||
NSMutableString *cipher = [NSMutableString new];
|
||||
for (NSUInteger c = 0; c < [password length]; ++c) {
|
||||
NSString *passwordCharacter = [password substringWithRange:NSMakeRange( c, 1 )];
|
||||
const char passwordCharacter = [password substringWithRange:NSMakeRange( c, 1 )].UTF8String[0];
|
||||
|
||||
unsigned int characterEntropy = 0;
|
||||
for (NSString *cipherClass in @[ @"v", @"c", @"a", @"x" ]) {
|
||||
NSString *charactersForClass = [self charactersForCipherClass:cipherClass];
|
||||
for (NSString *characterClass in @[ @"v", @"c", @"a", @"x" ]) {
|
||||
char const *charactersForClass = mpw_charactersInClass( characterClass.UTF8String[0] );
|
||||
|
||||
if ([charactersForClass rangeOfString:passwordCharacter].location != NSNotFound) {
|
||||
if (strchr( charactersForClass, passwordCharacter )) {
|
||||
// Found class for password character.
|
||||
characterEntropy = (BN_ULONG)[charactersForClass length];
|
||||
[cipher appendString:cipherClass];
|
||||
characterEntropy = (BN_ULONG)strlen(charactersForClass);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!characterEntropy) {
|
||||
[cipher appendString:@"b"];
|
||||
if (!characterEntropy)
|
||||
characterEntropy = 256 /* a byte */;
|
||||
}
|
||||
|
||||
BN_mul_word( permutations, characterEntropy );
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
|
||||
@implementation MPAlgorithmV1
|
||||
|
||||
- (NSUInteger)version {
|
||||
- (MPAlgorithmVersion)version {
|
||||
|
||||
return 1;
|
||||
return MPAlgorithmVersion1;
|
||||
}
|
||||
|
||||
- (BOOL)tryMigrateSite:(MPSiteEntity *)site explicit:(BOOL)explicit {
|
||||
@@ -45,49 +45,4 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
|
||||
variant:(MPSiteVariant)variant context:(NSString *)context usingKey:(MPKey *)key {
|
||||
|
||||
// Determine the seed whose bytes will be used for calculating a password
|
||||
uint32_t ncounter = htonl( counter ), nnameLength = htonl( name.length ), ncontextLength = htonl( context.length );
|
||||
NSData *counterBytes = [NSData dataWithBytes:&ncounter length:sizeof( ncounter )];
|
||||
NSData *nameLengthBytes = [NSData dataWithBytes:&nnameLength length:sizeof( nnameLength )];
|
||||
NSData *contextLengthBytes = [NSData dataWithBytes:&ncontextLength length:sizeof( ncontextLength )];
|
||||
NSString *scope = [self scopeForVariant:variant];
|
||||
trc( @"seed from: hmac-sha256(%@, %@ | %@ | %@ | %@)",
|
||||
[[key keyID] encodeHex], scope, [nameLengthBytes encodeHex], name, [counterBytes encodeHex] );
|
||||
NSData *seed = [[NSData dataByConcatenatingDatas:
|
||||
[scope dataUsingEncoding:NSUTF8StringEncoding],
|
||||
nameLengthBytes,
|
||||
[name dataUsingEncoding:NSUTF8StringEncoding],
|
||||
counterBytes,
|
||||
context? contextLengthBytes: nil,
|
||||
[context dataUsingEncoding:NSUTF8StringEncoding],
|
||||
nil]
|
||||
hmacWith:PearlHashSHA256 key:key.keyData];
|
||||
trc( @"seed is: %@", [seed encodeHex] );
|
||||
const unsigned char *seedBytes = seed.bytes;
|
||||
|
||||
// Determine the cipher from the first seed byte.
|
||||
NSAssert( [seed length], @"Missing seed." );
|
||||
NSArray *typeCiphers = [self ciphersForType:type];
|
||||
NSString *cipher = typeCiphers[seedBytes[0] % [typeCiphers count]];
|
||||
trc( @"type %@ (%lu), ciphers: %@, selected: %@", [self nameOfType:type], (unsigned long)type, typeCiphers, cipher );
|
||||
|
||||
// Encode the content, character by character, using subsequent seed bytes and the cipher.
|
||||
NSAssert( [seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher." );
|
||||
NSMutableString *content = [NSMutableString stringWithCapacity:[cipher length]];
|
||||
for (NSUInteger c = 0; c < [cipher length]; ++c) {
|
||||
uint16_t keyByte = seedBytes[c + 1];
|
||||
NSString *cipherClass = [cipher substringWithRange:NSMakeRange( c, 1 )];
|
||||
NSString *cipherClassCharacters = [self charactersForCipherClass:cipherClass];
|
||||
NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange( keyByte % [cipherClassCharacters length], 1 )];
|
||||
|
||||
trc( @"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character );
|
||||
[content appendString:character];
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAlgorithmV1
|
||||
// MPAlgorithmV2
|
||||
//
|
||||
// Created by Maarten Billemont on 17/07/12.
|
||||
// Copyright 2012 lhunath (Maarten Billemont). All rights reserved.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAlgorithmV1
|
||||
// MPAlgorithmV2
|
||||
//
|
||||
// Created by Maarten Billemont on 17/07/12.
|
||||
// Copyright 2012 lhunath (Maarten Billemont). All rights reserved.
|
||||
@@ -21,9 +21,9 @@
|
||||
|
||||
@implementation MPAlgorithmV2
|
||||
|
||||
- (NSUInteger)version {
|
||||
- (MPAlgorithmVersion)version {
|
||||
|
||||
return 2;
|
||||
return MPAlgorithmVersion2;
|
||||
}
|
||||
|
||||
- (BOOL)tryMigrateSite:(MPSiteEntity *)site explicit:(BOOL)explicit {
|
||||
@@ -46,52 +46,4 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString *)generateContentForSiteNamed:(NSString *)name ofType:(MPSiteType)type withCounter:(NSUInteger)counter
|
||||
variant:(MPSiteVariant)variant context:(NSString *)context usingKey:(MPKey *)key {
|
||||
|
||||
// Determine the seed whose bytes will be used for calculating a password
|
||||
NSData *nameBytes = [name dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSData *contextBytes = [context dataUsingEncoding:NSUTF8StringEncoding];
|
||||
uint32_t ncounter = htonl( counter ), nnameLength = htonl( nameBytes.length ), ncontextLength = htonl( contextBytes.length );
|
||||
NSData *counterBytes = [NSData dataWithBytes:&ncounter length:sizeof( ncounter )];
|
||||
NSData *nameLengthBytes = [NSData dataWithBytes:&nnameLength length:sizeof( nnameLength )];
|
||||
NSData *contextLengthBytes = [NSData dataWithBytes:&ncontextLength length:sizeof( ncontextLength )];
|
||||
NSString *scope = [self scopeForVariant:variant];
|
||||
NSData *scopeBytes = [scope dataUsingEncoding:NSUTF8StringEncoding];
|
||||
trc( @"seed from: hmac-sha256(%@, %@ | %@ | %@ | %@)",
|
||||
[[key keyID] encodeHex], scope, [nameLengthBytes encodeHex], name, [counterBytes encodeHex] );
|
||||
NSData *seed = [[NSData dataByConcatenatingDatas:
|
||||
scopeBytes,
|
||||
nameLengthBytes,
|
||||
nameBytes,
|
||||
counterBytes,
|
||||
context? contextLengthBytes: nil,
|
||||
contextBytes,
|
||||
nil]
|
||||
hmacWith:PearlHashSHA256 key:key.keyData];
|
||||
trc( @"seed is: %@", [seed encodeHex] );
|
||||
const unsigned char *seedBytes = seed.bytes;
|
||||
|
||||
// Determine the cipher from the first seed byte.
|
||||
NSAssert( [seed length], @"Missing seed." );
|
||||
NSArray *typeCiphers = [self ciphersForType:type];
|
||||
NSString *cipher = typeCiphers[seedBytes[0] % [typeCiphers count]];
|
||||
trc( @"type %@ (%lu), ciphers: %@, selected: %@", [self nameOfType:type], (unsigned long)type, typeCiphers, cipher );
|
||||
|
||||
// Encode the content, character by character, using subsequent seed bytes and the cipher.
|
||||
NSAssert( [seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher." );
|
||||
NSMutableString *content = [NSMutableString stringWithCapacity:[cipher length]];
|
||||
for (NSUInteger c = 0; c < [cipher length]; ++c) {
|
||||
uint16_t keyByte = seedBytes[c + 1];
|
||||
NSString *cipherClass = [cipher substringWithRange:NSMakeRange( c, 1 )];
|
||||
NSString *cipherClassCharacters = [self charactersForCipherClass:cipherClass];
|
||||
NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange( keyByte % [cipherClassCharacters length], 1 )];
|
||||
|
||||
trc( @"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character );
|
||||
[content appendString:character];
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
21
MasterPassword/ObjC/MPAlgorithmV3.h
Normal file
21
MasterPassword/ObjC/MPAlgorithmV3.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAlgorithmV3
|
||||
//
|
||||
// Created by Maarten Billemont on 13/01/15.
|
||||
// Copyright 2015 lhunath (Maarten Billemont). All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAlgorithmV2.h"
|
||||
|
||||
@interface MPAlgorithmV3 : MPAlgorithmV2
|
||||
@end
|
||||
48
MasterPassword/ObjC/MPAlgorithmV3.m
Normal file
48
MasterPassword/ObjC/MPAlgorithmV3.m
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAlgorithmV3
|
||||
//
|
||||
// Created by Maarten Billemont on 13/01/15.
|
||||
// Copyright 2015 lhunath (Maarten Billemont). All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPAlgorithmV3.h"
|
||||
#import "MPEntities.h"
|
||||
|
||||
@implementation MPAlgorithmV3
|
||||
|
||||
- (MPAlgorithmVersion)version {
|
||||
|
||||
return MPAlgorithmVersion3;
|
||||
}
|
||||
|
||||
- (BOOL)tryMigrateSite:(MPSiteEntity *)site explicit:(BOOL)explicit {
|
||||
|
||||
if (site.version != [self version] - 1)
|
||||
// Only migrate from previous version.
|
||||
return NO;
|
||||
|
||||
if (!explicit) {
|
||||
if (site.type & MPSiteTypeClassGenerated && site.name.length != [site.name dataUsingEncoding:NSUTF8StringEncoding].length) {
|
||||
// This migration requires explicit permission for types of the generated class.
|
||||
site.requiresExplicitMigration = YES;
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply migration.
|
||||
site.requiresExplicitMigration = NO;
|
||||
site.version = [self version];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -611,7 +611,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
}
|
||||
if (!headerEnded)
|
||||
continue;
|
||||
if (!importKeyID || ![importUserName length])
|
||||
if (![importUserName length])
|
||||
return MPImportResultMalformedInput;
|
||||
if (![importedSiteLine length])
|
||||
continue;
|
||||
@@ -689,12 +689,11 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
if (user && ![userKey.keyID isEqualToData:user.keyID])
|
||||
return MPImportResultInvalidPassword;
|
||||
__block MPKey *importKey = userKey;
|
||||
if (![importKey.keyID isEqualToData:importKeyID])
|
||||
if (importKeyID && ![importKey.keyID isEqualToData:importKeyID])
|
||||
importKey = [importAlgorithm keyForPassword:askImportPassword( importUserName ) ofUserNamed:importUserName];
|
||||
if (![importKey.keyID isEqualToData:importKeyID])
|
||||
if (importKeyID && ![importKey.keyID isEqualToData:importKeyID])
|
||||
return MPImportResultInvalidPassword;
|
||||
|
||||
|
||||
// Delete existing sites.
|
||||
if (sitesToDelete.count)
|
||||
[sitesToDelete enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
|
||||
@@ -711,7 +710,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
||||
else {
|
||||
user = [MPUserEntity insertNewObjectInContext:context];
|
||||
user.name = importUserName;
|
||||
user.keyID = importKeyID;
|
||||
user.keyID = [userKey keyID];
|
||||
if (importAvatar != NSNotFound)
|
||||
user.avatar = importAvatar;
|
||||
dbg( @"Created User: %@", [user debugDescription] );
|
||||
|
||||
@@ -6,54 +6,15 @@
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPKey.h"
|
||||
NSString *const MPErrorDomain;
|
||||
|
||||
typedef NS_ENUM( NSUInteger, MPSiteTypeClass ) {
|
||||
/** Generate the password. */
|
||||
MPSiteTypeClassGenerated = 1 << 4,
|
||||
/** Store the password. */
|
||||
MPSiteTypeClassStored = 1 << 5,
|
||||
};
|
||||
NSString *const MPSignedInNotification;
|
||||
NSString *const MPSignedOutNotification;
|
||||
NSString *const MPKeyForgottenNotification;
|
||||
NSString *const MPSiteUpdatedNotification;
|
||||
NSString *const MPCheckConfigNotification;
|
||||
NSString *const MPSitesImportedNotification;
|
||||
NSString *const MPFoundInconsistenciesNotification;
|
||||
|
||||
typedef NS_ENUM( NSUInteger, MPSiteVariant ) {
|
||||
/** Generate the password. */
|
||||
MPSiteVariantPassword,
|
||||
/** Generate the login name. */
|
||||
MPSiteVariantLogin,
|
||||
/** Generate a security answer. */
|
||||
MPSiteVariantAnswer,
|
||||
};
|
||||
|
||||
typedef NS_ENUM( NSUInteger, MPSiteFeature ) {
|
||||
/** Export the key-protected content data. */
|
||||
MPSiteFeatureExportContent = 1 << 10,
|
||||
/** Never export content. */
|
||||
MPSiteFeatureDevicePrivate = 1 << 11,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MPSiteType) {
|
||||
MPSiteTypeGeneratedMaximum = 0x0 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedLong = 0x1 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedMedium = 0x2 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedBasic = 0x4 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedShort = 0x3 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedPIN = 0x5 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedName = 0xE | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedPhrase = 0xF | MPSiteTypeClassGenerated | 0x0,
|
||||
|
||||
MPSiteTypeStoredPersonal = 0x0 | MPSiteTypeClassStored | MPSiteFeatureExportContent,
|
||||
MPSiteTypeStoredDevicePrivate = 0x1 | MPSiteTypeClassStored | MPSiteFeatureDevicePrivate,
|
||||
};
|
||||
|
||||
#define MPErrorDomain @"MPErrorDomain"
|
||||
|
||||
#define MPSignedInNotification @"MPSignedInNotification"
|
||||
#define MPSignedOutNotification @"MPSignedOutNotification"
|
||||
#define MPKeyForgottenNotification @"MPKeyForgottenNotification"
|
||||
#define MPSiteUpdatedNotification @"MPSiteUpdatedNotification"
|
||||
#define MPCheckConfigNotification @"MPCheckConfigNotification"
|
||||
#define MPSitesImportedNotification @"MPSitesImportedNotification"
|
||||
#define MPFoundInconsistenciesNotification @"MPFoundInconsistenciesNotification"
|
||||
|
||||
#define MPSitesImportedNotificationUserKey @"MPSitesImportedNotificationUserKey"
|
||||
#define MPInconsistenciesFixResultUserKey @"MPInconsistenciesFixResultUserKey"
|
||||
NSString *const MPSitesImportedNotificationUserKey;
|
||||
NSString *const MPInconsistenciesFixResultUserKey;
|
||||
|
||||
22
MasterPassword/ObjC/MPTypes.m
Normal file
22
MasterPassword/ObjC/MPTypes.m
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// MPTypes.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 02/01/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPTypes.h"
|
||||
|
||||
NSString *const MPErrorDomain = @"MPErrorDomain";
|
||||
|
||||
NSString *const MPSignedInNotification = @"MPSignedInNotification";
|
||||
NSString *const MPSignedOutNotification = @"MPSignedOutNotification";
|
||||
NSString *const MPKeyForgottenNotification = @"MPKeyForgottenNotification";
|
||||
NSString *const MPSiteUpdatedNotification = @"MPSiteUpdatedNotification";
|
||||
NSString *const MPCheckConfigNotification = @"MPCheckConfigNotification";
|
||||
NSString *const MPSitesImportedNotification = @"MPSitesImportedNotification";
|
||||
NSString *const MPFoundInconsistenciesNotification = @"MPFoundInconsistenciesNotification";
|
||||
|
||||
NSString *const MPSitesImportedNotificationUserKey = @"MPSitesImportedNotificationUserKey";
|
||||
NSString *const MPInconsistenciesFixResultUserKey = @"MPInconsistenciesFixResultUserKey";
|
||||
@@ -58,6 +58,33 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
|
||||
#ifdef CRASHLYTICS
|
||||
NSString *crashlyticsAPIKey = [self crashlyticsAPIKey];
|
||||
if ([crashlyticsAPIKey length]) {
|
||||
inf(@"Initializing Crashlytics");
|
||||
#if defined (DEBUG) || defined (ADHOC)
|
||||
[Crashlytics sharedInstance].debugMode = YES;
|
||||
#endif
|
||||
[Crashlytics setUserIdentifier:[PearlKeyChain deviceIdentifier]];
|
||||
[Crashlytics setObjectValue:[PearlKeyChain deviceIdentifier] forKey:@"deviceIdentifier"];
|
||||
[Crashlytics setUserName:@"Anonymous"];
|
||||
[Crashlytics setObjectValue:@"Anonymous" forKey:@"username"];
|
||||
[Crashlytics startWithAPIKey:crashlyticsAPIKey];
|
||||
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
||||
PearlLogLevel level = PearlLogLevelInfo;
|
||||
if ([[MPConfig get].sendInfo boolValue])
|
||||
level = PearlLogLevelDebug;
|
||||
|
||||
if (message.level >= level)
|
||||
CLSLog( @"%@", [message messageDescription] );
|
||||
|
||||
return YES;
|
||||
}];
|
||||
CLSLog( @"Crashlytics (%@) initialized for: %@ v%@.", //
|
||||
[Crashlytics sharedInstance].version, [PearlInfoPlist get].CFBundleName, [PearlInfoPlist get].CFBundleVersion );
|
||||
}
|
||||
#endif
|
||||
|
||||
// Setup delegates and listeners.
|
||||
[MPConfig get].delegate = self;
|
||||
__weak id weakSelf = self;
|
||||
@@ -224,6 +251,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
return;
|
||||
|
||||
NSURL *url = openPanel.URL;
|
||||
[openPanel close];
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
NSError *error;
|
||||
@@ -285,19 +313,19 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
case MPImportResultCancelled:
|
||||
break;
|
||||
case MPImportResultInternalError:
|
||||
[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Import failed because of an internal error."
|
||||
}]];
|
||||
}]] runModal];
|
||||
break;
|
||||
case MPImportResultMalformedInput:
|
||||
[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"The import doesn't look like a Master Password export."
|
||||
}]];
|
||||
}]] runModal];
|
||||
break;
|
||||
case MPImportResultInvalidPassword:
|
||||
[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Incorrect master password for the import sites."
|
||||
}]];
|
||||
}]] runModal];
|
||||
break;
|
||||
}
|
||||
} );
|
||||
@@ -362,7 +390,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Delete User"
|
||||
defaultButton:@"Delete" alternateButton:nil otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"This will delete %@ and all his sites.", self.activeUserForMainThread.name];
|
||||
informativeTextWithFormat:@"This will delete %@ and all their sites.", self.activeUserForMainThread.name];
|
||||
if ([alert runModal] != NSAlertDefaultReturn)
|
||||
return;
|
||||
|
||||
@@ -604,4 +632,25 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:NSStringFromSelector( configKey )];
|
||||
}
|
||||
|
||||
#pragma mark - Crashlytics
|
||||
|
||||
- (NSDictionary *)crashlyticsInfo {
|
||||
|
||||
static NSDictionary *crashlyticsInfo = nil;
|
||||
if (crashlyticsInfo == nil)
|
||||
crashlyticsInfo = [[NSDictionary alloc] initWithContentsOfURL:
|
||||
[[NSBundle mainBundle] URLForResource:@"Crashlytics" withExtension:@"plist"]];
|
||||
|
||||
return crashlyticsInfo;
|
||||
}
|
||||
|
||||
- (NSString *)crashlyticsAPIKey {
|
||||
|
||||
NSString *crashlyticsAPIKey = NSNullToNil( [[self crashlyticsInfo] valueForKeyPath:@"API Key"] );
|
||||
if (![crashlyticsAPIKey length])
|
||||
wrn( @"Crashlytics API key not set. Crash logs won't be recorded." );
|
||||
|
||||
return crashlyticsAPIKey;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
|
||||
[super windowDidLoad];
|
||||
|
||||
[self replaceFonts:self.window.contentView];
|
||||
|
||||
// [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:nil
|
||||
// queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
// [self fadeIn];
|
||||
@@ -95,6 +97,20 @@
|
||||
self.siteTable.controller = self;
|
||||
}
|
||||
|
||||
- (void)replaceFonts:(NSView *)view {
|
||||
|
||||
if (view.window.backingScaleFactor == 1)
|
||||
[view enumerateViews:^(NSView *subview, BOOL *stop, BOOL *recurse) {
|
||||
if ([subview respondsToSelector:@selector( setFont: )]) {
|
||||
NSFont *font = [(id)subview font];
|
||||
if ([font.fontName isEqualToString:@"HelveticaNeue-Thin"])
|
||||
[(id)subview setFont:[NSFont fontWithName:@"HelveticaNeue" matrix:font.matrix]];
|
||||
if ([font.fontName isEqualToString:@"HelveticaNeue-Light"])
|
||||
[(id)subview setFont:[NSFont fontWithName:@"HelveticaNeue" matrix:font.matrix]];
|
||||
}
|
||||
} recurse:YES];
|
||||
}
|
||||
|
||||
- (void)flagsChanged:(NSEvent *)theEvent {
|
||||
|
||||
BOOL alternatePressed = (theEvent.modifierFlags & NSAlternateKeyMask) != 0;
|
||||
@@ -186,6 +202,11 @@
|
||||
|
||||
#pragma mark - NSTableViewDelegate
|
||||
|
||||
- (void)tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row {
|
||||
|
||||
[self replaceFonts:rowView];
|
||||
}
|
||||
|
||||
#pragma mark - NSAlert
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
@@ -391,7 +412,7 @@
|
||||
NSArray *types = [site.algorithm allTypesStartingWith:MPSiteTypeGeneratedPIN];
|
||||
[self.passwordTypesMatrix renewRows:(NSInteger)[types count] columns:1];
|
||||
for (NSUInteger t = 0; t < [types count]; ++t) {
|
||||
MPSiteType type = [types[t] unsignedIntegerValue];
|
||||
MPSiteType type = (MPSiteType)[types[t] unsignedIntegerValue];
|
||||
NSString *title = [site.algorithm nameOfType:type];
|
||||
if (type & MPSiteTypeClassGenerated)
|
||||
title = [site.algorithm generatePasswordForSiteNamed:site.name ofType:type
|
||||
@@ -513,13 +534,13 @@
|
||||
NSMutableArray *fuzzyGroups = [NSMutableArray new];
|
||||
[fuzzyRE enumerateMatchesInString:queryString options:0 range:NSMakeRange( 0, queryString.length )
|
||||
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
|
||||
[fuzzyGroups addObject:[queryString substringWithRange:result.range] ];
|
||||
[fuzzyGroups addObject:[queryString substringWithRange:result.range]];
|
||||
}];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
|
||||
fetchRequest.sortDescriptors = @[ [[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO] ];
|
||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name LIKE[cd] %@) AND user == %@",
|
||||
queryPattern, queryPattern, [MPMacAppDelegate get].activeUserOID];
|
||||
queryPattern, queryPattern, [MPMacAppDelegate get].activeUserOID];
|
||||
|
||||
NSError *error = nil;
|
||||
NSArray *siteResults = [context executeFetchRequest:fetchRequest error:&error];
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6250" systemVersion="14A389" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6250"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="MPPasswordWindowController">
|
||||
@@ -26,7 +26,7 @@
|
||||
<windowCollectionBehavior key="collectionBehavior" transient="YES" ignoresCycle="YES" fullScreenAuxiliary="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="0.0" y="0.0" width="640" height="560"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="640" height="560"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
@@ -144,7 +144,7 @@
|
||||
</binding>
|
||||
</connections>
|
||||
</button>
|
||||
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="35" horizontalPageScroll="10" verticalLineScroll="35" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="Bme-XK-MMc" userLabel="Sites Table">
|
||||
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="35" horizontalPageScroll="10" verticalLineScroll="35" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="Bme-XK-MMc" userLabel="Sites Table">
|
||||
<rect key="frame" x="64" y="80" width="512" height="147"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="e11-59-xSS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="512" height="147"/>
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPSiteEntity.h"
|
||||
#import "MPAlgorithm.h"
|
||||
|
||||
@class MPSiteEntity;
|
||||
|
||||
@interface MPSiteModel : NSObject
|
||||
|
||||
@@ -8,12 +8,14 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
93D390C676DF52DA7E459F19 /* MPPasswordWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D9D0061FF1159998F06 /* MPPasswordWindow.m */; };
|
||||
93D391E61DC23E128DA4446C /* NSView+Traversing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393EE88DE554BCCBC1C2D /* NSView+Traversing.h */; };
|
||||
93D392EC39DA43C46C692C12 /* NSDictionary+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */; };
|
||||
93D394C4254EEB45FB335AFB /* MPSitesTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39423D7BF4FD31FE6D27C /* MPSitesTableView.m */; };
|
||||
93D395E4830290EBB6E71F34 /* MPNoStateButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39538C4CEFF46DF379254 /* MPNoStateButton.m */; };
|
||||
93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; };
|
||||
93D3970BCF85F7902E611168 /* PearlProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DB3A8ADED08C39A6228 /* PearlProfiler.m */; };
|
||||
93D39784E725A34D1EE3FB3B /* MPInitialWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D3CB30874147D9A9E1B /* MPInitialWindowController.m */; };
|
||||
93D3987F6D9046DBEE4D8364 /* NSView+Traversing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D392870DF659AFC1870521 /* NSView+Traversing.m */; };
|
||||
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
|
||||
93D39C5789EFA607CF788082 /* MPSiteModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E73BF5CBF8E5B005CD3 /* MPSiteModel.m */; };
|
||||
93D39D304F73B3BBA031522A /* PearlProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D394EEFF5BF555A55AF361 /* PearlProfiler.h */; };
|
||||
@@ -55,6 +57,8 @@
|
||||
DA3B8456190FC89700246EEA /* MPFixable.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3B8454190FC89700246EEA /* MPFixable.m */; };
|
||||
DA3BCFCD19BD09E0006B2681 /* SourceCodePro-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = DA3BCFCC19BD09E0006B2681 /* SourceCodePro-Regular.otf */; };
|
||||
DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6326C148680650075AEA5 /* libjrswizzle.a */; };
|
||||
DA4DAE941A7D8117003E5423 /* MPAlgorithmV3.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4DAE921A7D8117003E5423 /* MPAlgorithmV3.m */; };
|
||||
DA4DAE951A7D8117003E5423 /* MPTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4DAE931A7D8117003E5423 /* MPTypes.m */; };
|
||||
DA5180CA19FF2F9200A587E9 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */; };
|
||||
DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */; };
|
||||
DA5E5C9417248AA1003798D8 /* libscryptenc-osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5E5C8717248AA1003798D8 /* libscryptenc-osx.a */; };
|
||||
@@ -83,12 +87,13 @@
|
||||
DA67742F1A4746AF004F356A /* mpw-types.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773C21A4746AF004F356A /* mpw-types.c */; };
|
||||
DA6774311A4746AF004F356A /* mpw-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773C51A4746AF004F356A /* mpw-util.c */; };
|
||||
DA6774331A4746AF004F356A /* mpw.bashrc in Resources */ = {isa = PBXBuildFile; fileRef = DA6773C81A4746AF004F356A /* mpw.bashrc */; };
|
||||
DA6774341A4746AF004F356A /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = DA6773C91A4746AF004F356A /* VERSION */; };
|
||||
DA6774431A474A3B004F356A /* mpw-algorithm.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773BB1A4746AF004F356A /* mpw-algorithm.c */; };
|
||||
DA6774441A474A3B004F356A /* mpw-tests.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773C11A4746AF004F356A /* mpw-tests.c */; };
|
||||
DA6774451A474A3B004F356A /* mpw-types.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773C21A4746AF004F356A /* mpw-types.c */; };
|
||||
DA6774461A474A3B004F356A /* mpw-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6773C51A4746AF004F356A /* mpw-util.c */; };
|
||||
DA67744A1A47C8F7004F356A /* mpw-tests-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA6774481A47C8F7004F356A /* mpw-tests-util.c */; };
|
||||
DA89D4EC1A51EABD00AC64D7 /* Pearl-Cocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = DA89D4EA1A51EABD00AC64D7 /* Pearl-Cocoa.h */; };
|
||||
DA89D4ED1A51EABD00AC64D7 /* Pearl-Cocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = DA89D4EB1A51EABD00AC64D7 /* Pearl-Cocoa.m */; };
|
||||
DA8ED895192906920099B726 /* PearlTween.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8ED891192906920099B726 /* PearlTween.m */; };
|
||||
DA8ED896192906920099B726 /* PearlTween.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8ED892192906920099B726 /* PearlTween.h */; };
|
||||
DA8ED897192906920099B726 /* map-macro.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8ED894192906920099B726 /* map-macro.h */; };
|
||||
@@ -259,10 +264,12 @@
|
||||
/* Begin PBXFileReference section */
|
||||
93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Indexing.m"; sourceTree = "<group>"; };
|
||||
93D39240B5143E01F0B75E96 /* MPSiteModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteModel.h; sourceTree = "<group>"; };
|
||||
93D392870DF659AFC1870521 /* NSView+Traversing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+Traversing.m"; sourceTree = "<group>"; };
|
||||
93D392A4F3DE0BD758B9B056 /* MPNoStateButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNoStateButton.h; sourceTree = "<group>"; };
|
||||
93D392C3918763B3B72CF366 /* MPPasswordWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindowController.h; sourceTree = "<group>"; };
|
||||
93D39368EF3CBFEF2AFCA15A /* MPInitialWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInitialWindowController.h; sourceTree = "<group>"; };
|
||||
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D393EE88DE554BCCBC1C2D /* NSView+Traversing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSView+Traversing.h"; sourceTree = "<group>"; };
|
||||
93D39423D7BF4FD31FE6D27C /* MPSitesTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSitesTableView.m; sourceTree = "<group>"; };
|
||||
93D394EEFF5BF555A55AF361 /* PearlProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PearlProfiler.h; path = ../../../External/Pearl/Pearl/PearlProfiler.h; sourceTree = "<group>"; };
|
||||
93D39538C4CEFF46DF379254 /* MPNoStateButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNoStateButton.m; sourceTree = "<group>"; };
|
||||
@@ -323,6 +330,9 @@
|
||||
DA3B8454190FC89700246EEA /* MPFixable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPFixable.m; sourceTree = "<group>"; };
|
||||
DA3B8455190FC89700246EEA /* MPFixable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPFixable.h; sourceTree = "<group>"; };
|
||||
DA3BCFCC19BD09E0006B2681 /* SourceCodePro-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SourceCodePro-Regular.otf"; sourceTree = "<group>"; };
|
||||
DA4DAE911A7D8117003E5423 /* MPAlgorithmV3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithmV3.h; sourceTree = "<group>"; };
|
||||
DA4DAE921A7D8117003E5423 /* MPAlgorithmV3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV3.m; sourceTree = "<group>"; };
|
||||
DA4DAE931A7D8117003E5423 /* MPTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTypes.m; sourceTree = "<group>"; };
|
||||
DA5180C619FF2F9200A587E9 /* MPAlgorithmV2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithmV2.h; sourceTree = "<group>"; };
|
||||
DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV2.m; sourceTree = "<group>"; };
|
||||
DA5180CC19FF307E00A587E9 /* MPAppDelegate_Store.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_Store.h; sourceTree = "<group>"; };
|
||||
@@ -779,10 +789,15 @@
|
||||
DA6773C51A4746AF004F356A /* mpw-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-util.c"; sourceTree = "<group>"; };
|
||||
DA6773C61A4746AF004F356A /* mpw-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-util.h"; sourceTree = "<group>"; };
|
||||
DA6773C81A4746AF004F356A /* mpw.bashrc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mpw.bashrc; sourceTree = "<group>"; };
|
||||
DA6773C91A4746AF004F356A /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
|
||||
DA67743B1A474A03004F356A /* mpw-test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "mpw-test"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA6774481A47C8F7004F356A /* mpw-tests-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-tests-util.c"; sourceTree = "<group>"; };
|
||||
DA6774491A47C8F7004F356A /* mpw-tests-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-tests-util.h"; sourceTree = "<group>"; };
|
||||
DA831A271A6E1146000AC234 /* mpw-algorithm_v0.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v0.c"; sourceTree = "<group>"; };
|
||||
DA831A281A6E1146000AC234 /* mpw-algorithm_v1.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v1.c"; sourceTree = "<group>"; };
|
||||
DA831A291A6E1146000AC234 /* mpw-algorithm_v2.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v2.c"; sourceTree = "<group>"; };
|
||||
DA831A2A1A6E1146000AC234 /* mpw-algorithm_v3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v3.c"; sourceTree = "<group>"; };
|
||||
DA89D4EA1A51EABD00AC64D7 /* Pearl-Cocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Pearl-Cocoa.h"; sourceTree = "<group>"; };
|
||||
DA89D4EB1A51EABD00AC64D7 /* Pearl-Cocoa.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Pearl-Cocoa.m"; sourceTree = "<group>"; };
|
||||
DA8ED891192906920099B726 /* PearlTween.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlTween.m; sourceTree = "<group>"; };
|
||||
DA8ED892192906920099B726 /* PearlTween.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlTween.h; sourceTree = "<group>"; };
|
||||
DA8ED894192906920099B726 /* map-macro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "map-macro.h"; sourceTree = "<group>"; };
|
||||
@@ -1055,6 +1070,8 @@
|
||||
DA5E5C9C1724A667003798D8 /* MPAlgorithmV1.m */,
|
||||
DA5180C619FF2F9200A587E9 /* MPAlgorithmV2.h */,
|
||||
DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */,
|
||||
DA4DAE911A7D8117003E5423 /* MPAlgorithmV3.h */,
|
||||
DA4DAE921A7D8117003E5423 /* MPAlgorithmV3.m */,
|
||||
DA5E5C9D1724A667003798D8 /* MPAppDelegate_Key.h */,
|
||||
DA5E5C9E1724A667003798D8 /* MPAppDelegate_Key.m */,
|
||||
DA5E5C9F1724A667003798D8 /* MPAppDelegate_Shared.h */,
|
||||
@@ -1078,6 +1095,7 @@
|
||||
DA32CFDA19CF1C70004F3F0E /* MPStoredSiteEntity.h */,
|
||||
DA32CFDB19CF1C70004F3F0E /* MPStoredSiteEntity.m */,
|
||||
DA5E5CAF1724A667003798D8 /* MPTypes.h */,
|
||||
DA4DAE931A7D8117003E5423 /* MPTypes.m */,
|
||||
DA32CFE319CF1C71004F3F0E /* MPUserEntity.h */,
|
||||
DA32CFE419CF1C71004F3F0E /* MPUserEntity.m */,
|
||||
);
|
||||
@@ -1533,6 +1551,10 @@
|
||||
DA67732B1A4746AF004F356A /* build */,
|
||||
DA67732C1A4746AF004F356A /* distribute */,
|
||||
DA67732D1A4746AF004F356A /* install */,
|
||||
DA831A271A6E1146000AC234 /* mpw-algorithm_v0.c */,
|
||||
DA831A281A6E1146000AC234 /* mpw-algorithm_v1.c */,
|
||||
DA831A291A6E1146000AC234 /* mpw-algorithm_v2.c */,
|
||||
DA831A2A1A6E1146000AC234 /* mpw-algorithm_v3.c */,
|
||||
DA6773BB1A4746AF004F356A /* mpw-algorithm.c */,
|
||||
DA6773BC1A4746AF004F356A /* mpw-algorithm.h */,
|
||||
DA6773BF1A4746AF004F356A /* mpw-bench.c */,
|
||||
@@ -1545,12 +1567,22 @@
|
||||
DA6773C51A4746AF004F356A /* mpw-util.c */,
|
||||
DA6773C61A4746AF004F356A /* mpw-util.h */,
|
||||
DA6773C81A4746AF004F356A /* mpw.bashrc */,
|
||||
DA6773C91A4746AF004F356A /* VERSION */,
|
||||
);
|
||||
name = C;
|
||||
path = ../../C;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA89D4E51A51E53100AC64D7 /* Pearl-Cocoa */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA89D4EA1A51EABD00AC64D7 /* Pearl-Cocoa.h */,
|
||||
DA89D4EB1A51EABD00AC64D7 /* Pearl-Cocoa.m */,
|
||||
93D392870DF659AFC1870521 /* NSView+Traversing.m */,
|
||||
93D393EE88DE554BCCBC1C2D /* NSView+Traversing.h */,
|
||||
);
|
||||
path = "Pearl-Cocoa";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA8ED893192906920099B726 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1572,6 +1604,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAFE45D715039823003ABA7C /* Pearl */,
|
||||
DA89D4E51A51E53100AC64D7 /* Pearl-Cocoa */,
|
||||
DAFE45FC15039823003ABA7C /* Pearl-Crypto */,
|
||||
DAC77CB1148291A600BCF976 /* Pearl-Prefix.pch */,
|
||||
);
|
||||
@@ -1857,6 +1890,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA10007F1998A4C6002B873F /* scrypt in Headers */,
|
||||
DA89D4EC1A51EABD00AC64D7 /* Pearl-Cocoa.h in Headers */,
|
||||
DA1000801998A4C6002B873F /* openssl in Headers */,
|
||||
DA2CA4F218D323D3007798F8 /* NSTimer+PearlBlock.h in Headers */,
|
||||
DAFE4A1315039824003ABA7C /* NSObject+PearlExport.h in Headers */,
|
||||
@@ -1894,6 +1928,7 @@
|
||||
DA2CA4EE18D323D3007798F8 /* NSError+PearlFullDescription.h in Headers */,
|
||||
DAADCC4819FAFFAD00987B1D /* NSPersistentStore+PearlMigration.h in Headers */,
|
||||
93D39D304F73B3BBA031522A /* PearlProfiler.h in Headers */,
|
||||
93D391E61DC23E128DA4446C /* NSView+Traversing.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2103,7 +2138,6 @@
|
||||
DACA272C1705DF81002C6C22 /* avatar-14@2x.png in Resources */,
|
||||
DACA272D1705DF81002C6C22 /* avatar-4@2x.png in Resources */,
|
||||
DACA272E1705DF81002C6C22 /* avatar-9@2x.png in Resources */,
|
||||
DA6774341A4746AF004F356A /* VERSION in Resources */,
|
||||
DACA272F1705DF81002C6C22 /* avatar-3.png in Resources */,
|
||||
DACA27301705DF81002C6C22 /* avatar-18.png in Resources */,
|
||||
DACA27311705DF81002C6C22 /* avatar-4.png in Resources */,
|
||||
@@ -2191,7 +2225,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = "/bin/bash -e";
|
||||
shellScript = "../../../External/Mac/Crashlytics.framework/run \\\n \"$(/usr/libexec/PlistBuddy -c \"Print :'API Key'\" ../../Resources/Crashlytics/Crashlytics.plist)\"";
|
||||
shellScript = "../../../External/Mac/Crashlytics.framework/run \\\n \"$(/usr/libexec/PlistBuddy -c \"Print :'API Key'\" ../../Resources/Crashlytics/Crashlytics.plist)\" 410fb41450e3a2e50fa8357682d812ecd3e1846f2141a99bdb9d3a6a981ad69c";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
@@ -2230,6 +2264,8 @@
|
||||
93D394C4254EEB45FB335AFB /* MPSitesTableView.m in Sources */,
|
||||
DA6774291A4746AF004F356A /* mpw-algorithm.c in Sources */,
|
||||
93D395E4830290EBB6E71F34 /* MPNoStateButton.m in Sources */,
|
||||
DA4DAE941A7D8117003E5423 /* MPAlgorithmV3.m in Sources */,
|
||||
DA4DAE951A7D8117003E5423 /* MPTypes.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2281,6 +2317,7 @@
|
||||
DAFE4A2E15039824003ABA7C /* PearlStrings.m in Sources */,
|
||||
DAFE4A3015039824003ABA7C /* PearlStringUtils.m in Sources */,
|
||||
DAFE4A3515039824003ABA7C /* PearlCryptUtils.m in Sources */,
|
||||
DA89D4ED1A51EABD00AC64D7 /* Pearl-Cocoa.m in Sources */,
|
||||
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */,
|
||||
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */,
|
||||
DAFE4A3B15039824003ABA7C /* PearlSCrypt.m in Sources */,
|
||||
@@ -2298,6 +2335,7 @@
|
||||
93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */,
|
||||
DA3509FF15F101A500C14A8E /* PearlQueue.m in Sources */,
|
||||
93D3970BCF85F7902E611168 /* PearlProfiler.m in Sources */,
|
||||
93D3987F6D9046DBEE4D8364 /* NSView+Traversing.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2351,16 +2389,21 @@
|
||||
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
|
||||
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
|
||||
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_CXX0X_EXTENSIONS = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
|
||||
CLANG_WARN_OBJC_RECEIVER_WEAK = NO;
|
||||
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = NO;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES;
|
||||
@@ -2388,7 +2431,7 @@
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES;
|
||||
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
|
||||
@@ -2432,16 +2475,21 @@
|
||||
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
|
||||
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
|
||||
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_CXX0X_EXTENSIONS = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
|
||||
CLANG_WARN_OBJC_RECEIVER_WEAK = NO;
|
||||
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = NO;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES;
|
||||
@@ -2449,6 +2497,7 @@
|
||||
CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
@@ -2457,6 +2506,7 @@
|
||||
"$(inherited)",
|
||||
"NDEBUG=1",
|
||||
"NS_BLOCK_ASSERTIONS=1",
|
||||
"CRASHLYTICS=1",
|
||||
);
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
||||
@@ -2469,7 +2519,7 @@
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES;
|
||||
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
|
||||
@@ -2480,7 +2530,7 @@
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = NO;
|
||||
GCC_WARN_UNUSED_LABEL = YES;
|
||||
@@ -2598,16 +2648,21 @@
|
||||
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
|
||||
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
|
||||
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_CXX0X_EXTENSIONS = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
|
||||
CLANG_WARN_OBJC_RECEIVER_WEAK = NO;
|
||||
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = NO;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES;
|
||||
@@ -2615,6 +2670,7 @@
|
||||
CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
@@ -2623,6 +2679,7 @@
|
||||
"$(inherited)",
|
||||
"NDEBUG=1",
|
||||
"NS_BLOCK_ASSERTIONS=1",
|
||||
"CRASHLYTICS=1",
|
||||
);
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
|
||||
@@ -2635,7 +2692,7 @@
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES;
|
||||
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
|
||||
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
|
||||
@@ -2646,7 +2703,7 @@
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNKNOWN_PRAGMAS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = NO;
|
||||
GCC_WARN_UNUSED_LABEL = YES;
|
||||
|
||||
@@ -29,6 +29,15 @@
|
||||
buildConfiguration = "AppStore-Mac">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "Master Password.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
|
||||
@@ -29,6 +29,15 @@
|
||||
buildConfiguration = "Debug-Mac">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
|
||||
BuildableName = "Master Password.app"
|
||||
BlueprintName = "MasterPassword"
|
||||
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
// Prefix header for all source files of the 'MasterPassword' target in the 'MasterPassword' project
|
||||
//
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
|
||||
#warning "This project uses features only available in Mac OS X 10.8 and later."
|
||||
#endif
|
||||
|
||||
#import "Pearl-Prefix.pch"
|
||||
|
||||
#ifdef __OBJC__
|
||||
@@ -10,6 +14,10 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
#ifdef CRASHLYTICS
|
||||
#import <Crashlytics/Crashlytics.h>
|
||||
#endif
|
||||
|
||||
#import "MPTypes.h"
|
||||
#import "MPMacConfig.h"
|
||||
|
||||
|
||||
@@ -10,5 +10,7 @@
|
||||
</array>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -13,10 +13,16 @@
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
#define PEARL_UIKIT
|
||||
#endif
|
||||
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
#define PEARL_COCOA
|
||||
#endif
|
||||
|
||||
#import "Pearl.h"
|
||||
#import "Pearl-Crypto.h"
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
#import "Pearl-UIKit.h"
|
||||
#endif
|
||||
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
#import "Pearl-Cocoa.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -284,7 +284,7 @@
|
||||
initSheet:^(UIActionSheet *sheet) {
|
||||
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
||||
for (NSNumber *typeNumber in [MPAlgorithmDefault allTypes]) {
|
||||
MPSiteType type = [typeNumber unsignedIntegerValue];
|
||||
MPSiteType type = (MPSiteType)[typeNumber unsignedIntegerValue];
|
||||
NSString *typeName = [MPAlgorithmDefault nameOfType:type];
|
||||
if (type == mainSite.type)
|
||||
[sheet addButtonWithTitle:strf( @"● %@", typeName )];
|
||||
@@ -295,7 +295,7 @@
|
||||
if (buttonIndex == [sheet cancelButtonIndex])
|
||||
return;
|
||||
|
||||
MPSiteType type = [[MPAlgorithmDefault allTypes][buttonIndex] unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
|
||||
MPSiteType type = (MPSiteType)[[MPAlgorithmDefault allTypes][buttonIndex] unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPSiteEntity *site = [self siteInContext:context];
|
||||
|
||||
@@ -182,7 +182,7 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (enum MPSiteType)typeForSelectedSegment {
|
||||
- (MPSiteType)typeForSelectedSegment {
|
||||
|
||||
NSInteger selectedGeneratedIndex = self.generatedTypeControl.selectedSegmentIndex;
|
||||
NSInteger selectedStoredIndex = self.storedTypeControl.selectedSegmentIndex;
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
[Crashlytics startWithAPIKey:crashlyticsAPIKey];
|
||||
[[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) {
|
||||
PearlLogLevel level = PearlLogLevelInfo;
|
||||
if ([[MPiOSConfig get].sendInfo boolValue])
|
||||
if ([[MPConfig get].sendInfo boolValue])
|
||||
level = PearlLogLevelDebug;
|
||||
|
||||
if (message.level >= level)
|
||||
@@ -333,7 +333,7 @@
|
||||
|
||||
NSString *userName = [[MPiOSAppDelegate get] activeUserForMainThread].name;
|
||||
PearlLogLevel logLevel = PearlLogLevelInfo;
|
||||
if (logs && ([[MPiOSConfig get].sendInfo boolValue] || [[MPiOSConfig get].traceMode boolValue]))
|
||||
if (logs && ([[MPConfig get].sendInfo boolValue] || [[MPiOSConfig get].traceMode boolValue]))
|
||||
logLevel = PearlLogLevelDebug;
|
||||
|
||||
[[[PearlEMail alloc] initForEMailTo:@"Master Password Development <masterpassword@lyndir.com>"
|
||||
@@ -530,13 +530,13 @@
|
||||
[PearlLogger get].historyLevel = [[MPiOSConfig get].traceMode boolValue]? PearlLogLevelTrace: PearlLogLevelInfo;
|
||||
|
||||
// Send info
|
||||
if ([[MPiOSConfig get].sendInfo boolValue]) {
|
||||
if ([[MPConfig get].sendInfo boolValue]) {
|
||||
if ([PearlLogger get].printLevel > PearlLogLevelInfo)
|
||||
[PearlLogger get].printLevel = PearlLogLevelInfo;
|
||||
|
||||
#ifdef CRASHLYTICS
|
||||
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].rememberLogin boolValue] forKey:@"rememberLogin"];
|
||||
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].sendInfo boolValue] forKey:@"sendInfo"];
|
||||
[[Crashlytics sharedInstance] setBoolValue:[[MPConfig get].sendInfo boolValue] forKey:@"sendInfo"];
|
||||
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].helpHidden boolValue] forKey:@"helpHidden"];
|
||||
[[Crashlytics sharedInstance] setBoolValue:[[MPiOSConfig get].showSetup boolValue] forKey:@"showQuickStart"];
|
||||
[[Crashlytics sharedInstance] setBoolValue:[[PearlConfig get].firstRun boolValue] forKey:@"firstRun"];
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
93D3954E96236384AFA00453 /* UIScrollView+PearlAdjustInsets.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */; };
|
||||
93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */; };
|
||||
93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B381350802A194BF332 /* MPAvatarCell.m */; };
|
||||
93D39577FD8BB0945DB2F0A3 /* MPAlgorithmV3.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39FD9623E8D5571C0AEB3 /* MPAlgorithmV3.m */; };
|
||||
93D3958C13B557F60F63C72B /* distribute in Resources */ = {isa = PBXBuildFile; fileRef = 93D3979016BF0C5B29D1340D /* distribute */; };
|
||||
93D395B715D15F2B56F2A2EE /* mpw-types.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D392C5A6572DB0EB5B82C8 /* mpw-types.c */; };
|
||||
93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; };
|
||||
@@ -33,7 +34,6 @@
|
||||
93D396AA30690B256F30378A /* PearlNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3956915634581E737B38C /* PearlNavigationController.m */; };
|
||||
93D396BA1C74C4A06FD86437 /* PearlOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D3942A356B639724157982 /* PearlOverlay.h */; };
|
||||
93D396D8B67DA6522CDBA142 /* MPCoachmarkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */; };
|
||||
93D39711B6D873F37E8B9B2D /* VERSION in Resources */ = {isa = PBXBuildFile; fileRef = 93D3944F4D55D2A37EF6021B /* VERSION */; };
|
||||
93D397952F5635C793C24DF1 /* NSError+PearlFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */; };
|
||||
93D3980046016EFD05B35BC5 /* PearlUICollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */; };
|
||||
93D398ECD7D1A0DEDDADF516 /* MPEmergencyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */; };
|
||||
@@ -61,6 +61,7 @@
|
||||
93D39DF2E77B937D77C10414 /* install in Resources */ = {isa = PBXBuildFile; fileRef = 93D39ACD33E79386E6F33601 /* install */; };
|
||||
93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */; };
|
||||
93D39E34FD28D24FE3442C48 /* UITextView+PearlAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3977321EB249981821AB0 /* UITextView+PearlAttributes.m */; };
|
||||
93D39E5F7F6D7F5C0FAD090F /* MPTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39D72239990DDAC2D75B0 /* MPTypes.m */; };
|
||||
93D39EAA4D064193074D3021 /* MPFixable.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A813CA9D7E192261ED2 /* MPFixable.m */; };
|
||||
93D39F8A9254177891F38705 /* MPSetupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A28369954D147E239BA /* MPSetupViewController.m */; };
|
||||
93D39FAE1BB6A393BFE15FD0 /* mpw.bashrc in Resources */ = {isa = PBXBuildFile; fileRef = 93D39245A478883C672818F3 /* mpw.bashrc */; };
|
||||
@@ -167,7 +168,6 @@
|
||||
DA67460E18DE7F0C00DFE240 /* Exo2.0-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = DA67460A18DE7F0C00DFE240 /* Exo2.0-Regular.otf */; };
|
||||
DA67460F18DE7F0C00DFE240 /* Exo2.0-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = DA67460B18DE7F0C00DFE240 /* Exo2.0-ExtraBold.otf */; };
|
||||
DA67461018DE7F0C00DFE240 /* Exo2.0-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = DA67460C18DE7F0C00DFE240 /* Exo2.0-Bold.otf */; };
|
||||
DA6773251A43B660004F356A /* libscryptenc-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAFFC63E17EDDA7C007BB020 /* libscryptenc-ios.a */; };
|
||||
DA69540617D975D900BF294E /* icon_gears.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37841711E29500CF925C /* icon_gears.png */; };
|
||||
DA69540717D975D900BF294E /* icon_gears@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37851711E29500CF925C /* icon_gears@2x.png */; };
|
||||
DA72BD7919C137DE00E6ACFE /* libopensslcrypto-ios-dev.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA72BD7719C137D500E6ACFE /* libopensslcrypto-ios-dev.a */; };
|
||||
@@ -218,6 +218,7 @@
|
||||
DAA1765219D8B82B0044227B /* copy_pw.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1763C19D8B82B0044227B /* copy_pw.png */; };
|
||||
DAA1765319D8B82B0044227B /* choose_type@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1763D19D8B82B0044227B /* choose_type@2x.png */; };
|
||||
DAA1765419D8B82B0044227B /* choose_type.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1763E19D8B82B0044227B /* choose_type.png */; };
|
||||
DAADBFE01A68763B00F7A756 /* mpw-algorithm.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D3969393A3A46BD27D7078 /* mpw-algorithm.c */; };
|
||||
DABB981615100B4000B05417 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DABB981515100B4000B05417 /* SystemConfiguration.framework */; };
|
||||
DABD39371711E29700CF925C /* avatar-0.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD366C1711E29400CF925C /* avatar-0.png */; };
|
||||
DABD39381711E29700CF925C /* avatar-0@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD366D1711E29400CF925C /* avatar-0@2x.png */; };
|
||||
@@ -464,6 +465,8 @@
|
||||
93D390519405B76CC6A57C4F /* MPCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCell.h; sourceTree = "<group>"; };
|
||||
93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSArray+Indexing.m"; sourceTree = "<group>"; };
|
||||
93D3908DF8EABBD952065DC0 /* UICollectionView+PearlReloadFromArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionView+PearlReloadFromArray.m"; sourceTree = "<group>"; };
|
||||
93D390A3B351FEF1B9EDAB56 /* mpw-algorithm_v2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v2.c"; sourceTree = "<group>"; };
|
||||
93D390A99850139D0FF0211E /* mpw-algorithm_v0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v0.c"; sourceTree = "<group>"; };
|
||||
93D390FADEB325D8D54A957D /* PearlOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlOverlay.m; sourceTree = "<group>"; };
|
||||
93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+PearlAdjustInsets.m"; sourceTree = "<group>"; };
|
||||
93D39149A5F1F9B174D6D061 /* MPStoreViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStoreViewController.h; sourceTree = "<group>"; };
|
||||
@@ -485,14 +488,15 @@
|
||||
93D394077F8FAB8167647187 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; };
|
||||
93D3942A356B639724157982 /* PearlOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlOverlay.h; sourceTree = "<group>"; };
|
||||
93D394482BB07F90E8FD1314 /* UIResponder+PearlFirstResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIResponder+PearlFirstResponder.h"; sourceTree = "<group>"; };
|
||||
93D3944F4D55D2A37EF6021B /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
|
||||
93D394C78C7B879C9AD9152C /* MPAppDelegate_InApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_InApp.m; sourceTree = "<group>"; };
|
||||
93D394D73F5BC92297CE8D7B /* MPAlgorithmV3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithmV3.h; sourceTree = "<group>"; };
|
||||
93D395105935859D71679931 /* MPOverlayViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOverlayViewController.m; sourceTree = "<group>"; };
|
||||
93D3956915634581E737B38C /* PearlNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlNavigationController.m; sourceTree = "<group>"; };
|
||||
93D3957D76F71A652716EECC /* MPStoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStoreViewController.m; sourceTree = "<group>"; };
|
||||
93D3969393A3A46BD27D7078 /* mpw-algorithm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm.c"; sourceTree = "<group>"; };
|
||||
93D396C311C3725870343EE0 /* mpw-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-util.c"; sourceTree = "<group>"; };
|
||||
93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D396F918E6470DB846C17F /* mpw-algorithm_v1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v1.c"; sourceTree = "<group>"; };
|
||||
93D3970502644794E8A027BE /* MPNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNavigationController.h; sourceTree = "<group>"; };
|
||||
93D3971FE104BB4052484151 /* MPUsersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUsersViewController.h; sourceTree = "<group>"; };
|
||||
93D397288D0655822A73A539 /* mpw-tests-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-tests-util.c"; sourceTree = "<group>"; };
|
||||
@@ -541,7 +545,9 @@
|
||||
93D39CECA10BCCB0BA581BF1 /* MPAppDelegate_InApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_InApp.h; sourceTree = "<group>"; };
|
||||
93D39CF7DB942C69D1C5D6BE /* mpw-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-util.h"; sourceTree = "<group>"; };
|
||||
93D39CF8ADF4542CDC4CD385 /* MPCombinedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCombinedViewController.h; sourceTree = "<group>"; };
|
||||
93D39D4E713564B7654341B0 /* mpw-algorithm_v3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm_v3.c"; sourceTree = "<group>"; };
|
||||
93D39D6604447D7708039155 /* MPAnswersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAnswersViewController.h; sourceTree = "<group>"; };
|
||||
93D39D72239990DDAC2D75B0 /* MPTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTypes.m; sourceTree = "<group>"; };
|
||||
93D39D8A953779B35403AF6E /* PearlUICollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUICollectionView.m; sourceTree = "<group>"; };
|
||||
93D39DA27D768B53C8B1330C /* MPAvatarCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAvatarCell.h; sourceTree = "<group>"; };
|
||||
93D39DE2CB351D4E3789462B /* UIScrollView+PearlAdjustInsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+PearlAdjustInsets.h"; sourceTree = "<group>"; };
|
||||
@@ -551,6 +557,7 @@
|
||||
93D39F556F2F142740A65E59 /* MPWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPWebViewController.h; sourceTree = "<group>"; };
|
||||
93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = "<group>"; };
|
||||
93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = "<group>"; };
|
||||
93D39FD9623E8D5571C0AEB3 /* MPAlgorithmV3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV3.m; sourceTree = "<group>"; };
|
||||
DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
|
||||
DA071BF1190187FE00179766 /* empty@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "empty@2x.png"; sourceTree = "<group>"; };
|
||||
DA071BF2190187FE00179766 /* empty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = empty.png; sourceTree = "<group>"; };
|
||||
@@ -1592,7 +1599,6 @@
|
||||
DA4DA1DA1564471F00F6F596 /* libuicolor-utilities.a in Frameworks */,
|
||||
DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */,
|
||||
DAC77CAE148291A600BCF976 /* Foundation.framework in Frameworks */,
|
||||
DA6773251A43B660004F356A /* libscryptenc-ios.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1614,6 +1620,10 @@
|
||||
93D39B573E4DE98BAE518215 /* build */,
|
||||
93D3979016BF0C5B29D1340D /* distribute */,
|
||||
93D39ACD33E79386E6F33601 /* install */,
|
||||
93D390A99850139D0FF0211E /* mpw-algorithm_v0.c */,
|
||||
93D396F918E6470DB846C17F /* mpw-algorithm_v1.c */,
|
||||
93D390A3B351FEF1B9EDAB56 /* mpw-algorithm_v2.c */,
|
||||
93D39D4E713564B7654341B0 /* mpw-algorithm_v3.c */,
|
||||
93D3969393A3A46BD27D7078 /* mpw-algorithm.c */,
|
||||
93D3990D850D76A94C6B7A4D /* mpw-algorithm.h */,
|
||||
93D39B70138D0E28F7D5E86B /* mpw-bench.c */,
|
||||
@@ -1626,7 +1636,6 @@
|
||||
93D396C311C3725870343EE0 /* mpw-util.c */,
|
||||
93D39CF7DB942C69D1C5D6BE /* mpw-util.h */,
|
||||
93D39245A478883C672818F3 /* mpw.bashrc */,
|
||||
93D3944F4D55D2A37EF6021B /* VERSION */,
|
||||
);
|
||||
name = C;
|
||||
path = ../../C;
|
||||
@@ -2549,23 +2558,20 @@
|
||||
DABD3B9F1711E2DB00CF925C /* ObjC */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA32D05319D741DC004F3F0E /* MPSiteQuestionEntity.h */,
|
||||
DA32D05419D741DC004F3F0E /* MPSiteQuestionEntity.m */,
|
||||
DA32CFE619CF1C8F004F3F0E /* MPUserEntity.m */,
|
||||
DA32CFE719CF1C8F004F3F0E /* MPUserEntity.h */,
|
||||
DA32CFE819CF1C8F004F3F0E /* MPStoredSiteEntity.m */,
|
||||
DA32CFE919CF1C8F004F3F0E /* MPStoredSiteEntity.h */,
|
||||
DA32CFEC19CF1C8F004F3F0E /* MPSiteEntity.m */,
|
||||
DA32CFED19CF1C8F004F3F0E /* MPSiteEntity.h */,
|
||||
DA32CFEE19CF1C8F004F3F0E /* MPGeneratedSiteEntity.m */,
|
||||
DA32CFEF19CF1C8F004F3F0E /* MPGeneratedSiteEntity.h */,
|
||||
DABD3BD71711E2DC00CF925C /* iOS */,
|
||||
DA32D00119CF4735004F3F0E /* MasterPassword.xcdatamodeld */,
|
||||
DABD3BA01711E2DC00CF925C /* MPAlgorithm.h */,
|
||||
DABD3BA11711E2DC00CF925C /* MPAlgorithm.m */,
|
||||
DABD3BA21711E2DC00CF925C /* MPAlgorithmV0.h */,
|
||||
DABD3BA31711E2DC00CF925C /* MPAlgorithmV0.m */,
|
||||
DABD3BA41711E2DC00CF925C /* MPAlgorithmV1.h */,
|
||||
DABD3BA51711E2DC00CF925C /* MPAlgorithmV1.m */,
|
||||
93D39A97A7D48CB3B784194D /* MPAlgorithmV2.h */,
|
||||
93D399A8E3181B442D347CD7 /* MPAlgorithmV2.m */,
|
||||
93D394D73F5BC92297CE8D7B /* MPAlgorithmV3.h */,
|
||||
93D39FD9623E8D5571C0AEB3 /* MPAlgorithmV3.m */,
|
||||
93D39CECA10BCCB0BA581BF1 /* MPAppDelegate_InApp.h */,
|
||||
93D394C78C7B879C9AD9152C /* MPAppDelegate_InApp.m */,
|
||||
DABD3BA61711E2DC00CF925C /* MPAppDelegate_Key.h */,
|
||||
DABD3BA71711E2DC00CF925C /* MPAppDelegate_Key.m */,
|
||||
DABD3BA81711E2DC00CF925C /* MPAppDelegate_Shared.h */,
|
||||
@@ -2576,16 +2582,22 @@
|
||||
DABD3BAD1711E2DC00CF925C /* MPConfig.m */,
|
||||
DABD3BB41711E2DC00CF925C /* MPEntities.h */,
|
||||
DABD3BB51711E2DC00CF925C /* MPEntities.m */,
|
||||
DABD3BB61711E2DC00CF925C /* MPKey.h */,
|
||||
DABD3BB71711E2DC00CF925C /* MPKey.m */,
|
||||
DABD3BB81711E2DC00CF925C /* MPTypes.h */,
|
||||
DA32D00119CF4735004F3F0E /* MasterPassword.xcdatamodeld */,
|
||||
93D399F244BB522A317811BB /* MPFixable.h */,
|
||||
93D39A813CA9D7E192261ED2 /* MPFixable.m */,
|
||||
93D394C78C7B879C9AD9152C /* MPAppDelegate_InApp.m */,
|
||||
93D39CECA10BCCB0BA581BF1 /* MPAppDelegate_InApp.h */,
|
||||
93D399A8E3181B442D347CD7 /* MPAlgorithmV2.m */,
|
||||
93D39A97A7D48CB3B784194D /* MPAlgorithmV2.h */,
|
||||
DA32CFEF19CF1C8F004F3F0E /* MPGeneratedSiteEntity.h */,
|
||||
DA32CFEE19CF1C8F004F3F0E /* MPGeneratedSiteEntity.m */,
|
||||
DABD3BB61711E2DC00CF925C /* MPKey.h */,
|
||||
DABD3BB71711E2DC00CF925C /* MPKey.m */,
|
||||
DA32CFED19CF1C8F004F3F0E /* MPSiteEntity.h */,
|
||||
DA32CFEC19CF1C8F004F3F0E /* MPSiteEntity.m */,
|
||||
DA32D05319D741DC004F3F0E /* MPSiteQuestionEntity.h */,
|
||||
DA32D05419D741DC004F3F0E /* MPSiteQuestionEntity.m */,
|
||||
DA32CFE919CF1C8F004F3F0E /* MPStoredSiteEntity.h */,
|
||||
DA32CFE819CF1C8F004F3F0E /* MPStoredSiteEntity.m */,
|
||||
DABD3BB81711E2DC00CF925C /* MPTypes.h */,
|
||||
DA32CFE719CF1C8F004F3F0E /* MPUserEntity.h */,
|
||||
DA32CFE619CF1C8F004F3F0E /* MPUserEntity.m */,
|
||||
93D39D72239990DDAC2D75B0 /* MPTypes.m */,
|
||||
);
|
||||
name = ObjC;
|
||||
path = ..;
|
||||
@@ -3527,7 +3539,6 @@
|
||||
93D39CEA71BD460ED4876920 /* build in Resources */,
|
||||
93D390228D0B8ED51C0AFDB4 /* bashlib in Resources */,
|
||||
93D39DF2E77B937D77C10414 /* install in Resources */,
|
||||
93D39711B6D873F37E8B9B2D /* VERSION in Resources */,
|
||||
93D3958C13B557F60F63C72B /* distribute in Resources */,
|
||||
93D39FAE1BB6A393BFE15FD0 /* mpw.bashrc in Resources */,
|
||||
);
|
||||
@@ -3628,6 +3639,7 @@
|
||||
93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */,
|
||||
93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */,
|
||||
93D396D8B67DA6522CDBA142 /* MPCoachmarkViewController.m in Sources */,
|
||||
DAADBFE01A68763B00F7A756 /* mpw-algorithm.c in Sources */,
|
||||
93D39EAA4D064193074D3021 /* MPFixable.m in Sources */,
|
||||
DA32CFF119CF1C8F004F3F0E /* MPStoredSiteEntity.m in Sources */,
|
||||
93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */,
|
||||
@@ -3642,6 +3654,8 @@
|
||||
93D392FD5E2052F7D7DB3774 /* NSString+MPMarkDown.m in Sources */,
|
||||
93D395B715D15F2B56F2A2EE /* mpw-types.c in Sources */,
|
||||
93D39943D01E70DAC3B0DF76 /* mpw-util.c in Sources */,
|
||||
93D39577FD8BB0945DB2F0A3 /* MPAlgorithmV3.m in Sources */,
|
||||
93D39E5F7F6D7F5C0FAD090F /* MPTypes.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -3994,6 +4008,13 @@
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-lscryptenc-ios",
|
||||
"-framework",
|
||||
Reveal,
|
||||
);
|
||||
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
|
||||
"$(inherited)",
|
||||
"-lscryptenc-ios-sim",
|
||||
"-framework",
|
||||
Reveal,
|
||||
);
|
||||
@@ -4023,6 +4044,14 @@
|
||||
"\"$(SRCROOT)/../../../External/Pearl/Pearl-Crypto/lib\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-lscryptenc-ios",
|
||||
);
|
||||
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
|
||||
"$(inherited)",
|
||||
"-lscryptenc-ios-sim",
|
||||
);
|
||||
PROVISIONING_PROFILE = "";
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "59b587d0-3ef3-4691-9f12-c48f7f283002";
|
||||
SKIP_INSTALL = NO;
|
||||
@@ -4130,6 +4159,14 @@
|
||||
"\"$(SRCROOT)/../../../External/Pearl/Pearl-Crypto/lib\"",
|
||||
"$(inherited)",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-lscryptenc-ios",
|
||||
);
|
||||
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
|
||||
"$(inherited)",
|
||||
"-lscryptenc-ios-sim",
|
||||
);
|
||||
PROVISIONING_PROFILE = "";
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "a1d8cfc8-b8db-4544-af34-28cc75e46c40";
|
||||
SKIP_INSTALL = NO;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6245" systemVersion="13E28" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="Q1S-vU-GGO">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="Q1S-vU-GGO">
|
||||
<dependencies>
|
||||
<deployment defaultVersion="1792" identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6238"/>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
|
||||
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
@@ -182,10 +182,10 @@
|
||||
<constraint firstAttribute="width" secondItem="Aca-he-7Qi" secondAttribute="height" multiplier="1:1" id="a8Q-UO-SH0"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop">
|
||||
<view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop">
|
||||
<rect key="frame" x="43" y="263" width="128.5" height="16"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" misplaced="YES" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field">
|
||||
<rect key="frame" x="5" y="0.0" width="118.5" height="16"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-ExtraBold" family="Exo 2.0" pointSize="13"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -249,7 +249,7 @@
|
||||
<outlet property="delegate" destination="S8q-YF-Kt9" id="det-Eh-phM"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
<button opaque="NO" alpha="0.69999999999999996" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9u7-pu-Wtv" userLabel="Previous Avatar">
|
||||
<button opaque="NO" alpha="0.69999999999999996" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9u7-pu-Wtv" userLabel="Previous Avatar">
|
||||
<rect key="frame" x="0.0" y="244" width="44" height="53"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="44" id="Ay6-Jg-c3T"/>
|
||||
@@ -262,7 +262,7 @@
|
||||
<action selector="changeAvatar:" destination="S8q-YF-Kt9" eventType="touchUpInside" id="lNu-mK-3zD"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" alpha="0.69999999999999996" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fUK-gJ-NRE" userLabel="Next Avatar">
|
||||
<button opaque="NO" alpha="0.69999999999999996" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fUK-gJ-NRE" userLabel="Next Avatar">
|
||||
<rect key="frame" x="331" y="244" width="44" height="53"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="44" id="oAm-YX-Fx5"/>
|
||||
@@ -297,20 +297,20 @@
|
||||
<outlet property="delegate" destination="S8q-YF-Kt9" id="5u3-XN-LOe"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fdS-zb-K9I" userLabel="Entry Tip">
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fdS-zb-K9I" userLabel="Entry Tip">
|
||||
<rect key="frame" x="71" y="-33" width="234.5" height="82.5"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="g2g-5i-er4">
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" misplaced="YES" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="g2g-5i-er4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="234.5" height="82.5"/>
|
||||
<rect key="contentStretch" x="0.15000000000000002" y="0.14999999999999999" width="0.69999999999999973" height="0.44999999999999996"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Looks like a typo!" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="ZI7-qg-7OW">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" misplaced="YES" text="Looks like a typo!" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="ZI7-qg-7OW">
|
||||
<rect key="frame" x="20" y="12" width="194.5" height="17"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Try again; the password was wrong." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KhE-Yj-Kvm">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" misplaced="YES" text="Try again; the password was wrong." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KhE-Yj-Kvm">
|
||||
<rect key="frame" x="20" y="37" width="194.5" height="14.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="12"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||
@@ -369,14 +369,14 @@
|
||||
<segue destination="Sd5-eW-Cx2" kind="modal" identifier="web" id="gtb-zE-u9H"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="069-Pu-yXe" userLabel="Thanks Tip">
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="069-Pu-yXe" userLabel="Thanks Tip">
|
||||
<rect key="frame" x="72" y="0.0" width="232.5" height="60"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="Z8P-ZK-aS0">
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" misplaced="YES" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="Z8P-ZK-aS0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="232.5" height="60"/>
|
||||
<rect key="contentStretch" x="0.15000000000000002" y="0.0" width="0.69999999999999973" height="1"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Why is Master Password free?" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="BLV-3x-Q0z">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" misplaced="YES" text="Why is Master Password free?" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="BLV-3x-Q0z">
|
||||
<rect key="frame" x="20" y="12" width="192.5" height="17"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||
@@ -407,14 +407,14 @@
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="ignoreTouches" value="YES"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cF4-TE-GEj" userLabel="Avatar Tip">
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cF4-TE-GEj" userLabel="Avatar Tip">
|
||||
<rect key="frame" x="49.5" y="184" width="276" height="60"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="V4W-bK-age">
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" misplaced="YES" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="V4W-bK-age">
|
||||
<rect key="frame" x="0.0" y="0.0" width="276" height="60"/>
|
||||
<rect key="contentStretch" x="0.15000000000000002" y="0.0" width="0.69999999999999973" height="1"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Change your avatar using the arrows." textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="MoM-8d-jlm">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" misplaced="YES" text="Change your avatar using the arrows." textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="MoM-8d-jlm">
|
||||
<rect key="frame" x="20" y="12" width="236" height="17"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||
@@ -432,14 +432,14 @@
|
||||
<constraint firstAttribute="trailing" secondItem="MoM-8d-jlm" secondAttribute="trailing" constant="20" id="Hc3-Mb-x5c"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Um-Ot-hI6" userLabel="Preferences Tip">
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0Um-Ot-hI6" userLabel="Preferences Tip">
|
||||
<rect key="frame" x="72" y="42" width="230" height="60"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black_top.png" translatesAutoresizingMaskIntoConstraints="NO" id="5H0-ml-Uso">
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" misplaced="YES" image="tip_basic_black_top.png" translatesAutoresizingMaskIntoConstraints="NO" id="5H0-ml-Uso">
|
||||
<rect key="frame" x="0.0" y="0.0" width="230" height="60"/>
|
||||
<rect key="contentStretch" x="0.15000000000000002" y="0.0" width="0.69999999999999973" height="1"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Tap for preferences and more." textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="Er5-X1-ejQ">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" misplaced="YES" text="Tap for preferences and more." textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="Er5-X1-ejQ">
|
||||
<rect key="frame" x="20" y="31.5" width="190" height="17"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||
@@ -847,7 +847,7 @@
|
||||
<constraint firstAttribute="height" constant="110" id="zBf-EA-iDN"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<button opaque="NO" alpha="0.69999998807907104" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DzC-Ts-gew" userLabel="Previous Avatar">
|
||||
<button opaque="NO" alpha="0.69999998807907104" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DzC-Ts-gew" userLabel="Previous Avatar">
|
||||
<rect key="frame" x="20" y="117" width="44" height="53"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="44" id="1Wu-gS-flK"/>
|
||||
@@ -861,7 +861,7 @@
|
||||
<action selector="previousAvatar:" destination="JFc-sj-awD" eventType="touchUpInside" id="D92-6I-zFd"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" alpha="0.69999998807907104" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yAf-fc-SKl" userLabel="Next Avatar">
|
||||
<button opaque="NO" alpha="0.69999998807907104" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yAf-fc-SKl" userLabel="Next Avatar">
|
||||
<rect key="frame" x="311" y="117" width="44" height="53"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="44" id="pEf-Vp-D7s"/>
|
||||
@@ -1040,13 +1040,13 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="152"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" text="© 2012-2014, Maarten Billemont (lhunath)" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sPw-mV-mFF">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" ambiguous="YES" misplaced="YES" text="© 2012-2014, Maarten Billemont (lhunath)" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sPw-mV-mFF">
|
||||
<rect key="frame" x="20" y="4" width="335" height="12"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Thin" family="Exo 2.0" pointSize="10"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Rl7-cr-FHf">
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Rl7-cr-FHf">
|
||||
<rect key="frame" x="20" y="24" width="335" height="26"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Home Page">
|
||||
@@ -1056,7 +1056,7 @@
|
||||
<action selector="homePageButton:" destination="JFc-sj-awD" eventType="touchUpInside" id="ptD-cv-NMr"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="epW-Rm-9St">
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="epW-Rm-9St">
|
||||
<rect key="frame" x="20" y="58" width="335" height="26"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Understanding Master Password's Security">
|
||||
@@ -1066,7 +1066,7 @@
|
||||
<action selector="securityButton:" destination="JFc-sj-awD" eventType="touchUpInside" id="Efv-cp-Xfh"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LTN-ch-h8D">
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LTN-ch-h8D">
|
||||
<rect key="frame" x="20" y="92" width="335" height="26"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Get the Master Password source code">
|
||||
@@ -1076,7 +1076,7 @@
|
||||
<action selector="sourceButton:" destination="JFc-sj-awD" eventType="touchUpInside" id="Y3O-di-CZo"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Z60-lc-Nka">
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Z60-lc-Nka">
|
||||
<rect key="frame" x="20" y="126" width="335" height="26"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Send Thanks">
|
||||
@@ -1235,10 +1235,10 @@
|
||||
<constraint firstItem="Iwe-rQ-ma0" firstAttribute="top" secondItem="w2g-zN-1wZ" secondAttribute="top" id="q2j-Aa-lEd"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2tX-WK-ASq" userLabel="Password Container">
|
||||
<view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2tX-WK-ASq" userLabel="Password Container">
|
||||
<rect key="frame" x="0.0" y="20" width="300" height="43"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="CuzaSasy3*Rimo" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="blw-Ou-8I8" userLabel="Password">
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="CuzaSasy3*Rimo" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="blw-Ou-8I8" userLabel="Password">
|
||||
<rect key="frame" x="8" y="0.0" width="284" height="31"/>
|
||||
<color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
|
||||
@@ -1248,7 +1248,7 @@
|
||||
<outlet property="delegate" destination="W2g-yv-V3V" id="YKp-IE-zEQ"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="3" contentMode="left" text="> age of the universe" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="wfM-xz-roR" userLabel="Strength">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="3" contentMode="left" misplaced="YES" text="> age of the universe" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="wfM-xz-roR" userLabel="Strength">
|
||||
<rect key="frame" x="0.0" y="31" width="300" height="12"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="10"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -1298,7 +1298,7 @@
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LvK-28-fbm" userLabel="Settings Container">
|
||||
<rect key="frame" x="300" y="0.0" width="300" height="100"/>
|
||||
<subviews>
|
||||
<button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IKd-Ot-0n4" userLabel="Upgrade">
|
||||
<button opaque="NO" alpha="0.5" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IKd-Ot-0n4" userLabel="Upgrade">
|
||||
<rect key="frame" x="-15" y="56" width="44" height="44"/>
|
||||
<accessibility key="accessibilityConfiguration" hint="Upgrades the password."/>
|
||||
<constraints>
|
||||
@@ -1318,7 +1318,7 @@
|
||||
<action selector="doUpgrade:" destination="W2g-yv-V3V" eventType="touchUpInside" id="kTZ-AM-qGa"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" alpha="0.5" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vGk-t6-hZn" userLabel="Answers">
|
||||
<button opaque="NO" alpha="0.5" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vGk-t6-hZn" userLabel="Answers">
|
||||
<rect key="frame" x="29" y="56" width="44" height="44"/>
|
||||
<accessibility key="accessibilityConfiguration" hint="Upgrades the password."/>
|
||||
<constraints>
|
||||
@@ -1338,7 +1338,7 @@
|
||||
<segue destination="aow-In-vb8" kind="custom" identifier="answers" customClass="MPOverlaySegue" id="5Wo-YZ-8HZ"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" text="1" textAlignment="right" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="PKP-M9-T8E" userLabel="Counter">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.5" contentMode="left" misplaced="YES" text="1" textAlignment="right" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="PKP-M9-T8E" userLabel="Counter">
|
||||
<rect key="frame" x="73" y="67" width="7" height="21.5"/>
|
||||
<accessibility key="accessibilityConfiguration" hint="Site's counter."/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="17"/>
|
||||
@@ -1599,14 +1599,14 @@
|
||||
<outlet property="delegate" destination="nkY-z6-8jd" id="ENG-q5-XwX"/>
|
||||
</connections>
|
||||
</searchBar>
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LEX-BK-PdS" userLabel="Bad Name Tip">
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LEX-BK-PdS" userLabel="Bad Name Tip">
|
||||
<rect key="frame" x="37" y="86" width="300.5" height="75.5"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black_top.png" translatesAutoresizingMaskIntoConstraints="NO" id="Rt5-v4-I0R">
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" misplaced="YES" image="tip_basic_black_top.png" translatesAutoresizingMaskIntoConstraints="NO" id="Rt5-v4-I0R">
|
||||
<rect key="frame" x="0.0" y="0.0" width="300.5" height="75.5"/>
|
||||
<rect key="contentStretch" x="0.050000000000000003" y="0.49999999999999994" width="0.90000000000000002" height="0.20000000000000001"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" verticalCompressionResistancePriority="1000" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="Eie-8u-hV2">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" verticalCompressionResistancePriority="1000" misplaced="YES" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="Eie-8u-hV2">
|
||||
<rect key="frame" x="20" y="26" width="260.5" height="43.5"/>
|
||||
<string key="text">Try using exclusively bare domain names.
|
||||
Avoid capitals and use @ to include a user name.
|
||||
@@ -1750,7 +1750,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<rect key="frame" x="0.0" y="0.5" width="375" height="333.5"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1lc-e7-Qme" userLabel="Emergency Generator">
|
||||
<view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1lc-e7-Qme" userLabel="Emergency Generator">
|
||||
<rect key="frame" x="20" y="140" width="335" height="387"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Emergency Generator" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="4Lh-s0-Dbt">
|
||||
@@ -1761,7 +1761,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<size key="shadowOffset" width="0.0" height="1"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Generate your password without logging in. Great for if you're borrowing a friend's device or are having trouble logging in." lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="vHS-3A-Tae">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" misplaced="YES" text="Generate your password without logging in. Great for if you're borrowing a friend's device or are having trouble logging in." lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="vHS-3A-Tae">
|
||||
<rect key="frame" x="20" y="49" width="295" height="51.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Thin" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -1769,7 +1769,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<size key="shadowOffset" width="0.0" height="1"/>
|
||||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Your Name" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="XAC-Da-lpf" userLabel="User Name">
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Your Name" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="XAC-Da-lpf" userLabel="User Name">
|
||||
<rect key="frame" x="20" y="109" width="295" height="30"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="words" keyboardAppearance="alert" returnKeyType="next" enablesReturnKeyAutomatically="YES"/>
|
||||
@@ -1778,7 +1778,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<outlet property="delegate" destination="osn-5H-SWW" id="VQI-Lq-GWG"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Your Master Password" clearsOnBeginEditing="YES" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="J46-0E-no3" userLabel="Master Password">
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Your Master Password" clearsOnBeginEditing="YES" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="J46-0E-no3" userLabel="Master Password">
|
||||
<rect key="frame" x="20" y="147" width="295" height="30"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardAppearance="alert" returnKeyType="next" enablesReturnKeyAutomatically="YES" secureTextEntry="YES"/>
|
||||
@@ -1787,7 +1787,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<outlet property="delegate" destination="osn-5H-SWW" id="bpf-YA-5XP"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Site Name" clearsOnBeginEditing="YES" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="56H-xR-09J" userLabel="Site Name">
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Site Name" clearsOnBeginEditing="YES" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="56H-xR-09J" userLabel="Site Name">
|
||||
<rect key="frame" x="20" y="185" width="295" height="30"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="URL" keyboardAppearance="alert" returnKeyType="done" enablesReturnKeyAutomatically="YES"/>
|
||||
@@ -1796,7 +1796,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<outlet property="delegate" destination="osn-5H-SWW" id="QgA-TS-5KG"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="e4b-Iv-Pk9" userLabel="Type">
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="e4b-Iv-Pk9" userLabel="Type">
|
||||
<rect key="frame" x="20" y="223" width="295" height="29"/>
|
||||
<segments>
|
||||
<segment title="Max"/>
|
||||
@@ -1811,7 +1811,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<action selector="controlChanged:" destination="osn-5H-SWW" eventType="valueChanged" id="sRc-3g-wqY"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Counter" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="cAo-K2-E23">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" misplaced="YES" text="Counter" lineBreakMode="tailTruncation" numberOfLines="0" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="cAo-K2-E23">
|
||||
<rect key="frame" x="20" y="262.5" width="64" height="21.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -1819,13 +1819,13 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<color key="shadowColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<size key="shadowOffset" width="0.0" height="1"/>
|
||||
</label>
|
||||
<stepper opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" maximumValue="100" translatesAutoresizingMaskIntoConstraints="NO" id="ZPT-EI-yuv" userLabel="Counter">
|
||||
<stepper opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" maximumValue="100" translatesAutoresizingMaskIntoConstraints="NO" id="ZPT-EI-yuv" userLabel="Counter">
|
||||
<rect key="frame" x="221" y="259" width="94" height="29"/>
|
||||
<connections>
|
||||
<action selector="controlChanged:" destination="osn-5H-SWW" eventType="valueChanged" id="eQA-3X-uc9"/>
|
||||
</connections>
|
||||
</stepper>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="1" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="3Cd-XH-Wau">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" misplaced="YES" text="1" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="3Cd-XH-Wau">
|
||||
<rect key="frame" x="206" y="262.5" width="7" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -1866,10 +1866,10 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
</button>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="4sN-hm-xio">
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" misplaced="YES" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="4sN-hm-xio">
|
||||
<rect key="frame" x="149" y="329" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="XapaNuwjFihn6$" textAlignment="center" lineBreakMode="clip" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bHR-he-dnZ" userLabel="Password Label">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="XapaNuwjFihn6$" textAlignment="center" lineBreakMode="clip" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bHR-he-dnZ" userLabel="Password Label">
|
||||
<rect key="frame" x="20" y="328" width="295" height="39"/>
|
||||
<gestureRecognizers/>
|
||||
<fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="30"/>
|
||||
@@ -1880,7 +1880,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<outletCollection property="gestureRecognizers" destination="gJb-50-mjy" appends="YES" id="3Ho-tp-mDE"/>
|
||||
</connections>
|
||||
</label>
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="beo-cJ-jIn" userLabel="View - Content Tip">
|
||||
<view userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="beo-cJ-jIn" userLabel="View - Content Tip">
|
||||
<rect key="frame" x="62" y="287.5" width="210" height="60"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="tip_basic_black.png" translatesAutoresizingMaskIntoConstraints="NO" id="nyL-cO-aPa">
|
||||
@@ -2082,7 +2082,7 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<pageControl opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="3" translatesAutoresizingMaskIntoConstraints="NO" id="8A2-ly-WTX">
|
||||
<rect key="frame" x="168" y="630" width="39" height="37"/>
|
||||
</pageControl>
|
||||
<collectionView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" minimumZoomScale="0.0" maximumZoomScale="0.0" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="i2y-lo-HXR">
|
||||
<collectionView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" misplaced="YES" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" minimumZoomScale="0.0" maximumZoomScale="0.0" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="i2y-lo-HXR">
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="476"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="m8O-kY-22j">
|
||||
@@ -2122,13 +2122,13 @@ eg. apple.com, rmitchell@twitter.com</string>
|
||||
<outlet property="delegate" destination="z9O-w0-6oR" id="RcD-gy-C1W"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="To begin, tap the "New User" icon and add yourself as a user to the application." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ciw-56-nNy" userLabel="Caption">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" misplaced="YES" text="To begin, tap the "New User" icon and add yourself as a user to the application." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ciw-56-nNy" userLabel="Caption">
|
||||
<rect key="frame" x="8" y="548" width="359" height="82"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="13"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label hidden="YES" opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Oop-Ff-gbz" userLabel="Caption Height Strut">
|
||||
<label hidden="YES" opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Oop-Ff-gbz" userLabel="Caption Height Strut">
|
||||
<rect key="frame" x="8" y="548" width="1" height="82"/>
|
||||
<string key="text" base64-UTF8="YES">
|
||||
CgoKCgoKCgoKCgoKCg
|
||||
@@ -2308,7 +2308,7 @@ Suspendisse potenti. Etiam ut nisi id augue tempor ultrices et sit amet sapien.
|
||||
<rect key="frame" x="163" y="532" width="51" height="31"/>
|
||||
<color key="onTintColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</switch>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e80-98-V6D">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e80-98-V6D">
|
||||
<rect key="frame" x="20" y="137" width="335" height="151.5"/>
|
||||
<string key="text">The right balance between security and convenience is often very personal.
|
||||
|
||||
@@ -2392,7 +2392,7 @@ However, it means that anyone who finds your device unlocked can do the same.</s
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" usesAttributedText="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J90-SQ-ljR">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" usesAttributedText="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J90-SQ-ljR">
|
||||
<rect key="frame" x="20" y="136" width="335" height="522.5"/>
|
||||
<attributedString key="attributedText">
|
||||
<fragment content="The passwords generated by this app are not stored but ">
|
||||
@@ -2580,7 +2580,7 @@ See </string>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="cef-sc-aph">
|
||||
<rect key="frame" x="168" y="100" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="3" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FWu-V6-mLT">
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="3" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FWu-V6-mLT">
|
||||
<rect key="frame" x="200" y="-6" width="92.5" height="132"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="110"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -2645,7 +2645,7 @@ See </string>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="X2g-Go-2Hz">
|
||||
<rect key="frame" x="169" y="100" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N9y-ue-L8d">
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="N9y-ue-L8d">
|
||||
<rect key="frame" x="200" y="-6" width="92.5" height="132"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="110"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -2691,7 +2691,7 @@ See </string>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="96"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="iOS Integration" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Zch-DS-J3I">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" misplaced="YES" text="iOS Integration" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Zch-DS-J3I">
|
||||
<rect key="frame" x="20" y="226" width="244" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -2710,13 +2710,13 @@ See </string>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="yUe-TX-fli">
|
||||
<rect key="frame" x="169" y="100" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ec8-P9-KPY">
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ec8-P9-KPY">
|
||||
<rect key="frame" x="200" y="-6" width="92.5" height="132"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="110"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Coming Soon" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3jH-eX-9N2">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" misplaced="YES" text="Coming Soon" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3jH-eX-9N2">
|
||||
<rect key="frame" x="272" y="226" width="83" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -2756,7 +2756,7 @@ See </string>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="96"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="TouchID Login" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="e1D-jp-GBs">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" misplaced="YES" text="TouchID Login" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="e1D-jp-GBs">
|
||||
<rect key="frame" x="20" y="226" width="244.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -2775,13 +2775,13 @@ See </string>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="Dv5-t7-lL1">
|
||||
<rect key="frame" x="169" y="100" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yZX-ns-8oV">
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="✔︎" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yZX-ns-8oV">
|
||||
<rect key="frame" x="200" y="-6" width="92.5" height="132"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="110"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Coming Soon" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZGg-O6-rsg">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" misplaced="YES" text="Coming Soon" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZGg-O6-rsg">
|
||||
<rect key="frame" x="272" y="226" width="83" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -2821,13 +2821,13 @@ See </string>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="96"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Fuel Top-Up" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Jnv-uN-xeg">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" ambiguous="YES" misplaced="YES" text="Fuel Top-Up" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Jnv-uN-xeg">
|
||||
<rect key="frame" x="20" y="226" width="292" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fz2-AO-aGW">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" ambiguous="YES" misplaced="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fz2-AO-aGW">
|
||||
<rect key="frame" x="20" y="254" width="335" height="132"/>
|
||||
<string key="text">You really love Master Password and how it's solving your password problems. You're eager to encourage the maintenance, technical support and development of new features. I am a one-man shop, fuel enables me to allocate more work hours to Master Password.
|
||||
|
||||
@@ -2840,22 +2840,22 @@ UPCOMING:
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="thumb_fuel.png" translatesAutoresizingMaskIntoConstraints="NO" id="PnG-hP-syh">
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" image="thumb_fuel.png" translatesAutoresizingMaskIntoConstraints="NO" id="PnG-hP-syh">
|
||||
<rect key="frame" x="88" y="20" width="198" height="198"/>
|
||||
</imageView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="eS4-59-Xny">
|
||||
<activityIndicatorView hidden="YES" opaque="NO" tag="2" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" ambiguous="YES" misplaced="YES" hidesWhenStopped="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="eS4-59-Xny">
|
||||
<rect key="frame" x="169" y="100" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="$2.95" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EbU-DV-fKF">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" ambiguous="YES" misplaced="YES" text="$2.95" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EbU-DV-fKF">
|
||||
<rect key="frame" x="320" y="226" width="34.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="14"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="meter_fuel.png" translatesAutoresizingMaskIntoConstraints="NO" id="aGb-QC-A92">
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" image="meter_fuel.png" translatesAutoresizingMaskIntoConstraints="NO" id="aGb-QC-A92">
|
||||
<rect key="frame" x="261" y="208" width="12" height="10"/>
|
||||
</imageView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dsR-fr-dY4">
|
||||
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dsR-fr-dY4">
|
||||
<rect key="frame" x="20" y="20" width="107" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="W6p-kB-VBX"/>
|
||||
@@ -2868,7 +2868,7 @@ UPCOMING:
|
||||
<action selector="toggleFuelConsumption:" destination="pdl-xv-zjX" eventType="touchUpInside" id="NkB-Dy-IeY"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kYb-j4-32C">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" misplaced="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kYb-j4-32C">
|
||||
<rect key="frame" x="20" y="64" width="117.5" height="26.5"/>
|
||||
<string key="text">fuel left: 0.3 work hours
|
||||
invested: 3.7 work hours</string>
|
||||
@@ -2920,7 +2920,7 @@ invested: 3.7 work hours</string>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="Vjt-7c-BJ4">
|
||||
<rect key="frame" x="169" y="20" width="37" height="37"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" text="Loading products..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ARC-xH-0U0">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" misplaced="YES" text="Loading products..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ARC-xH-0U0">
|
||||
<rect key="frame" x="114.5" y="97" width="145.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -2944,7 +2944,7 @@ invested: 3.7 work hours</string>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="152"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IOk-WZ-HJ8">
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IOk-WZ-HJ8">
|
||||
<rect key="frame" x="20" y="58" width="335" height="26"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Restore Previous Purchases">
|
||||
@@ -2954,7 +2954,7 @@ invested: 3.7 work hours</string>
|
||||
<action selector="restorePurchases:" destination="pdl-xv-zjX" eventType="touchUpInside" id="lKu-PL-PfX"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bCe-a3-cDC">
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" ambiguous="YES" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bCe-a3-cDC">
|
||||
<rect key="frame" x="8" y="24" width="359" height="26"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Send Thanks">
|
||||
@@ -2964,7 +2964,7 @@ invested: 3.7 work hours</string>
|
||||
<action selector="sendThanks:" destination="pdl-xv-zjX" eventType="touchUpInside" id="r5l-3U-jCA"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" text="© 2012-2014, Maarten Billemont (lhunath)" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DxV-2L-bxL">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" ambiguous="YES" text="© 2012-2014, Maarten Billemont (lhunath)" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DxV-2L-bxL">
|
||||
<rect key="frame" x="20" y="4" width="335" height="12"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Thin" family="Exo 2.0" pointSize="10"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -3042,13 +3042,13 @@ invested: 3.7 work hours</string>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="96"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Answer for lyndir.com:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tal-1I-HQw" userLabel="Title Label">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" misplaced="YES" text="Answer for lyndir.com:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tal-1I-HQw" userLabel="Title Label">
|
||||
<rect key="frame" x="8" y="8" width="180" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="hok petwuvaqu xixo" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="GfC-j4-Qx7" userLabel="Answer Field">
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="hok petwuvaqu xixo" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="GfC-j4-Qx7" userLabel="Answer Field">
|
||||
<rect key="frame" x="8" y="48" width="359" height="43"/>
|
||||
<color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
|
||||
@@ -3132,7 +3132,7 @@ invested: 3.7 work hours</string>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="96"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="mother" textAlignment="center" minimumFontSize="14" clearButtonMode="unlessEditing" translatesAutoresizingMaskIntoConstraints="NO" id="T2F-PD-Nw8" userLabel="Question Field">
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="mother" textAlignment="center" minimumFontSize="14" clearButtonMode="unlessEditing" translatesAutoresizingMaskIntoConstraints="NO" id="T2F-PD-Nw8" userLabel="Question Field">
|
||||
<rect key="frame" x="8" y="19" width="359" height="30"/>
|
||||
<color key="backgroundColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="0.5" colorSpace="calibratedRGB"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -3143,13 +3143,13 @@ invested: 3.7 work hours</string>
|
||||
<outlet property="delegate" destination="iFm-3w-hOv" id="olS-Rx-56Y"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="pifm gup balvabi yiz" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="3xA-ez-efa" userLabel="Answer Field">
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="pifm gup balvabi yiz" textAlignment="center" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="3xA-ez-efa" userLabel="Answer Field">
|
||||
<rect key="frame" x="20" y="90" width="335" height="31"/>
|
||||
<color key="textColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<fontDescription key="fontDescription" name="SourceCodePro-Black" family="Source Code Pro" pointSize="24"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="alphabet" keyboardAppearance="alert" returnKeyType="next"/>
|
||||
</textField>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Enter the single most significant word in the question above." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qqg-Ny-7Po">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" misplaced="YES" text="Enter the single most significant word in the question above." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qqg-Ny-7Po">
|
||||
<rect key="frame" x="8" y="57" width="359" height="13.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Thin" family="Exo 2.0" pointSize="11"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -3242,7 +3242,7 @@ invested: 3.7 work hours</string>
|
||||
<rect key="frame" x="163" y="532" width="51" height="31"/>
|
||||
<color key="onTintColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</switch>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yx2-Eh-hM0">
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yx2-Eh-hM0">
|
||||
<rect key="frame" x="20" y="137" width="335" height="202"/>
|
||||
<string key="text">To make it easy for you to recognize and copy passwords manually using a keyboard or other means, Master Password makes your site passwords visible on your screen by default.
|
||||
|
||||
|
||||
31
MasterPassword/homebrew-mpw.rb
Normal file
31
MasterPassword/homebrew-mpw.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
class Mpw < Formula
|
||||
homepage "http://masterpasswordapp.com"
|
||||
url "https://ssl.masterpasswordapp.com/mpw-2.1-cli4-0-gf6b2287.tar.gz"
|
||||
sha1 "036b3d8f4bd6f0676ae16e7e9c3de65f6030874f"
|
||||
version "2.1-cli4"
|
||||
|
||||
depends_on "automake" => :build
|
||||
depends_on "autoconf" => :build
|
||||
depends_on "openssl"
|
||||
|
||||
resource "libscrypt" do
|
||||
url "http://masterpasswordapp.com/libscrypt-b12b554.tar.gz"
|
||||
sha1 "ee871e0f93a786c4e3622561f34565337cfdb815"
|
||||
end
|
||||
|
||||
def install
|
||||
resource("libscrypt").stage buildpath/"lib/scrypt"
|
||||
touch "lib/scrypt/.unpacked"
|
||||
|
||||
ENV["targets"] = "mpw mpw-tests"
|
||||
system "./build"
|
||||
system "./mpw-tests"
|
||||
|
||||
bin.install "mpw"
|
||||
end
|
||||
|
||||
test do
|
||||
assert_equal "Jejr5[RepuSosp",
|
||||
shell_output("mpw -u 'Robert Lee Mitchell' -P 'banana colored duckling' masterpasswordapp.com").strip
|
||||
end
|
||||
end
|
||||
@@ -255,7 +255,7 @@
|
||||
</pre></code>
|
||||
|
||||
<p>
|
||||
The result is a 64-byte <code>key</code> derived from the user's master password. This key will be fed into the rest of the algorithm to produce output passwords that are as private to the user as his master password is.
|
||||
The result is a 64-byte <code>key</code> derived from the user's master password. This key will be fed into the rest of the algorithm to produce output passwords that are as private to the user as their master password is.
|
||||
</p>
|
||||
|
||||
<h2>Combining The Inputs</h2>
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
<p>Another strategy is by "encoding" something you already know. This can seem like a good way to make memorable passwords, but recalling the "encoding" you used two years later can be tricky. This also makes it much easier for attackers that know you to find your password.</p>
|
||||
<p>Master Password itself generates very random passwords that look semi-legible, for instance <code>Togu3]ToxiBuzb</code>. Such passwords have been found to be very memorable while also being very high in entropy (hard to guess).</p>
|
||||
<p>A strategy that's gaining traction lately is that of combining words into a sentence. Some claim it's best for the sentence to make no grammatical sense, others dispute these claims. It's a fact, though, that if your attacker doesn't expect such a password, they're nearly impossible to defeat.</p>
|
||||
<p><iframe width="420" height="315" src="//www.youtube.com/embed/MSyIhapMdI8?start=109" frameborder="0" allowfullscreen></iframe></p>
|
||||
<p>Let's sum these strategies up in a table, note that this type of comparison is very subjective.</p>
|
||||
<table>
|
||||
<caption>Time to crack a master password</caption>
|
||||
|
||||
@@ -82,8 +82,7 @@
|
||||
<a title="iPhone, iPad, iPod touch" href="https://itunes.apple.com/app/id510296984" onclick="_gaq.push(['_trackPageview', '/outbound/ios']);">iPhone / iPad<img class="popup" src="img/ios.png" /></a> |
|
||||
<a title="Mac (graphical interface)" href="https://itunes.apple.com/app/id662763204" onclick="_gaq.push(['_trackPageview', '/outbound/gui/mac']);">Mac<img class="popup border" src="img/mac-gui.png" /></a> |
|
||||
<a title="Mac, Linux, UNIX, Windows (graphical interface)" href="https://ssl.masterpasswordapp.com/masterpassword-gui.jar" onclick="_gaq.push(['_trackPageview', '/outbound/gui/java']);">Desktop (Java)<img class="popup" src="img/java-gui.png" /></a> |
|
||||
Terminal (<a title="Mac, Linux, UNIX, Windows (command line interface)" href="https://ssl.masterpasswordapp.com/masterpassword-cli.zip" onclick="_gaq.push(['_trackPageview', '/outbound/cli/java']);">Java<img class="popup" src="img/java-cli.png" /></a> /
|
||||
<a title="Mac, Linux, UNIX, Windows (command line interface)" href="https://github.com/Lyndir/MasterPassword/tree/master/MasterPassword/C" onclick="_gaq.push(['_trackPageview', '/outbound/cli/c']);">Native C<img class="popup" src="img/c-cli.png" /></a>) |
|
||||
Terminal (<a title="Mac, Linux, POSIX (command line interface)" href="https://ssl.masterpasswordapp.com/masterpassword-cli.tar.gz" onclick="_gaq.push(['_trackPageview', '/outbound/cli/c']);">Native C<img class="popup" src="img/c-cli.png" /></a>) |
|
||||
<a title="Android" href="https://ssl.masterpasswordapp.com/masterpassword-android.apk" onclick="_gaq.push(['_trackPageview', '/outbound/android']);">Android (Beta)<img class="popup" src="img/android.png" /></a> |
|
||||
<a title="JavaScript" href="https://js.masterpasswordapp.com/" onclick="_gaq.push(['_trackPageview', '/outbound/js']);">Web (Beta)<img class="popup border" src="img/web.png" /></a>
|
||||
</h4>
|
||||
|
||||
1
Site/2013-05/masterpassword-cli.tar.gz
Symbolic link
1
Site/2013-05/masterpassword-cli.tar.gz
Symbolic link
@@ -0,0 +1 @@
|
||||
mpw-2.1-cli4-0-gf6b2287.tar.gz
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
1fbb6b0754c9ea1ecf733c260dc06200d2eeed6c
|
||||
3932857c2117b8a399fdcb4fa888e9dc1a6818ee
|
||||
|
||||
Binary file not shown.
1
Site/2013-05/mpw-2.1-cli2-2-g82c96dd.tar.gz
Symbolic link
1
Site/2013-05/mpw-2.1-cli2-2-g82c96dd.tar.gz
Symbolic link
@@ -0,0 +1 @@
|
||||
../../MasterPassword/C/mpw-2.1-cli2-2-g82c96dd.tar.gz
|
||||
1
Site/2013-05/mpw-2.1-cli3-0-g438daf2.tar.gz
Symbolic link
1
Site/2013-05/mpw-2.1-cli3-0-g438daf2.tar.gz
Symbolic link
@@ -0,0 +1 @@
|
||||
../../MasterPassword/C/mpw-2.1-cli3-0-g438daf2.tar.gz
|
||||
1
Site/2013-05/mpw-2.1-cli4-0-gf6b2287.tar.gz
Symbolic link
1
Site/2013-05/mpw-2.1-cli4-0-gf6b2287.tar.gz
Symbolic link
@@ -0,0 +1 @@
|
||||
../../MasterPassword/C/mpw-2.1-cli4-0-gf6b2287.tar.gz
|
||||
@@ -296,14 +296,14 @@
|
||||
<h3 id="masterkey" class="inline">The Master Key</h3>
|
||||
<p>The first part of the process it to obtain a very strong "token" of your personal identity. We call this token your <em>master key</em>, because it is very much like the one and only <strong>main key that opens all your doors</strong>. It is a personal key, it represents your identity.</p>
|
||||
<p>The master key is derived from your name and your master password, and thrown away as soon as it's no longer needed to minimize the risk of loss.</p>
|
||||
<p>Since it's vital that nobody else can gain access to your master key, it's important that the process of deriving the key is insurmountably difficult. An attacker could try a brute-force attack against your master key or password by convincing you to make an account on his website, and then guessing at your master password or your master key until he finds one that gives him your password for his fake site.</p>
|
||||
<p>Since it's vital that nobody else can gain access to your master key, it's important that the process of deriving the key is insurmountably difficult. An attacker could try a brute-force attack against your master key or password by convincing you to make an account on their website, and then guessing at your master password or your master key until he finds one that gives him your password for their fake site.</p>
|
||||
<p>These are two different types of brute-force attacks and we need to make sure to defeat both of them.</p>
|
||||
<p>To defeat a brute-force attack against your master key, we make sure the master key is sufficiently high in entropy. Since the master key is a 256-bit key, an attacker would now have to make up to <code>2<sup>256</sup></code> guesses, or try <code>115792089237316195423570985008687907853269984665640564039457584007913129639936</code> master keys before finding the right one. Even at an ambitious rate of 2 billion tries per second, it would take several times the age of the universe to try all of them.
|
||||
<p>A brute-force attack against your master password is more feasible, since your master password will be tiny compared to such a huge master key.</p>
|
||||
<p>Even if you used an 8-character evenly distributed random alphanumeric password (such as <code>yIp6X2qd</code>), a smart attacker could brute-force such a password in less than <em>1.7 days</em>.</p>
|
||||
<p>To solve this problem, we introduce an expensive <q>scrypt</q>-based <em>key derivation</em> step. <em>scrypt</em> specifically improves on standard key derivation techniques by not only wasting a lot of <em>CPU time</em>, but also consuming huge amounts of <em>RAM</em>. We need to be careful to choose the right parameters so that logging into Master Password doesn't take too long on weaker mobile devices while the possibility of guessing at passwords is sufficiently
|
||||
crippled for attackers. The theory is, the longer it takes for an attacker to try out one guess of your master password, the longer it'll take him to find the right one. We pull this theory into the extreme so that guessing your password now takes <strong>2151076 years</strong> instead of <em>1.7 days</em> while logging into Master Password on an iPhone 4S takes no more than 3 seconds.</p>
|
||||
<p>It bears note that <em>scrypt</em>'s approach is specifically interesting because it costs both a lot of CPU and a lot of RAM to derive a master key. That means that the more computers an attacker buys, the more his $ cost goes up. CPU and RAM are expensive, and forcing the derivation to use a lot instead of minuscule amounts causes the $ cost of a brute-force attack to become phenomenal.</p>
|
||||
<p>It bears note that <em>scrypt</em>'s approach is specifically interesting because it costs both a lot of CPU and a lot of RAM to derive a master key. That means that the more computers an attacker buys, the more their $ cost goes up. CPU and RAM are expensive, and forcing the derivation to use a lot instead of minuscule amounts causes the $ cost of a brute-force attack to become phenomenal.</p>
|
||||
<p>Given these solutions, we feel confident Master Password is adequately protected against attacks on your private master key.</p>
|
||||
</div>
|
||||
<div class="hlvl">
|
||||
|
||||
@@ -3,4 +3,4 @@ set -e
|
||||
|
||||
cd "${BASH_SOURCE[0]%/*}"
|
||||
s3cmd sync --exclude '.git/**' --delete-removed --follow-symlinks --preserve --acl-public --reduced-redundancy . s3://masterpasswordapp.com/
|
||||
rsync -avP --no-group . satura.lyndir.com:/usr/local/www/masterpasswordapp.com/htdocs-secure/
|
||||
rsync -avPL --no-group . satura.lyndir.com:/usr/local/www/masterpasswordapp.com/htdocs-secure/
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
<p>In fact, just stop thinking about passwords at all.</p>
|
||||
<p>Master Password users have no more passwords. They have a password. Their password is their single master key for unlocking all doors.</p>
|
||||
|
||||
<a name="how"></a>
|
||||
<h2>One, two, enter.</h2>
|
||||
<p>As a Master Password user, there are about three steps to entering any site:</p>
|
||||
<ol>
|
||||
@@ -118,6 +119,7 @@
|
||||
<li>You can stop sharing the keys to your digital life with online password websites that promise all the military grade encryption while being gagged and tapped by a government agency.</li>
|
||||
</ul>
|
||||
|
||||
<a name="others"></a>
|
||||
<h2>I use this other password manager, and it's awesome.</h2>
|
||||
<p>I shall not endeavour to quarrel with the point on the awesome scale of your other password manager. That said, Master Password was designed from the ground up specifically because of the many flaws that existed in all the popular password managers at the time. And the times haven't changed for the better since.</p>
|
||||
<p>I'm going to provide an excessively brief description of the primary flaws other password managers suffer, which Master Password is free from. Please <a href="support.html">contact me</a> if you have something to add, ask or correct.</p>
|
||||
@@ -139,6 +141,7 @@
|
||||
|
||||
</ul>
|
||||
|
||||
<a name="cons"></a>
|
||||
<h2>What are Master Password's cons? Or is it flawless?</h2>
|
||||
<p>Master Password also has cons. Let's be frank and list the cons that the other solutions generally don't suffer:</p>
|
||||
<p><em>Cons:</em> Changing your master password requires you to update all your site passwords. A compromised or forgotten master password requires you to do the same.</p>
|
||||
@@ -154,9 +157,10 @@
|
||||
<p>Two factor authentication is defined as authenticating yourself with two methods that are so distinct that a single attack cannot compromise both. Many sites claim to use two-factor authentication but actually rely only on an extra password hidden in an app on your phone or computer. If an attacker can steal your master password, he can probably download the hidden password too. Or read in your two-factor response while you're typing it in. On top of that, you're using a password manager: after your "two-factor" authentication, you get a single password to perform another one-factor authentication with a site. As a hacker, I'd go for the weakest link to break your chain.</li>
|
||||
</ul>
|
||||
|
||||
<a name="trust"></a>
|
||||
<h2>You speak of trust, how can I trust you?</h2>
|
||||
<p>A very valid question, and arguably the most important one to ask!</p>
|
||||
<p>Trust is a very difficult thing to guarantee. Powerful entities will solicit your trust by appearing with it and coming well recommended. Trust can also be assured by legalese or contracts. If you have the means and energy to hold an entity responsible for his claims and actions, this might be sufficient for you.</p>
|
||||
<p>Trust is a very difficult thing to guarantee. Powerful entities will solicit your trust by appearing with it and coming well recommended. Trust can also be assured by legalese or contracts. If you have the means and energy to hold an entity responsible for their claims and actions, this might be sufficient for you.</p>
|
||||
<p>Most of us mere mortals cannot afford this level of trust enforcement, however. We're mostly left in the position of trusting claims blindly, in the hopes that companies will not violate those claims for fear of taking a seizable public-relations hit.</p>
|
||||
<h3>I propose that none of these forms of trust are sufficient adequate.</h3>
|
||||
<p>In fact, Master Password is what it is because it aims to avoid any requirement of trust in the solution's author. Master Password requires no services or proprietary storage format. I've published Master Password's algorithm for you to inspect and licensed to you the full source code to the implementations for you to use.</p>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<body>
|
||||
<header>
|
||||
<p><strong>BETA</strong> - This site may not yet work on your browser.<br>
|
||||
Passwords are generated locally, your master password is not sent to any server. See <a href="https://github.com/Lyndir/MasterPassword/tree/master/Site/2013-05/mpw-js">the source</a>.</p>
|
||||
Passwords are generated locally, your master password is not sent to any server. See <a href="https://github.com/Lyndir/MasterPassword/tree/master/Site/mpw-js">the source</a>.</p>
|
||||
<span id="error"></span>
|
||||
</header>
|
||||
<section id="identity" class="active"><form action="#">
|
||||
@@ -51,15 +51,15 @@
|
||||
<footer>
|
||||
<p>This page was made possible thanks to <a href="https://tomthorogood.co.uk/" title="Tom Thorogood">tmthrgd</a>'s <a href="https://github.com/tmthrgd/mpw-js">mpw-js</a>.<br>
|
||||
<em><a href="http://masterpasswordapp.com">Master Password</a> is a security product and algorithm by <a href="http://www.lhunath.com" title="Maarten Billemont">Maarten Billemont</a>, <a href="http://www.lyndir.com">Lyndir</a> (© 2011-2014).</em><br>
|
||||
Usage implies agreement with our <a href="/privacy.html">privacy policy and disclaimer</a>.</p>
|
||||
Usage implies agreement with our <a href="http://masterpasswordapp.com/privacy.html">privacy policy and disclaimer</a>.</p>
|
||||
</footer>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script>window.jQuery || document.write('<script src="js/vendor/jquery-2.1.1.js"><\/script>')</script>
|
||||
<script>window.jQuery || document.write('<script src="js/vendor/jquery-2.1.1.min.js"><\/script>')</script>
|
||||
<script src="js/dependencies.js?2"></script>
|
||||
<script src="js/main.js?2"></script>
|
||||
<script src="js/dependencies.js?3"></script>
|
||||
<script src="js/main.js?3"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -41,7 +41,7 @@ window.setImmediate || document.write("<script src=js/mpw-js/" + esdir + "setImm
|
||||
|
||||
// Include the scrypt implementation
|
||||
var SCRYPTASM_PATH = (window.location + '').replace(/[^/]*(#[^#]*)?$/, 'js/mpw-js/scrypt-asm.js');
|
||||
document.write("<script src=js/mpw-js/" + esdir + "scrypt.js><\/script>");
|
||||
document.write("<script src=js/mpw-js/" + esdir + "scrypt.js?1><\/script>");
|
||||
|
||||
// Include the MPW class
|
||||
document.write("<script src=js/mpw-js/" + esdir + "mpw.js><\/script>");
|
||||
document.write("<script src=js/mpw-js/" + esdir + "mpw.js?1><\/script>");
|
||||
|
||||
Submodule Site/mpw-js/js/mpw-js updated: 768cfad320...442e418969
Reference in New Issue
Block a user