diff --git a/MasterPassword/C/build b/MasterPassword/C/build index 2c06e2a2..948e779a 100755 --- a/MasterPassword/C/build +++ b/MasterPassword/C/build @@ -39,7 +39,7 @@ else fi # Optional features. -mpw_color=0 # Colorized Identicon, requires libncurses-dev +mpw_color=1 # Colorized Identicon, requires libncurses-dev ### DEPENDENCIES diff --git a/MasterPassword/C/mpw-algorithm_v0.c b/MasterPassword/C/mpw-algorithm_v0.c index 28eefb3e..fb9f46a1 100644 --- a/MasterPassword/C/mpw-algorithm_v0.c +++ b/MasterPassword/C/mpw-algorithm_v0.c @@ -38,7 +38,8 @@ static const char mpw_characterFromClass_v0(char characterClass, uint16_t seedBy static const uint8_t *mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) { const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword ); - trc( "fullName: %s\n", fullName ); + trc( "algorithm: v%d\n", 0 ); + trc( "fullName: %s (%zu)\n", fullName, mpw_charlen( fullName ) ); trc( "masterPassword: %s\n", masterPassword ); trc( "key scope: %s\n", mpKeyScope ); @@ -72,6 +73,7 @@ static const char *mpw_passwordForSite_v0(const uint8_t *masterKey, const char * const MPSiteVariant siteVariant, const char *siteContext) { const char *siteScope = mpw_scopeForVariant( siteVariant ); + trc( "algorithm: v%d\n", 0 ); trc( "siteName: %s\n", siteName ); trc( "siteCounter: %d\n", siteCounter ); trc( "siteVariant: %d\n", siteVariant ); diff --git a/MasterPassword/C/mpw-algorithm_v1.c b/MasterPassword/C/mpw-algorithm_v1.c index 925e02bb..55159e7e 100644 --- a/MasterPassword/C/mpw-algorithm_v1.c +++ b/MasterPassword/C/mpw-algorithm_v1.c @@ -22,7 +22,8 @@ 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( "algorithm: v%d\n", 1 ); + trc( "fullName: %s (%zu)\n", fullName, mpw_charlen( fullName ) ); trc( "masterPassword: %s\n", masterPassword ); trc( "key scope: %s\n", mpKeyScope ); @@ -56,6 +57,7 @@ static const char *mpw_passwordForSite_v1(const uint8_t *masterKey, const char * const MPSiteVariant siteVariant, const char *siteContext) { const char *siteScope = mpw_scopeForVariant( siteVariant ); + trc( "algorithm: v%d\n", 1 ); trc( "siteName: %s\n", siteName ); trc( "siteCounter: %d\n", siteCounter ); trc( "siteVariant: %d\n", siteVariant ); diff --git a/MasterPassword/C/mpw-algorithm_v2.c b/MasterPassword/C/mpw-algorithm_v2.c index 935b5016..2d019dbe 100644 --- a/MasterPassword/C/mpw-algorithm_v2.c +++ b/MasterPassword/C/mpw-algorithm_v2.c @@ -22,7 +22,8 @@ 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( "algorithm: v%d\n", 2 ); + trc( "fullName: %s (%zu)\n", fullName, mpw_charlen( fullName ) ); trc( "masterPassword: %s\n", masterPassword ); trc( "key scope: %s\n", mpKeyScope ); @@ -56,6 +57,7 @@ static const char *mpw_passwordForSite_v2(const uint8_t *masterKey, const char * const MPSiteVariant siteVariant, const char *siteContext) { const char *siteScope = mpw_scopeForVariant( siteVariant ); + trc( "algorithm: v%d\n", 2 ); trc( "siteName: %s\n", siteName ); trc( "siteCounter: %d\n", siteCounter ); trc( "siteVariant: %d\n", siteVariant ); diff --git a/MasterPassword/C/mpw-algorithm_v3.c b/MasterPassword/C/mpw-algorithm_v3.c index bd1feeb4..bfb22532 100644 --- a/MasterPassword/C/mpw-algorithm_v3.c +++ b/MasterPassword/C/mpw-algorithm_v3.c @@ -22,7 +22,8 @@ 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( "algorithm: v%d\n", 3 ); + trc( "fullName: %s (%zu)\n", fullName, strlen( fullName ) ); trc( "masterPassword: %s\n", masterPassword ); trc( "key scope: %s\n", mpKeyScope ); @@ -56,6 +57,7 @@ static const char *mpw_passwordForSite_v3(const uint8_t *masterKey, const char * const MPSiteVariant siteVariant, const char *siteContext) { const char *siteScope = mpw_scopeForVariant( siteVariant ); + trc( "algorithm: v%d\n", 3 ); trc( "siteName: %s\n", siteName ); trc( "siteCounter: %d\n", siteCounter ); trc( "siteVariant: %d\n", siteVariant ); diff --git a/MasterPassword/C/mpw-tests.c b/MasterPassword/C/mpw-tests.c index 8755bd59..7f4c8981 100644 --- a/MasterPassword/C/mpw-tests.c +++ b/MasterPassword/C/mpw-tests.c @@ -21,6 +21,7 @@ int main(int argc, char *const argv[]) { // Read in the test case. xmlChar *id = mpw_xmlTestCaseString( testCase, "id" ); + uint32_t algorithm = mpw_xmlTestCaseInteger( testCase, "algorithm" ); xmlChar *fullName = mpw_xmlTestCaseString( testCase, "fullName" ); xmlChar *masterPassword = mpw_xmlTestCaseString( testCase, "masterPassword" ); xmlChar *keyID = mpw_xmlTestCaseString( testCase, "keyID" ); @@ -36,16 +37,20 @@ int main(int argc, char *const argv[]) { // Run the test case. fprintf( stdout, "test case %s... ", id ); + if (!xmlStrlen( result )) { + fprintf( stdout, "abstract.\n" ); + continue; + } // 1. calculate the master key. const uint8_t *masterKey = mpw_masterKeyForUser( - (char *)fullName, (char *)masterPassword, MPAlgorithmVersionCurrent ); + (char *)fullName, (char *)masterPassword, algorithm ); 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, MPAlgorithmVersionCurrent ); + masterKey, (char *)siteName, siteType, siteCounter, siteVariant, (char *)siteContext, algorithm ); mpw_free( masterKey, MP_dkLen ); if (!sitePassword) ftl( "Couldn't derive site password." ); @@ -56,7 +61,7 @@ int main(int argc, char *const argv[]) { else { ++failedTests; - fprintf( stdout, "FAILED! (result %s != expected %s)\n", result, sitePassword ); + fprintf( stdout, "FAILED! (got %s != expected %s)\n", sitePassword, result ); } // Free test case. diff --git a/MasterPassword/C/mpw-util.c b/MasterPassword/C/mpw-util.c index c9042359..3bc072cb 100644 --- a/MasterPassword/C/mpw-util.c +++ b/MasterPassword/C/mpw-util.c @@ -8,9 +8,7 @@ #include #include -#include #include -#include #ifdef COLOR #include @@ -111,7 +109,7 @@ const char *mpw_hex(const void *buf, size_t length) { #ifdef COLOR static int putvari; static char *putvarc = NULL; -static bool istermsetup = false; +static int istermsetup = 0; static void initputvar() { if (putvarc) free(putvarc); @@ -172,8 +170,33 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) { return identicon; } -const size_t mpw_charlen(const char *string) { +/** +* @return the amount of bytes used by UTF-8 to encode a single character that starts with the given byte. +*/ +static int mpw_charByteSize(unsigned char utf8Byte) { - setlocale( LC_ALL, "en_US.UTF-8" ); - return mbstowcs( NULL, string, strlen( string ) ); + if (!utf8Byte) + return 0; + if ((utf8Byte & 0x80) == 0) + return 1; + if ((utf8Byte & 0xC0) != 0xC0) + return 0; + if ((utf8Byte & 0xE0) == 0xC0) + return 2; + if ((utf8Byte & 0xF0) == 0xE0) + return 3; + if ((utf8Byte & 0xF8) == 0xF0) + return 4; + + return 0; +} + +const size_t mpw_charlen(const char *utf8String) { + + size_t charlen = 0; + char *remainingString = (char *)utf8String; + for (int charByteSize; (charByteSize = mpw_charByteSize( *remainingString )); remainingString += charByteSize) + ++charlen; + + return charlen; } diff --git a/MasterPassword/C/mpw-util.h b/MasterPassword/C/mpw-util.h index 52ba5f99..8c5db151 100644 --- a/MasterPassword/C/mpw-util.h +++ b/MasterPassword/C/mpw-util.h @@ -75,4 +75,5 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword); //// String utilities. -const size_t mpw_charlen(const char *string); +/** @return The amount of display characters in the given UTF-8 string. */ +const size_t mpw_charlen(const char *utf8String);