//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
//
// Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Master Password is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see .
//==============================================================================
//
// mpw-bench.c
// MasterPassword
//
// Created by Maarten Billemont on 2014-12-20.
// Copyright (c) 2014 Lyndir. All rights reserved.
//
#include
#include
#include
#include
#include
#include
#include "bcrypt.c"
#include "mpw-algorithm.h"
#include "mpw-util.h"
#define MP_N 32768
#define MP_r 8
#define MP_p 2
static void mpw_time(struct timeval *time) {
if (gettimeofday( time, NULL ) != 0)
ftl( "Could not get time: %s", strerror( errno ) );
}
static const double mpw_show_speed(struct timeval startTime, const unsigned int iterations, const char *operation) {
struct timeval endTime;
mpw_time( &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 %lus %uµs -> %.2f/s\n", iterations, operation, dsec, dusec, speed );
return speed;
}
int main(int argc, char *const argv[]) {
const char *fullName = "Robert Lee Mitchel";
const char *masterPassword = "banana colored duckling";
const char *siteName = "masterpassword.app";
const MPCounterValue siteCounter = MPCounterValueDefault;
const MPResultType resultType = MPResultTypeDefault;
const MPKeyPurpose keyPurpose = MPKeyPurposeAuthentication;
const char *keyContext = NULL;
struct timeval startTime;
unsigned int iterations;
float percent;
MPMasterKey masterKey;
// Start HMAC-SHA-256
// Similar to phase-two of mpw
uint8_t *sitePasswordInfo = malloc( 128 );
iterations = 4200000; /* tuned to ~10s on dev machine */
masterKey = mpw_master_key( fullName, masterPassword, MPAlgorithmVersionCurrent );
if (!masterKey) {
ftl( "Could not allocate master key: %s", strerror( errno ) );
abort();
}
mpw_time( &startTime );
for (int i = 1; i <= iterations; ++i) {
free( (void *)mpw_hash_hmac_sha256( masterKey, MPMasterKeySize, sitePasswordInfo, 128 ) );
if (modff( 100.f * i / iterations, &percent ) == 0)
fprintf( stderr, "\rhmac-sha-256: iteration %d / %d (%.0f%%)..", i, iterations, percent );
}
const double hmacSha256Speed = mpw_show_speed( startTime, iterations, "hmac-sha-256" );
free( (void *)masterKey );
// Start BCrypt
// Similar to phase-one of mpw
uint8_t bcrypt_rounds = 9;
iterations = 170; /* tuned to ~10s on dev machine */
mpw_time( &startTime );
for (int i = 1; i <= iterations; ++i) {
bcrypt( masterPassword, bcrypt_gensalt( bcrypt_rounds ) );
if (modff( 100.f * i / iterations, &percent ) == 0)
fprintf( stderr, "\rbcrypt (rounds 10^%d): iteration %d / %d (%.0f%%)..", bcrypt_rounds, i, iterations, percent );
}
const double bcrypt9Speed = mpw_show_speed( startTime, iterations, "bcrypt" );
// Start SCrypt
// Phase one of mpw
iterations = 50; /* tuned to ~10s on dev machine */
mpw_time( &startTime );
for (int i = 1; i <= iterations; ++i) {
free( (void *)mpw_master_key( fullName, masterPassword, MPAlgorithmVersionCurrent ) );
if (modff( 100.f * i / iterations, &percent ) == 0)
fprintf( stderr, "\rscrypt_mpw: iteration %d / %d (%.0f%%)..", i, iterations, percent );
}
const double scryptSpeed = mpw_show_speed( startTime, iterations, "scrypt_mpw" );
// Start MPW
// Both phases of mpw
iterations = 50; /* tuned to ~10s on dev machine */
mpw_time( &startTime );
for (int i = 1; i <= iterations; ++i) {
masterKey = mpw_master_key( fullName, masterPassword, MPAlgorithmVersionCurrent );
if (!masterKey) {
ftl( "Could not allocate master key: %s", strerror( errno ) );
break;
}
free( (void *)mpw_site_result(
masterKey, siteName, siteCounter, keyPurpose, keyContext, resultType, NULL, MPAlgorithmVersionCurrent ) );
free( (void *)masterKey );
if (modff( 100.f * i / iterations, &percent ) == 0)
fprintf( stderr, "\rmpw: iteration %d / %d (%.0f%%)..", i, iterations, percent );
}
const double mpwSpeed = mpw_show_speed( startTime, iterations, "mpw" );
// Summarize.
fprintf( stdout, "\n== SUMMARY ==\nOn this machine,\n" );
fprintf( stdout, " - mpw is %f times slower than hmac-sha-256.\n", hmacSha256Speed / mpwSpeed );
fprintf( stdout, " - mpw is %f times slower than bcrypt (rounds 10^%d).\n", bcrypt9Speed / mpwSpeed, bcrypt_rounds );
fprintf( stdout, " - scrypt is %f times slower than bcrypt (rounds 10^%d).\n", bcrypt9Speed / scryptSpeed, bcrypt_rounds );
return 0;
}