More restructuring and rewriting of the C code.
This commit is contained in:
parent
49da0b47c7
commit
0ccd545dd4
@ -2,6 +2,7 @@
|
|||||||
<profile version="1.0" is_locked="false">
|
<profile version="1.0" is_locked="false">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<option name="myLocal" value="false" />
|
<option name="myLocal" value="false" />
|
||||||
|
<inspection_tool class="Convert to string" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||||
<inspection_tool class="FunctionImplicitDeclarationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="FunctionImplicitDeclarationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="ImplicitIntegerAndEnumConversion" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="ImplicitIntegerAndEnumConversion" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="LossyEncoding" enabled="true" level="WARNING" enabled_by_default="true" />
|
<inspection_tool class="LossyEncoding" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
@ -9,6 +10,7 @@
|
|||||||
<inspection_tool class="OCNotLocalizedStringInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="OCNotLocalizedStringInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="OCUnusedMacroInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="OCUnusedMacroInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="OCUnusedMethodInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="OCUnusedMethodInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="Replace with subshell" enabled="true" level="INFO" enabled_by_default="true" />
|
||||||
<inspection_tool class="SignednessMismatch" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="SignednessMismatch" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
<inspection_tool class="UnavailableInDeploymentTarget" enabled="true" level="INFO" enabled_by_default="true" />
|
<inspection_tool class="UnavailableInDeploymentTarget" enabled="true" level="INFO" enabled_by_default="true" />
|
||||||
<inspection_tool class="UnusedLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
|
<inspection_tool class="UnusedLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
@ -216,9 +216,11 @@ mpw() {
|
|||||||
# optional features
|
# optional features
|
||||||
(( mpw_color )) && CFLAGS+=( -DCOLOR ) LDFLAGS+=( -l"curses" )
|
(( mpw_color )) && CFLAGS+=( -DCOLOR ) LDFLAGS+=( -l"curses" )
|
||||||
|
|
||||||
cc "${CFLAGS[@]}" -c types.c -o types.o "$@"
|
cc "${CFLAGS[@]}" "$@" -c mpw-algorithm.c -o mpw-algorithm.o
|
||||||
cc "${CFLAGS[@]}" -c mpw.c -o mpw.o "$@"
|
cc "${CFLAGS[@]}" "$@" -c mpw-types.c -o mpw-types.o
|
||||||
cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "types.o" "mpw.o" mpw-cli.c -o mpw "$@"
|
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
|
||||||
echo "done! Now run ./install or use ./mpw"
|
echo "done! Now run ./install or use ./mpw"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,8 +256,11 @@ mpw-bench() {
|
|||||||
-l"crypto"
|
-l"crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
cc "${CFLAGS[@]}" -c types.c -o types.o "$@"
|
cc "${CFLAGS[@]}" "$@" -c mpw-algorithm.c -o mpw-algorithm.o
|
||||||
cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "types.o" mpw-bench.c -o mpw-bench "$@"
|
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-bench.c -o mpw-bench
|
||||||
echo "done! Now use ./mpw-bench"
|
echo "done! Now use ./mpw-bench"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
#define _GNU_SOURCE
|
//
|
||||||
|
// mpw-algorithm.c
|
||||||
|
// MasterPassword
|
||||||
|
//
|
||||||
|
// Created by Maarten Billemont on 2014-12-20.
|
||||||
|
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <scrypt/sha256.h>
|
#include "mpw-types.h"
|
||||||
#include <scrypt/crypto_scrypt.h>
|
#include "mpw-util.h"
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
#define MP_N 32768
|
#define MP_N 32768
|
||||||
#define MP_r 8
|
#define MP_r 8
|
||||||
@ -16,33 +20,9 @@
|
|||||||
#define MP_dkLen 64
|
#define MP_dkLen 64
|
||||||
#define MP_hash PearlHashSHA256
|
#define MP_hash PearlHashSHA256
|
||||||
|
|
||||||
static void mpw_pushBuf(uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize) {
|
|
||||||
|
|
||||||
*bufferSize += pushSize;
|
|
||||||
*buffer = realloc( *buffer, *bufferSize );
|
|
||||||
uint8_t *pushDst = *buffer + *bufferSize - pushSize;
|
|
||||||
memcpy( pushDst, pushBuffer, pushSize );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpw_pushString(uint8_t **buffer, size_t *const bufferSize, const char *pushString) {
|
|
||||||
|
|
||||||
mpw_pushBuf( buffer, bufferSize, pushString, strlen( pushString ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpw_pushInt(uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt) {
|
|
||||||
|
|
||||||
mpw_pushBuf( buffer, bufferSize, &pushInt, sizeof( pushInt ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpw_free(void *const buffer, const size_t bufferSize) {
|
|
||||||
|
|
||||||
memset( buffer, 0, bufferSize );
|
|
||||||
free( buffer );
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPassword) {
|
const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPassword) {
|
||||||
|
|
||||||
const char *mpKeyScope = ScopeForVariant( MPSiteVariantPassword );
|
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||||
trc( "fullName: %s\n", fullName );
|
trc( "fullName: %s\n", fullName );
|
||||||
trc( "masterPassword: %s\n", masterPassword );
|
trc( "masterPassword: %s\n", masterPassword );
|
||||||
trc( "key scope: %s\n", mpKeyScope );
|
trc( "key scope: %s\n", mpKeyScope );
|
||||||
@ -56,18 +36,15 @@ const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPass
|
|||||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||||
if (!masterKeySalt)
|
if (!masterKeySalt)
|
||||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||||
trc( "masterKeySalt ID: %s\n", IDForBuf( masterKeySalt, masterKeySaltSize ) );
|
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||||
|
|
||||||
// Calculate the master key.
|
// Calculate the master key.
|
||||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||||
uint8_t *masterKey = (uint8_t *)malloc( MP_dkLen );
|
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||||
|
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||||
if (!masterKey)
|
if (!masterKey)
|
||||||
ftl( "Could not allocate master key: %d\n", errno );
|
ftl( "Could not allocate master key: %d\n", errno );
|
||||||
if (crypto_scrypt( (const uint8_t *)masterPassword, strlen( masterPassword ),
|
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||||
masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p, masterKey, MP_dkLen ) < 0)
|
|
||||||
ftl( "Could not generate master key: %d\n", errno );
|
|
||||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
|
||||||
trc( "masterKey ID: %s\n", IDForBuf( masterKey, MP_dkLen ) );
|
|
||||||
|
|
||||||
return masterKey;
|
return masterKey;
|
||||||
}
|
}
|
||||||
@ -75,7 +52,7 @@ const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPass
|
|||||||
const char *mpw_passwordForSite(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
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 char *siteScope = ScopeForVariant( siteVariant );
|
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||||
trc( "siteName: %s\n", siteName );
|
trc( "siteName: %s\n", siteName );
|
||||||
trc( "siteCounter: %d\n", siteCounter );
|
trc( "siteCounter: %d\n", siteCounter );
|
||||||
trc( "siteVariant: %d\n", siteVariant );
|
trc( "siteVariant: %d\n", siteVariant );
|
||||||
@ -95,28 +72,28 @@ const char *mpw_passwordForSite(const uint8_t *masterKey, const char *siteName,
|
|||||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||||
}
|
}
|
||||||
if (!sitePasswordInfo)
|
if (!sitePasswordInfo)
|
||||||
ftl( "Could not allocate site seed: %d\n", errno );
|
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||||
trc( "sitePasswordInfo ID: %s\n", IDForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||||
|
|
||||||
uint8_t sitePasswordSeed[32];
|
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||||
HMAC_SHA256_Buf( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize, sitePasswordSeed );
|
if (!sitePasswordSeed)
|
||||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
ftl( "Could not allocate site seed: %d\n", errno );
|
||||||
trc( "sitePasswordSeed ID: %s\n", IDForBuf( sitePasswordSeed, 32 ) );
|
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||||
|
|
||||||
// Determine the template.
|
// Determine the template.
|
||||||
const char *template = TemplateForType( siteType, sitePasswordSeed[0] );
|
const char *template = mpw_templateForType( siteType, sitePasswordSeed[0] );
|
||||||
trc( "type %d, template: %s\n", siteType, template );
|
trc( "type %d, template: %s\n", siteType, template );
|
||||||
if (strlen( template ) > 32)
|
if (strlen( template ) > 32)
|
||||||
ftl( "Template too long for password seed: %d", strlen( template ) );
|
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||||
|
|
||||||
// Encode the password from the seed using the template.
|
// Encode the password from the seed using the template.
|
||||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||||
for (int c = 0; c < strlen( template ); ++c) {
|
for (int c = 0; c < strlen( template ); ++c) {
|
||||||
sitePassword[c] = CharacterFromClass( template[c], sitePasswordSeed[c + 1] );
|
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],
|
trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1],
|
||||||
sitePassword[c] );
|
sitePassword[c] );
|
||||||
}
|
}
|
||||||
memset( sitePasswordSeed, 0, sizeof( sitePasswordSeed ) );
|
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||||
|
|
||||||
return sitePassword;
|
return sitePassword;
|
||||||
}
|
}
|
18
MasterPassword/C/mpw-algorithm.h
Normal file
18
MasterPassword/C/mpw-algorithm.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// mpw-algorithm.h
|
||||||
|
// MasterPassword
|
||||||
|
//
|
||||||
|
// Created by Maarten Billemont on 2014-12-20.
|
||||||
|
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
/** Derive the master key for a user based on their name and master password.
|
||||||
|
* @return A new 64-byte allocated buffer. */
|
||||||
|
const uint8_t *mpw_masterKeyForUser(
|
||||||
|
const char *fullName, const char *masterPassword);
|
||||||
|
|
||||||
|
/** Encode a password for the site from the given master key and site parameters.
|
||||||
|
* @return A newly allocated string. */
|
||||||
|
const char *mpw_passwordForSite(
|
||||||
|
const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||||
|
const MPSiteVariant siteVariant, const char *siteContext);
|
@ -1,20 +1,22 @@
|
|||||||
#include <sys/time.h>
|
//
|
||||||
|
// mpw-bench.c
|
||||||
|
// MasterPassword
|
||||||
|
//
|
||||||
|
// Created by Maarten Billemont on 2014-12-20.
|
||||||
|
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <scrypt/sha256.h>
|
#include <scrypt/sha256.h>
|
||||||
#include <scrypt/crypto_scrypt.h>
|
|
||||||
#include <bcrypt/ow-crypt.h>
|
#include <bcrypt/ow-crypt.h>
|
||||||
#include "types.h"
|
|
||||||
|
#include "mpw-types.h"
|
||||||
|
#include "mpw-algorithm.h"
|
||||||
|
|
||||||
#define MP_N 32768
|
#define MP_N 32768
|
||||||
#define MP_r 8
|
#define MP_r 8
|
||||||
@ -22,166 +24,82 @@
|
|||||||
#define MP_dkLen 64
|
#define MP_dkLen 64
|
||||||
#define MP_hash PearlHashSHA256
|
#define MP_hash PearlHashSHA256
|
||||||
|
|
||||||
|
static void mpw_getTime(struct timeval *time) {
|
||||||
|
|
||||||
|
if (gettimeofday( time, NULL ) != 0)
|
||||||
|
ftl( "Could not get time: %d\n", errno );
|
||||||
|
}
|
||||||
|
|
||||||
|
static const double mpw_showSpeed(struct timeval startTime, const unsigned int iterations, const char *operation) {
|
||||||
|
|
||||||
|
struct timeval endTime;
|
||||||
|
mpw_getTime( &endTime );
|
||||||
|
|
||||||
|
const time_t dsec = (endTime.tv_sec - startTime.tv_sec);
|
||||||
|
const suseconds_t dusec = (endTime.tv_usec - startTime.tv_usec);
|
||||||
|
const double elapsed = dsec + dusec / 1000000.;
|
||||||
|
const double speed = iterations / elapsed;
|
||||||
|
|
||||||
|
fprintf( stderr, " done. " );
|
||||||
|
fprintf( stdout, "%d %s iterations in %llds %lldµs -> %.2f/s\n", iterations, operation, (long long)dsec, (long long)dusec, speed );
|
||||||
|
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *const argv[]) {
|
int main(int argc, char *const argv[]) {
|
||||||
|
|
||||||
char *fullName = "Robert Lee Mitchel";
|
const char *fullName = "Robert Lee Mitchel";
|
||||||
char *masterPassword = "banana colored duckling";
|
const char *masterPassword = "banana colored duckling";
|
||||||
char *siteName = "masterpasswordapp.com";
|
const char *siteName = "masterpasswordapp.com";
|
||||||
uint32_t siteCounter = 1;
|
const uint32_t siteCounter = 1;
|
||||||
MPSiteType siteType = MPSiteTypeGeneratedLong;
|
const MPSiteType siteType = MPSiteTypeGeneratedLong;
|
||||||
|
const MPSiteVariant siteVariant = MPSiteVariantPassword;
|
||||||
// Start MP
|
const char *siteContext = NULL;
|
||||||
struct timeval startTime;
|
struct timeval startTime;
|
||||||
if (gettimeofday(&startTime, NULL) != 0) {
|
|
||||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int iterations = 100;
|
// Start MPW
|
||||||
|
unsigned int iterations = 100;
|
||||||
|
mpw_getTime( &startTime );
|
||||||
for (int i = 0; i < iterations; ++i) {
|
for (int i = 0; i < iterations; ++i) {
|
||||||
// Calculate the master key salt.
|
const uint8_t *masterKey = mpw_masterKeyForUser( fullName, masterPassword );
|
||||||
char *mpNameSpace = "com.lyndir.masterpassword";
|
if (!masterKey)
|
||||||
const uint32_t n_fullNameLength = htonl(strlen(fullName));
|
ftl( "Could not allocate master key: %d\n", errno );
|
||||||
const size_t masterKeySaltLength = strlen(mpNameSpace) + sizeof(n_fullNameLength) + strlen(fullName);
|
free( (void *)mpw_passwordForSite( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext ) );
|
||||||
char *masterKeySalt = malloc( masterKeySaltLength );
|
free( (void *)masterKey );
|
||||||
if (!masterKeySalt) {
|
|
||||||
fprintf(stderr, "Could not allocate master key salt: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *mKS = masterKeySalt;
|
|
||||||
memcpy(mKS, mpNameSpace, strlen(mpNameSpace)); mKS += strlen(mpNameSpace);
|
|
||||||
memcpy(mKS, &n_fullNameLength, sizeof(n_fullNameLength)); mKS += sizeof(n_fullNameLength);
|
|
||||||
memcpy(mKS, fullName, strlen(fullName)); mKS += strlen(fullName);
|
|
||||||
if (mKS - masterKeySalt != masterKeySaltLength)
|
|
||||||
abort();
|
|
||||||
trc("masterKeySalt ID: %s\n", IDForBuf(masterKeySalt, masterKeySaltLength));
|
|
||||||
|
|
||||||
// Calculate the master key.
|
|
||||||
uint8_t *masterKey = malloc( MP_dkLen );
|
|
||||||
if (!masterKey) {
|
|
||||||
fprintf(stderr, "Could not allocate master key: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (crypto_scrypt( (const uint8_t *)masterPassword, strlen(masterPassword), (const uint8_t *)masterKeySalt, masterKeySaltLength, MP_N, MP_r, MP_p, masterKey, MP_dkLen ) < 0) {
|
|
||||||
fprintf(stderr, "Could not generate master key: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
memset(masterKeySalt, 0, masterKeySaltLength);
|
|
||||||
free(masterKeySalt);
|
|
||||||
|
|
||||||
// Calculate the site seed.
|
|
||||||
const uint32_t n_siteNameLength = htonl(strlen(siteName));
|
|
||||||
const uint32_t n_siteCounter = htonl(siteCounter);
|
|
||||||
const size_t sitePasswordInfoLength = strlen(mpNameSpace) + sizeof(n_siteNameLength) + strlen(siteName) + sizeof(n_siteCounter);
|
|
||||||
char *sitePasswordInfo = malloc( sitePasswordInfoLength );
|
|
||||||
if (!sitePasswordInfo) {
|
|
||||||
fprintf(stderr, "Could not allocate site seed: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *sPI = sitePasswordInfo;
|
|
||||||
memcpy(sPI, mpNameSpace, strlen(mpNameSpace)); sPI += strlen(mpNameSpace);
|
|
||||||
memcpy(sPI, &n_siteNameLength, sizeof(n_siteNameLength)); sPI += sizeof(n_siteNameLength);
|
|
||||||
memcpy(sPI, siteName, strlen(siteName)); sPI += strlen(siteName);
|
|
||||||
memcpy(sPI, &n_siteCounter, sizeof(n_siteCounter)); sPI += sizeof(n_siteCounter);
|
|
||||||
if (sPI - sitePasswordInfo != sitePasswordInfoLength)
|
|
||||||
abort();
|
|
||||||
|
|
||||||
uint8_t sitePasswordSeed[32];
|
|
||||||
HMAC_SHA256_Buf(masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoLength, sitePasswordSeed);
|
|
||||||
memset(masterKey, 0, MP_dkLen);
|
|
||||||
memset(sitePasswordInfo, 0, sitePasswordInfoLength);
|
|
||||||
free(masterKey);
|
|
||||||
free(sitePasswordInfo);
|
|
||||||
|
|
||||||
// Determine the template.
|
|
||||||
const char *template = TemplateForType(siteType, sitePasswordSeed[0]);
|
|
||||||
trc("type %d, template: %s\n", siteType, template);
|
|
||||||
if (strlen(template) > 32)
|
|
||||||
abort();
|
|
||||||
|
|
||||||
// Encode the password from the seed using the template.
|
|
||||||
char *sitePassword = calloc(strlen(template) + 1, sizeof(char));
|
|
||||||
for (int c = 0; c < strlen(template); ++c) {
|
|
||||||
sitePassword[c] = CharacterFromClass(template[c], sitePasswordSeed[c + 1]);
|
|
||||||
trc("class %c, character: %c\n", template[c], sitePassword[c]);
|
|
||||||
}
|
|
||||||
memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed));
|
|
||||||
|
|
||||||
if (i % 1 == 0)
|
if (i % 1 == 0)
|
||||||
fprintf( stderr, "\rmpw: iteration %d / %d..", i, iterations );
|
fprintf( stderr, "\rmpw: iteration %d / %d..", i, iterations );
|
||||||
}
|
}
|
||||||
|
const double mpwSpeed = mpw_showSpeed( startTime, iterations, "mpw" );
|
||||||
// Output timing results.
|
|
||||||
struct timeval endTime;
|
|
||||||
if (gettimeofday(&endTime, NULL) != 0) {
|
|
||||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
long long secs = (endTime.tv_sec - startTime.tv_sec);
|
|
||||||
long long usecs = (endTime.tv_usec - startTime.tv_usec);
|
|
||||||
double elapsed = secs + usecs / 1000000.0;
|
|
||||||
double mpwSpeed = iterations / elapsed;
|
|
||||||
fprintf( stdout, " done. %d iterations in %llds %lldµs -> %.2f/s\n", iterations, secs, usecs, mpwSpeed );
|
|
||||||
|
|
||||||
// Start SHA-256
|
// Start SHA-256
|
||||||
if (gettimeofday(&startTime, NULL) != 0) {
|
|
||||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterations = 50000000;
|
iterations = 50000000;
|
||||||
uint8_t hash[32];
|
uint8_t hash[32];
|
||||||
|
mpw_getTime( &startTime );
|
||||||
for (int i = 0; i < iterations; ++i) {
|
for (int i = 0; i < iterations; ++i) {
|
||||||
SHA256_Buf(masterPassword, strlen(masterPassword), hash);
|
SHA256_Buf( masterPassword, strlen( masterPassword ), hash );
|
||||||
|
|
||||||
if (i % 1000 == 0)
|
if (i % 1000 == 0)
|
||||||
fprintf( stderr, "\rsha256: iteration %d / %d..", i, iterations );
|
fprintf( stderr, "\rsha256: iteration %d / %d..", i, iterations );
|
||||||
}
|
}
|
||||||
|
const double sha256Speed = mpw_showSpeed( startTime, iterations, "sha256" );
|
||||||
// Output timing results.
|
|
||||||
if (gettimeofday(&endTime, NULL) != 0) {
|
|
||||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
secs = (endTime.tv_sec - startTime.tv_sec);
|
|
||||||
usecs = (endTime.tv_usec - startTime.tv_usec);
|
|
||||||
elapsed = secs + usecs / 1000000.0;
|
|
||||||
double sha256Speed = iterations / elapsed;
|
|
||||||
fprintf( stdout, " done. %d iterations in %llds %lldµs -> %.2f/s\n", iterations, secs, usecs, sha256Speed );
|
|
||||||
|
|
||||||
// Start BCrypt
|
// Start BCrypt
|
||||||
if (gettimeofday(&startTime, NULL) != 0) {
|
|
||||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int bcrypt_cost = 9;
|
int bcrypt_cost = 9;
|
||||||
iterations = 600;
|
iterations = 600;
|
||||||
|
mpw_getTime( &startTime );
|
||||||
for (int i = 0; i < iterations; ++i) {
|
for (int i = 0; i < iterations; ++i) {
|
||||||
crypt(masterPassword, crypt_gensalt("$2b$", bcrypt_cost, fullName, strlen(fullName)));
|
crypt( masterPassword, crypt_gensalt( "$2b$", bcrypt_cost, fullName, strlen( fullName ) ) );
|
||||||
|
|
||||||
if (i % 10 == 0)
|
if (i % 10 == 0)
|
||||||
fprintf( stderr, "\rbcrypt (cost %d): iteration %d / %d..", bcrypt_cost, i, iterations );
|
fprintf( stderr, "\rbcrypt (cost %d): iteration %d / %d..", bcrypt_cost, i, iterations );
|
||||||
}
|
}
|
||||||
|
const double bcrypt9Speed = mpw_showSpeed( startTime, iterations, "bcrypt9" );
|
||||||
// Output timing results.
|
|
||||||
if (gettimeofday(&endTime, NULL) != 0) {
|
|
||||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
secs = (endTime.tv_sec - startTime.tv_sec);
|
|
||||||
usecs = (endTime.tv_usec - startTime.tv_usec);
|
|
||||||
elapsed = secs + usecs / 1000000.0;
|
|
||||||
double bcrypt9Speed = iterations / elapsed;
|
|
||||||
fprintf( stdout, " done. %d iterations in %llds %lldµs -> %.2f/s\n", iterations, secs, usecs, bcrypt9Speed );
|
|
||||||
|
|
||||||
// Summarize.
|
// Summarize.
|
||||||
fprintf( stdout, "\n== SUMMARY ==\nOn this machine,\n" );
|
fprintf( stdout, "\n== SUMMARY ==\nOn this machine,\n" );
|
||||||
fprintf( stdout, "mpw is %f times slower than sha256\n", sha256Speed / mpwSpeed );
|
fprintf( stdout, " - mpw is %f times slower than sha256.\n", sha256Speed / mpwSpeed );
|
||||||
fprintf( stdout, "mpw is %f times slower than bcrypt (cost 9)\n", bcrypt9Speed / mpwSpeed );
|
fprintf( stdout, " - mpw is %f times slower than bcrypt (cost 9).\n", bcrypt9Speed / mpwSpeed );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
#include "mpw.h"
|
|
||||||
|
|
||||||
#if defined(READLINE)
|
#if defined(READLINE)
|
||||||
#include <readline/readline.h>
|
#include <readline/readline.h>
|
||||||
#elif defined(EDITLINE)
|
#elif defined(EDITLINE)
|
||||||
#include <histedit.h>
|
#include <histedit.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#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_fullname "MP_FULLNAME"
|
||||||
#define MP_env_sitetype "MP_SITETYPE"
|
#define MP_env_sitetype "MP_SITETYPE"
|
||||||
#define MP_env_sitecounter "MP_SITECOUNTER"
|
#define MP_env_sitecounter "MP_SITECOUNTER"
|
||||||
@ -125,18 +127,17 @@ int main(int argc, char *const argv[]) {
|
|||||||
case '?':
|
case '?':
|
||||||
switch (optopt) {
|
switch (optopt) {
|
||||||
case 'u':
|
case 'u':
|
||||||
fprintf( stderr, "Missing full name to option: -%c\n", optopt );
|
ftl( "Missing full name to option: -%c\n", optopt );
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
fprintf( stderr, "Missing type name to option: -%c\n", optopt );
|
ftl( "Missing type name to option: -%c\n", optopt );
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
fprintf( stderr, "Missing counter value to option: -%c\n", optopt );
|
ftl( "Missing counter value to option: -%c\n", optopt );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf( stderr, "Unknown option: -%c\n", optopt );
|
ftl( "Unknown option: -%c\n", optopt );
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
default:
|
default:
|
||||||
ftl("Unexpected option: %c", opt);
|
ftl("Unexpected option: %c", opt);
|
||||||
}
|
}
|
||||||
@ -144,39 +145,27 @@ int main(int argc, char *const argv[]) {
|
|||||||
siteName = argv[optind];
|
siteName = argv[optind];
|
||||||
|
|
||||||
// Convert and validate input.
|
// Convert and validate input.
|
||||||
if (!fullName) {
|
if (!fullName && !(fullName = getlinep( "Your full name:" )))
|
||||||
if (!(fullName = getlinep( "Your full name:" ))) {
|
ftl( "Missing full name.\n" );
|
||||||
fprintf( stderr, "Missing full name.\n" );
|
if (!siteName && !(siteName = getlinep( "Site name:" )))
|
||||||
return 1;
|
ftl( "Missing site name.\n" );
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!siteName) {
|
|
||||||
if (!(siteName = getlinep( "Site name:" ))) {
|
|
||||||
fprintf( stderr, "Missing site name.\n" );
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (siteCounterString)
|
if (siteCounterString)
|
||||||
siteCounter = atoi( siteCounterString );
|
siteCounter = atoi( siteCounterString );
|
||||||
if (siteCounter < 1) {
|
if (siteCounter < 1)
|
||||||
fprintf( stderr, "Invalid site counter: %d\n", siteCounter );
|
ftl( "Invalid site counter: %d\n", siteCounter );
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (siteVariantString)
|
if (siteVariantString)
|
||||||
siteVariant = VariantWithName( siteVariantString );
|
siteVariant = mpw_variantWithName( siteVariantString );
|
||||||
if (siteVariant == MPSiteVariantLogin)
|
if (siteVariant == MPSiteVariantLogin)
|
||||||
siteType = MPSiteTypeGeneratedName;
|
siteType = MPSiteTypeGeneratedName;
|
||||||
if (siteVariant == MPSiteVariantAnswer)
|
if (siteVariant == MPSiteVariantAnswer)
|
||||||
siteType = MPSiteTypeGeneratedPhrase;
|
siteType = MPSiteTypeGeneratedPhrase;
|
||||||
if (siteTypeString)
|
if (siteTypeString)
|
||||||
siteType = TypeWithName( siteTypeString );
|
siteType = mpw_typeWithName( siteTypeString );
|
||||||
|
|
||||||
// Read the master password.
|
// Read the master password.
|
||||||
char *mpwConfigPath = homedir( ".mpw" );
|
char *mpwConfigPath = homedir( ".mpw" );
|
||||||
if (!mpwConfigPath) {
|
if (!mpwConfigPath)
|
||||||
fprintf( stderr, "Couldn't resolve path for configuration file: %d\n", errno );
|
ftl( "Couldn't resolve path for configuration file: %d\n", errno );
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
trc( "mpwConfigPath: %s\n", mpwConfigPath );
|
trc( "mpwConfigPath: %s\n", mpwConfigPath );
|
||||||
FILE *mpwConfig = fopen( mpwConfigPath, "r" );
|
FILE *mpwConfig = fopen( mpwConfigPath, "r" );
|
||||||
free( mpwConfigPath );
|
free( mpwConfigPath );
|
||||||
@ -190,16 +179,18 @@ int main(int argc, char *const argv[]) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free( line );
|
mpw_free( line, linecap );
|
||||||
}
|
}
|
||||||
while (!masterPassword)
|
while (!masterPassword || !strlen(masterPassword))
|
||||||
masterPassword = getpass( "Your master password: " );
|
masterPassword = getpass( "Your master password: " );
|
||||||
|
|
||||||
// Summarize operation.
|
// Summarize operation.
|
||||||
fprintf( stderr, "%s's password for %s:\n[ %s ]: ", fullName, siteName, Identicon( fullName, masterPassword ) );
|
fprintf( stderr, "%s's password for %s:\n[ %s ]: ", fullName, siteName, mpw_identicon( fullName, masterPassword ) );
|
||||||
|
|
||||||
// Output the password.
|
// Output the password.
|
||||||
const uint8_t *masterKey = mpw_masterKeyForUser( fullName, masterPassword );
|
const uint8_t *masterKey = mpw_masterKeyForUser( fullName, masterPassword );
|
||||||
|
mpw_free( masterPassword, strlen( masterPassword ) );
|
||||||
|
|
||||||
const char *sitePassword = mpw_passwordForSite( masterKey, siteName, siteType, siteCounter, siteVariant, siteContextString );
|
const char *sitePassword = mpw_passwordForSite( masterKey, siteName, siteType, siteCounter, siteVariant, siteContextString );
|
||||||
fprintf( stdout, "%s\n", sitePassword );
|
fprintf( stdout, "%s\n", sitePassword );
|
||||||
|
|
||||||
|
@ -1,29 +1,24 @@
|
|||||||
//
|
//
|
||||||
// MPTypes.h
|
// mpw-types.c
|
||||||
// MasterPassword
|
// MasterPassword
|
||||||
//
|
//
|
||||||
// Created by Maarten Billemont on 02/01/12.
|
// Created by Maarten Billemont on 2012-02-01.
|
||||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <scrypt/sha256.h>
|
|
||||||
|
|
||||||
#ifdef COLOR
|
#ifdef COLOR
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
#include <term.h>
|
#include <term.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "types.h"
|
#include "mpw-types.h"
|
||||||
|
|
||||||
const MPSiteType TypeWithName(const char *typeName) {
|
const MPSiteType mpw_typeWithName(const char *typeName) {
|
||||||
char lowerTypeName[strlen(typeName)];
|
char lowerTypeName[strlen(typeName)];
|
||||||
strcpy(lowerTypeName, typeName);
|
strcpy(lowerTypeName, typeName);
|
||||||
for (char *tN = lowerTypeName; *tN; ++tN)
|
for (char *tN = lowerTypeName; *tN; ++tN)
|
||||||
@ -50,7 +45,7 @@ const MPSiteType TypeWithName(const char *typeName) {
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *TemplateForType(MPSiteType type, uint8_t seedByte) {
|
const char *mpw_templateForType(MPSiteType type, uint8_t seedByte) {
|
||||||
if (!(type & MPSiteTypeClassGenerated)) {
|
if (!(type & MPSiteTypeClassGenerated)) {
|
||||||
fprintf(stderr, "Not a generated type: %d", type);
|
fprintf(stderr, "Not a generated type: %d", type);
|
||||||
abort();
|
abort();
|
||||||
@ -93,7 +88,7 @@ const char *TemplateForType(MPSiteType type, uint8_t seedByte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MPSiteVariant VariantWithName(const char *variantName) {
|
const MPSiteVariant mpw_variantWithName(const char *variantName) {
|
||||||
char lowerVariantName[strlen(variantName)];
|
char lowerVariantName[strlen(variantName)];
|
||||||
strcpy(lowerVariantName, variantName);
|
strcpy(lowerVariantName, variantName);
|
||||||
for (char *vN = lowerVariantName; *vN; ++vN)
|
for (char *vN = lowerVariantName; *vN; ++vN)
|
||||||
@ -110,7 +105,7 @@ const MPSiteVariant VariantWithName(const char *variantName) {
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *ScopeForVariant(MPSiteVariant variant) {
|
const char *mpw_scopeForVariant(MPSiteVariant variant) {
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
case MPSiteVariantPassword: {
|
case MPSiteVariantPassword: {
|
||||||
return "com.lyndir.masterpassword";
|
return "com.lyndir.masterpassword";
|
||||||
@ -128,7 +123,7 @@ const char *ScopeForVariant(MPSiteVariant variant) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char CharacterFromClass(char characterClass, uint8_t seedByte) {
|
const char mpw_characterFromClass(char characterClass, uint8_t seedByte) {
|
||||||
const char *classCharacters;
|
const char *classCharacters;
|
||||||
switch (characterClass) {
|
switch (characterClass) {
|
||||||
case 'V': {
|
case 'V': {
|
||||||
@ -179,82 +174,3 @@ const char CharacterFromClass(char characterClass, uint8_t seedByte) {
|
|||||||
|
|
||||||
return classCharacters[seedByte % strlen(classCharacters)];
|
return classCharacters[seedByte % strlen(classCharacters)];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *IDForBuf(const void *buf, size_t length) {
|
|
||||||
uint8_t hash[32];
|
|
||||||
SHA256_Buf(buf, length, hash);
|
|
||||||
|
|
||||||
char *id = (char *)calloc(65, sizeof(char));
|
|
||||||
for (int kH = 0; kH < 32; kH++)
|
|
||||||
sprintf(&(id[kH * 2]), "%02X", hash[kH]);
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *Hex(const void *buf, size_t length) {
|
|
||||||
char *id = (char *)calloc(length*2+1, sizeof(char));
|
|
||||||
for (int kH = 0; kH < length; kH++)
|
|
||||||
sprintf(&(id[kH * 2]), "%02X", ((const uint8_t*)buf)[kH]);
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef COLOR
|
|
||||||
int putvari;
|
|
||||||
char *putvarc = NULL;
|
|
||||||
bool istermsetup = false;
|
|
||||||
static void initputvar() {
|
|
||||||
if (putvarc)
|
|
||||||
free(putvarc);
|
|
||||||
putvarc=(char *)calloc(256, sizeof(char));
|
|
||||||
putvari=0;
|
|
||||||
|
|
||||||
if (!istermsetup)
|
|
||||||
istermsetup = (OK == setupterm(NULL, STDERR_FILENO, NULL));
|
|
||||||
}
|
|
||||||
static int putvar(int c) {
|
|
||||||
putvarc[putvari++]=c;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *Identicon(const char *fullName, const char *masterPassword) {
|
|
||||||
const char *leftArm[] = { "╔", "╚", "╰", "═" };
|
|
||||||
const char *rightArm[] = { "╗", "╝", "╯", "═" };
|
|
||||||
const char *body[] = { "█", "░", "▒", "▓", "☺", "☻" };
|
|
||||||
const char *accessory[] = { "◈", "◎", "◐", "◑", "◒", "◓", "☀", "☁", "☂", "☃", "☄", "★", "☆", "☎", "☏", "⎈", "⌂", "☘", "☢", "☣", "☕", "⌚", "⌛", "⏰", "⚡", "⛄", "⛅", "☔", "♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛", "♜", "♝", "♞", "♟", "♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌" };
|
|
||||||
|
|
||||||
uint8_t identiconSeed[32];
|
|
||||||
HMAC_SHA256_Buf(masterPassword, strlen(masterPassword), fullName, strlen(fullName), identiconSeed);
|
|
||||||
|
|
||||||
char *colorString, *resetString;
|
|
||||||
#ifdef COLOR
|
|
||||||
if (isatty( STDERR_FILENO )) {
|
|
||||||
uint8_t colorIdentifier = (uint8_t)(identiconSeed[4] % 7 + 1);
|
|
||||||
initputvar();
|
|
||||||
tputs(tparm(tgetstr("AF", NULL), colorIdentifier), 1, putvar);
|
|
||||||
colorString = calloc(strlen(putvarc) + 1, sizeof(char));
|
|
||||||
strcpy(colorString, putvarc);
|
|
||||||
tputs(tgetstr("me", NULL), 1, putvar);
|
|
||||||
resetString = calloc(strlen(putvarc) + 1, sizeof(char));
|
|
||||||
strcpy(resetString, putvarc);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
colorString = calloc(1, sizeof(char));
|
|
||||||
resetString = calloc(1, sizeof(char));
|
|
||||||
}
|
|
||||||
|
|
||||||
char *identicon = (char *)calloc(256, sizeof(char));
|
|
||||||
snprintf(identicon, 256, "%s%s%s%s%s%s",
|
|
||||||
colorString,
|
|
||||||
leftArm[identiconSeed[0] % (sizeof(leftArm) / sizeof(leftArm[0]))],
|
|
||||||
body[identiconSeed[1] % (sizeof(body) / sizeof(body[0]))],
|
|
||||||
rightArm[identiconSeed[2] % (sizeof(rightArm) / sizeof(rightArm[0]))],
|
|
||||||
accessory[identiconSeed[3] % (sizeof(accessory) / sizeof(accessory[0]))],
|
|
||||||
resetString);
|
|
||||||
|
|
||||||
free(colorString);
|
|
||||||
free(resetString);
|
|
||||||
return identicon;
|
|
||||||
}
|
|
@ -1,11 +1,24 @@
|
|||||||
//
|
//
|
||||||
// MPTypes.h
|
// mpw-types.h
|
||||||
// MasterPassword
|
// MasterPassword
|
||||||
//
|
//
|
||||||
// Created by Maarten Billemont on 02/01/12.
|
// Created by Maarten Billemont on 2012-02-01.
|
||||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
//// Logging.
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define trc(...) fprintf( stderr, __VA_ARGS__ )
|
||||||
|
#else
|
||||||
|
#define trc(...) do {} while (0)
|
||||||
|
#endif
|
||||||
|
#ifndef ftl
|
||||||
|
#define ftl(...) do { fprintf( stderr, __VA_ARGS__ ); abort(); } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//// Types.
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/** Generate the password to log in with. */
|
/** Generate the password to log in with. */
|
||||||
MPSiteVariantPassword,
|
MPSiteVariantPassword,
|
||||||
@ -43,19 +56,11 @@ typedef enum {
|
|||||||
MPSiteTypeStoredDevicePrivate = 0x1 | MPSiteTypeClassStored | MPSiteFeatureDevicePrivate,
|
MPSiteTypeStoredDevicePrivate = 0x1 | MPSiteTypeClassStored | MPSiteFeatureDevicePrivate,
|
||||||
} MPSiteType;
|
} MPSiteType;
|
||||||
|
|
||||||
#ifdef DEBUG
|
//// Type utilities.
|
||||||
#define trc(...) fprintf(stderr, __VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define trc(...) do {} while (0)
|
|
||||||
#endif
|
|
||||||
#define ftl(...) do { fprintf( stderr, "Could not allocate master key salt: %d\n", errno ); abort(); } while (0)
|
|
||||||
|
|
||||||
const MPSiteVariant VariantWithName(const char *variantName);
|
const MPSiteVariant mpw_variantWithName(const char *variantName);
|
||||||
const char *ScopeForVariant(MPSiteVariant variant);
|
const char *mpw_scopeForVariant(MPSiteVariant variant);
|
||||||
const MPSiteType TypeWithName(const char *typeName);
|
const MPSiteType mpw_typeWithName(const char *typeName);
|
||||||
const char *TemplateForType(MPSiteType type, uint8_t seedByte);
|
const char *mpw_templateForType(MPSiteType type, uint8_t seedByte);
|
||||||
const char CharacterFromClass(char characterClass, uint8_t seedByte);
|
const char mpw_characterFromClass(char characterClass, uint8_t seedByte);
|
||||||
const char *IDForBuf(const void *buf, size_t length);
|
|
||||||
const char *Hex(const void *buf, size_t length);
|
|
||||||
const char *Identicon(const char *fullName, const char *masterPassword);
|
|
||||||
|
|
155
MasterPassword/C/mpw-util.c
Normal file
155
MasterPassword/C/mpw-util.c
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
//
|
||||||
|
// mpw-util.c
|
||||||
|
// MasterPassword
|
||||||
|
//
|
||||||
|
// Created by Maarten Billemont on 2014-12-20.
|
||||||
|
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <scrypt/sha256.h>
|
||||||
|
#include <scrypt/crypto_scrypt.h>
|
||||||
|
|
||||||
|
#include "mpw-util.h"
|
||||||
|
|
||||||
|
void mpw_pushBuf(uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize) {
|
||||||
|
|
||||||
|
if (*bufferSize == (size_t)-1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*bufferSize += pushSize;
|
||||||
|
*buffer = realloc( *buffer, *bufferSize );
|
||||||
|
if (!*buffer) {
|
||||||
|
*bufferSize = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *pushDst = *buffer + *bufferSize - pushSize;
|
||||||
|
memcpy( pushDst, pushBuffer, pushSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpw_pushString(uint8_t **buffer, size_t *const bufferSize, const char *pushString) {
|
||||||
|
|
||||||
|
mpw_pushBuf( buffer, bufferSize, pushString, strlen( pushString ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpw_pushInt(uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt) {
|
||||||
|
|
||||||
|
mpw_pushBuf( buffer, bufferSize, &pushInt, sizeof( pushInt ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpw_free(const void *buffer, const size_t bufferSize) {
|
||||||
|
|
||||||
|
memset( (void *)buffer, 0, bufferSize );
|
||||||
|
free( (void *)buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
|
||||||
|
uint64_t N, uint32_t r, uint32_t p) {
|
||||||
|
|
||||||
|
uint8_t *key = malloc( keySize );
|
||||||
|
if (!key)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (crypto_scrypt( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize ) < 0) {
|
||||||
|
mpw_free( key, keySize );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize) {
|
||||||
|
|
||||||
|
uint8_t *const buffer = malloc(32);
|
||||||
|
if (!buffer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
HMAC_SHA256_Buf( key, keySize, salt, saltSize, buffer );
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *mpw_idForBuf(const void *buf, size_t length) {
|
||||||
|
|
||||||
|
uint8_t hash[32];
|
||||||
|
SHA256_Buf( buf, length, hash );
|
||||||
|
|
||||||
|
return mpw_hex( hash, 32 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *mpw_hex_buf = NULL;
|
||||||
|
const char *mpw_hex(const void *buf, size_t length) {
|
||||||
|
|
||||||
|
mpw_hex_buf = realloc( mpw_hex_buf, length * 2 + 1 );
|
||||||
|
for (int kH = 0; kH < length; kH++)
|
||||||
|
sprintf( &(mpw_hex_buf[kH * 2]), "%02X", ((const uint8_t *)buf)[kH] );
|
||||||
|
|
||||||
|
return mpw_hex_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef COLOR
|
||||||
|
static int putvari;
|
||||||
|
static char *putvarc = NULL;
|
||||||
|
static bool istermsetup = false;
|
||||||
|
static void initputvar() {
|
||||||
|
if (putvarc)
|
||||||
|
free(putvarc);
|
||||||
|
putvarc=(char *)calloc(256, sizeof(char));
|
||||||
|
putvari=0;
|
||||||
|
|
||||||
|
if (!istermsetup)
|
||||||
|
istermsetup = (OK == setupterm(NULL, STDERR_FILENO, NULL));
|
||||||
|
}
|
||||||
|
static int putvar(int c) {
|
||||||
|
putvarc[putvari++]=c;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *mpw_identicon(const char *fullName, const char *masterPassword) {
|
||||||
|
|
||||||
|
const char *leftArm[] = { "╔", "╚", "╰", "═" };
|
||||||
|
const char *rightArm[] = { "╗", "╝", "╯", "═" };
|
||||||
|
const char *body[] = { "█", "░", "▒", "▓", "☺", "☻" };
|
||||||
|
const char *accessory[] = {
|
||||||
|
"◈", "◎", "◐", "◑", "◒", "◓", "☀", "☁", "☂", "☃", "☄", "★", "☆", "☎", "☏", "⎈", "⌂", "☘", "☢", "☣",
|
||||||
|
"☕", "⌚", "⌛", "⏰", "⚡", "⛄", "⛅", "☔", "♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛", "♜", "♝", "♞", "♟",
|
||||||
|
"♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌" };
|
||||||
|
|
||||||
|
uint8_t identiconSeed[32];
|
||||||
|
HMAC_SHA256_Buf( masterPassword, strlen( masterPassword ), fullName, strlen( fullName ), identiconSeed );
|
||||||
|
|
||||||
|
char *colorString, *resetString;
|
||||||
|
#ifdef COLOR
|
||||||
|
if (isatty( STDERR_FILENO )) {
|
||||||
|
uint8_t colorIdentifier = (uint8_t)(identiconSeed[4] % 7 + 1);
|
||||||
|
initputvar();
|
||||||
|
tputs(tparm(tgetstr("AF", NULL), colorIdentifier), 1, putvar);
|
||||||
|
colorString = calloc(strlen(putvarc) + 1, sizeof(char));
|
||||||
|
strcpy(colorString, putvarc);
|
||||||
|
tputs(tgetstr("me", NULL), 1, putvar);
|
||||||
|
resetString = calloc(strlen(putvarc) + 1, sizeof(char));
|
||||||
|
strcpy(resetString, putvarc);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
colorString = calloc( 1, sizeof( char ) );
|
||||||
|
resetString = calloc( 1, sizeof( char ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
char *identicon = (char *)calloc( 256, sizeof( char ) );
|
||||||
|
snprintf( identicon, 256, "%s%s%s%s%s%s",
|
||||||
|
colorString,
|
||||||
|
leftArm[identiconSeed[0] % (sizeof( leftArm ) / sizeof( leftArm[0] ))],
|
||||||
|
body[identiconSeed[1] % (sizeof( body ) / sizeof( body[0] ))],
|
||||||
|
rightArm[identiconSeed[2] % (sizeof( rightArm ) / sizeof( rightArm[0] ))],
|
||||||
|
accessory[identiconSeed[3] % (sizeof( accessory ) / sizeof( accessory[0] ))],
|
||||||
|
resetString );
|
||||||
|
|
||||||
|
free( colorString );
|
||||||
|
free( resetString );
|
||||||
|
return identicon;
|
||||||
|
}
|
46
MasterPassword/C/mpw-util.h
Normal file
46
MasterPassword/C/mpw-util.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// mpw-util.h
|
||||||
|
// MasterPassword
|
||||||
|
//
|
||||||
|
// Created by Maarten Billemont on 2014-12-20.
|
||||||
|
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
//// Buffers and memory.
|
||||||
|
|
||||||
|
/** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */
|
||||||
|
void mpw_pushBuf(
|
||||||
|
uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize);
|
||||||
|
/** Push a string onto a buffer. reallocs the given buffer and appends the given string. */
|
||||||
|
void mpw_pushString(
|
||||||
|
uint8_t **buffer, size_t *const bufferSize, const char *pushString);
|
||||||
|
/** Push an integer onto a buffer. reallocs the given buffer and appends the given integer. */
|
||||||
|
void mpw_pushInt(
|
||||||
|
uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt);
|
||||||
|
/** Free a buffer after zero'ing its contents. */
|
||||||
|
void mpw_free(
|
||||||
|
const void *buffer, const size_t bufferSize);
|
||||||
|
|
||||||
|
//// Cryptographic functions.
|
||||||
|
|
||||||
|
/** Perform a scrypt-based key derivation on the given key using the given salt and scrypt parameters.
|
||||||
|
* @return A new keySize-size allocated buffer. */
|
||||||
|
uint8_t const *mpw_scrypt(
|
||||||
|
const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
|
||||||
|
uint64_t N, uint32_t r, uint32_t p);
|
||||||
|
/** Calculate a SHA256-based HMAC by encrypting the given salt with the given key.
|
||||||
|
* @return A new 32-byte allocated buffer. */
|
||||||
|
uint8_t const *mpw_hmac_sha256(
|
||||||
|
const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize);
|
||||||
|
|
||||||
|
//// Visualizers.
|
||||||
|
|
||||||
|
/** Encode a buffer as a string of hexadecimal characters.
|
||||||
|
* @return 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. */
|
||||||
|
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);
|
@ -1,6 +0,0 @@
|
|||||||
const uint8_t *mpw_masterKeyForUser(
|
|
||||||
const char *fullName, const char *masterPassword);
|
|
||||||
|
|
||||||
const char *mpw_passwordForSite(
|
|
||||||
const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
|
||||||
const MPSiteVariant siteVariant, const char *siteContext);
|
|
@ -27,7 +27,7 @@
|
|||||||
93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */; };
|
93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */; };
|
||||||
93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B381350802A194BF332 /* MPAvatarCell.m */; };
|
93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B381350802A194BF332 /* MPAvatarCell.m */; };
|
||||||
93D3958C13B557F60F63C72B /* distribute in Resources */ = {isa = PBXBuildFile; fileRef = 93D3979016BF0C5B29D1340D /* distribute */; };
|
93D3958C13B557F60F63C72B /* distribute in Resources */ = {isa = PBXBuildFile; fileRef = 93D3979016BF0C5B29D1340D /* distribute */; };
|
||||||
93D395B715D15F2B56F2A2EE /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D392C5A6572DB0EB5B82C8 /* types.c */; };
|
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 */; };
|
93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; };
|
||||||
93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */; };
|
93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */; };
|
||||||
93D396AA30690B256F30378A /* PearlNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3956915634581E737B38C /* PearlNavigationController.m */; };
|
93D396AA30690B256F30378A /* PearlNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3956915634581E737B38C /* PearlNavigationController.m */; };
|
||||||
@ -40,6 +40,7 @@
|
|||||||
93D399246DC90F50913A1287 /* UIResponder+PearlFirstResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A1DDFA09AE2E14D26DC /* UIResponder+PearlFirstResponder.m */; };
|
93D399246DC90F50913A1287 /* UIResponder+PearlFirstResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A1DDFA09AE2E14D26DC /* UIResponder+PearlFirstResponder.m */; };
|
||||||
93D3992FA1546E01F498F665 /* PearlNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */; };
|
93D3992FA1546E01F498F665 /* PearlNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */; };
|
||||||
93D399433EA75E50656040CB /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D394077F8FAB8167647187 /* Twitter.framework */; };
|
93D399433EA75E50656040CB /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D394077F8FAB8167647187 /* Twitter.framework */; };
|
||||||
|
93D39943D01E70DAC3B0DF76 /* mpw-util.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D396C311C3725870343EE0 /* mpw-util.c */; };
|
||||||
93D399D7E08A142776A74CB8 /* MPOverlayViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D395105935859D71679931 /* MPOverlayViewController.m */; };
|
93D399D7E08A142776A74CB8 /* MPOverlayViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D395105935859D71679931 /* MPOverlayViewController.m */; };
|
||||||
93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399A8E3181B442D347CD7 /* MPAlgorithmV2.m */; };
|
93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399A8E3181B442D347CD7 /* MPAlgorithmV2.m */; };
|
||||||
93D39A53D76CA70786423458 /* UICollectionView+PearlReloadFromArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadFromArray.h */; };
|
93D39A53D76CA70786423458 /* UICollectionView+PearlReloadFromArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadFromArray.h */; };
|
||||||
@ -477,7 +478,7 @@
|
|||||||
93D3924D6F77E6BF41AC32D3 /* MPRootSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRootSegue.h; sourceTree = "<group>"; };
|
93D3924D6F77E6BF41AC32D3 /* MPRootSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRootSegue.h; sourceTree = "<group>"; };
|
||||||
93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsViewController.m; sourceTree = "<group>"; };
|
93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsViewController.m; sourceTree = "<group>"; };
|
||||||
93D392876BE5C011DE73B43F /* MPPopdownSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPopdownSegue.h; sourceTree = "<group>"; };
|
93D392876BE5C011DE73B43F /* MPPopdownSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPopdownSegue.h; sourceTree = "<group>"; };
|
||||||
93D392C5A6572DB0EB5B82C8 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = types.c; sourceTree = "<group>"; };
|
93D392C5A6572DB0EB5B82C8 /* mpw-types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-types.c"; sourceTree = "<group>"; };
|
||||||
93D393310223DDB35218467A /* MPCombinedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCombinedViewController.m; sourceTree = "<group>"; };
|
93D393310223DDB35218467A /* MPCombinedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCombinedViewController.m; sourceTree = "<group>"; };
|
||||||
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
|
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
|
||||||
93D393BB973253D4BAAC84AA /* PearlEMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlEMail.m; sourceTree = "<group>"; };
|
93D393BB973253D4BAAC84AA /* PearlEMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlEMail.m; sourceTree = "<group>"; };
|
||||||
@ -490,7 +491,8 @@
|
|||||||
93D395105935859D71679931 /* MPOverlayViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOverlayViewController.m; 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>"; };
|
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>"; };
|
93D3957D76F71A652716EECC /* MPStoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStoreViewController.m; sourceTree = "<group>"; };
|
||||||
93D3969393A3A46BD27D7078 /* mpw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpw.c; 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>"; };
|
93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = "<group>"; };
|
||||||
93D3970502644794E8A027BE /* MPNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNavigationController.h; 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>"; };
|
93D3971FE104BB4052484151 /* MPUsersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUsersViewController.h; sourceTree = "<group>"; };
|
||||||
@ -502,7 +504,7 @@
|
|||||||
93D398121C8F063A3637144E /* mpw-cli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-cli.c"; sourceTree = "<group>"; };
|
93D398121C8F063A3637144E /* mpw-cli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-cli.c"; sourceTree = "<group>"; };
|
||||||
93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlNavigationController.h; sourceTree = "<group>"; };
|
93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlNavigationController.h; sourceTree = "<group>"; };
|
||||||
93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = "<group>"; };
|
93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = "<group>"; };
|
||||||
93D3990D850D76A94C6B7A4D /* mpw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mpw.h; sourceTree = "<group>"; };
|
93D3990D850D76A94C6B7A4D /* mpw-algorithm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-algorithm.h"; sourceTree = "<group>"; };
|
||||||
93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWebViewController.m; sourceTree = "<group>"; };
|
93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWebViewController.m; sourceTree = "<group>"; };
|
||||||
93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRootSegue.m; sourceTree = "<group>"; };
|
93D399493FEDDE74DD1A0C15 /* MPRootSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRootSegue.m; sourceTree = "<group>"; };
|
||||||
93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoachmarkViewController.m; sourceTree = "<group>"; };
|
93D3995B1D4DCE5A30D882BA /* MPCoachmarkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoachmarkViewController.m; sourceTree = "<group>"; };
|
||||||
@ -521,7 +523,7 @@
|
|||||||
93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Indexing.m"; sourceTree = "<group>"; };
|
93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Indexing.m"; sourceTree = "<group>"; };
|
||||||
93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPEmergencyViewController.m; sourceTree = "<group>"; };
|
93D39ACBA9F4878B6A1CC33B /* MPEmergencyViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPEmergencyViewController.m; sourceTree = "<group>"; };
|
||||||
93D39ACD33E79386E6F33601 /* install */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = install; sourceTree = "<group>"; };
|
93D39ACD33E79386E6F33601 /* install */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = install; sourceTree = "<group>"; };
|
||||||
93D39AFD17CBE324D745DAB0 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = "<group>"; };
|
93D39AFD17CBE324D745DAB0 /* mpw-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mpw-types.h"; sourceTree = "<group>"; };
|
||||||
93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPopdownSegue.m; sourceTree = "<group>"; };
|
93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPopdownSegue.m; sourceTree = "<group>"; };
|
||||||
93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUICollectionView.h; sourceTree = "<group>"; };
|
93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUICollectionView.h; sourceTree = "<group>"; };
|
||||||
93D39B381350802A194BF332 /* MPAvatarCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAvatarCell.m; sourceTree = "<group>"; };
|
93D39B381350802A194BF332 /* MPAvatarCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAvatarCell.m; sourceTree = "<group>"; };
|
||||||
@ -536,6 +538,7 @@
|
|||||||
93D39CC01630D0421205C4C4 /* MPNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNavigationController.m; sourceTree = "<group>"; };
|
93D39CC01630D0421205C4C4 /* MPNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNavigationController.m; sourceTree = "<group>"; };
|
||||||
93D39CDD434AFD6E1B0DA359 /* MPEmergencyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEmergencyViewController.h; sourceTree = "<group>"; };
|
93D39CDD434AFD6E1B0DA359 /* MPEmergencyViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEmergencyViewController.h; sourceTree = "<group>"; };
|
||||||
93D39CECA10BCCB0BA581BF1 /* MPAppDelegate_InApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_InApp.h; sourceTree = "<group>"; };
|
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>"; };
|
93D39CF8ADF4542CDC4CD385 /* MPCombinedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCombinedViewController.h; sourceTree = "<group>"; };
|
||||||
93D39D6604447D7708039155 /* MPAnswersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAnswersViewController.h; sourceTree = "<group>"; };
|
93D39D6604447D7708039155 /* MPAnswersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAnswersViewController.h; sourceTree = "<group>"; };
|
||||||
93D39D8A953779B35403AF6E /* PearlUICollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUICollectionView.m; sourceTree = "<group>"; };
|
93D39D8A953779B35403AF6E /* PearlUICollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlUICollectionView.m; sourceTree = "<group>"; };
|
||||||
@ -1606,17 +1609,19 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
93D39B573E4DE98BAE518215 /* build */,
|
93D39B573E4DE98BAE518215 /* build */,
|
||||||
93D3969393A3A46BD27D7078 /* mpw.c */,
|
93D3969393A3A46BD27D7078 /* mpw-algorithm.c */,
|
||||||
93D39E71D6BAECEC4CD886F4 /* bashlib */,
|
93D39E71D6BAECEC4CD886F4 /* bashlib */,
|
||||||
93D39ACD33E79386E6F33601 /* install */,
|
93D39ACD33E79386E6F33601 /* install */,
|
||||||
93D392C5A6572DB0EB5B82C8 /* types.c */,
|
93D392C5A6572DB0EB5B82C8 /* mpw-types.c */,
|
||||||
93D39AFD17CBE324D745DAB0 /* types.h */,
|
93D39AFD17CBE324D745DAB0 /* mpw-types.h */,
|
||||||
93D3944F4D55D2A37EF6021B /* VERSION */,
|
93D3944F4D55D2A37EF6021B /* VERSION */,
|
||||||
93D3979016BF0C5B29D1340D /* distribute */,
|
93D3979016BF0C5B29D1340D /* distribute */,
|
||||||
93D39245A478883C672818F3 /* mpw.bashrc */,
|
93D39245A478883C672818F3 /* mpw.bashrc */,
|
||||||
93D39B70138D0E28F7D5E86B /* mpw-bench.c */,
|
93D39B70138D0E28F7D5E86B /* mpw-bench.c */,
|
||||||
93D398121C8F063A3637144E /* mpw-cli.c */,
|
93D398121C8F063A3637144E /* mpw-cli.c */,
|
||||||
93D3990D850D76A94C6B7A4D /* mpw.h */,
|
93D3990D850D76A94C6B7A4D /* mpw-algorithm.h */,
|
||||||
|
93D39CF7DB942C69D1C5D6BE /* mpw-util.h */,
|
||||||
|
93D396C311C3725870343EE0 /* mpw-util.c */,
|
||||||
);
|
);
|
||||||
name = C;
|
name = C;
|
||||||
path = ../../C;
|
path = ../../C;
|
||||||
@ -3630,8 +3635,9 @@
|
|||||||
93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */,
|
93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */,
|
||||||
93D39B429C67A62E29DC02DA /* MPRootSegue.m in Sources */,
|
93D39B429C67A62E29DC02DA /* MPRootSegue.m in Sources */,
|
||||||
93D392FD5E2052F7D7DB3774 /* NSString+MPMarkDown.m in Sources */,
|
93D392FD5E2052F7D7DB3774 /* NSString+MPMarkDown.m in Sources */,
|
||||||
93D395B715D15F2B56F2A2EE /* types.c in Sources */,
|
93D395B715D15F2B56F2A2EE /* mpw-types.c in Sources */,
|
||||||
93D39B35D4B8E87ADEC05246 /* mpw-cli.c in Sources */,
|
93D39B35D4B8E87ADEC05246 /* mpw-cli.c in Sources */,
|
||||||
|
93D39943D01E70DAC3B0DF76 /* mpw-util.c in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user