bcrypt hashes implementation, not activated yet.

This commit is contained in:
Enno Rehling 2016-02-12 07:14:12 +01:00
parent 01e864273a
commit c0c6d19be2
4 changed files with 83 additions and 50 deletions

2
crypto

@ -1 +1 @@
Subproject commit e0f9891a91d69c042f82c1e13e48ab4c7160381d
Subproject commit 7101b264c8150c513d454421b1b263345ff90f66

View File

@ -108,12 +108,12 @@ static void test_addfaction(CuTest *tc) {
CuAssertPtrEquals(tc, NULL, (void *)f->ursprung);
CuAssertPtrEquals(tc, (void *)factions, (void *)f);
CuAssertStrEquals(tc, "test@eressea.de", f->email);
CuAssertIntEquals(tc, true, checkpasswd(f, "hurrdurr"));
CuAssertTrue(tc, checkpasswd(f, "hurrdurr"));
CuAssertPtrEquals(tc, (void *)lang, (void *)f->locale);
CuAssertIntEquals(tc, 1234, f->subscription);
CuAssertIntEquals(tc, 0, f->flags);
CuAssertIntEquals(tc, 0, f->age);
CuAssertIntEquals(tc, true, faction_alive(f));
CuAssertTrue(tc, faction_alive(f));
CuAssertIntEquals(tc, M_GRAY, f->magiegebiet);
CuAssertIntEquals(tc, turn, f->lastorders);
CuAssertPtrEquals(tc, f, findfaction(f->no));
@ -125,9 +125,9 @@ static void test_check_passwd(CuTest *tc) {
f = test_create_faction(0);
faction_setpassword(f, password_hash("password", 0, PASSWORD_DEFAULT));
CuAssertIntEquals(tc, true, checkpasswd(f, "password"));
CuAssertIntEquals(tc, false, checkpasswd(f, "assword"));
CuAssertIntEquals(tc, false, checkpasswd(f, "PASSWORD"));
CuAssertTrue(tc, checkpasswd(f, "password"));
CuAssertTrue(tc, !checkpasswd(f, "assword"));
CuAssertTrue(tc, !checkpasswd(f, "PASSWORD"));
}
static void test_get_monsters(CuTest *tc) {

View File

@ -2,6 +2,8 @@
#include "password.h"
#include <md5.h>
#include <crypt_blowfish.h>
#include <drepper.h>
#include <mtrand.h>
#include <assert.h>
@ -25,37 +27,68 @@
} while (0)
char *password_gensalt(void) {
static char salt[SALTLEN + 1];
char *password_gensalt(char *salt, size_t salt_len) {
size_t buflen = salt_len-1;
char *cp = salt;
int buflen = SALTLEN;
while (buflen) {
unsigned long ul = genrand_int32() & (unsigned long)time(0);
b64_from_24bit((char)(ul & 0xFF), (char)((ul>>8)&0xff), (char)((ul>>16)&0xFF), 4);
}
salt[SALTLEN] = 0;
salt[salt_len-1] = 0;
return salt;
}
static const char * password_hash_i(const char * passwd, const char *salt, int algo, char *result, size_t len) {
assert(passwd);
if (!salt) {
salt = password_gensalt();
}
if (algo==PASSWORD_PLAIN) {
_snprintf(result, len, "$0$%s$%s", salt, passwd);
}
else if (algo == PASSWORD_MD5) {
return md5_crypt_r(passwd, salt, result, len);
}
else if (algo == PASSWORD_APACHE_MD5) {
apr_md5_encode(passwd, salt, result, len);
static bool password_is_implemented(int algo) {
return algo == PASSWORD_BCRYPT || algo == PASSWORD_PLAIN || algo == PASSWORD_MD5 || algo == PASSWORD_APACHE_MD5;
}
static const char * password_hash_i(const char * passwd, const char *input, int algo, char *result, size_t len) {
if (algo == PASSWORD_BCRYPT) {
char salt[MAXSALTLEN];
char setting[40];
if (!input) {
input = password_gensalt(salt, MAXSALTLEN);
}
if (_crypt_gensalt_blowfish_rn("$2y$", 5, input, strlen(input), setting, sizeof(setting)) == NULL) {
return NULL;
}
if (_crypt_blowfish_rn(passwd, setting, result, len) == NULL) {
return NULL;
}
return result;
}
else {
return NULL;
else if (algo == PASSWORD_PLAIN) {
_snprintf(result, len, "$0$%s", passwd);
return result;
}
return result;
else if (password_is_implemented(algo)) {
char salt[MAXSALTLEN];
assert(passwd);
if (input) {
const char * dol = strchr(input, '$');
size_t salt_len;
if (dol) {
assert(dol > input && dol[0] == '$');
salt_len = dol - input;
}
else {
salt_len = strlen(input);
}
assert(salt_len < MAXSALTLEN);
stpncpy(salt, input, salt_len);
salt[salt_len] = 0;
} else {
input = password_gensalt(salt, sizeof(salt));
}
if (algo == PASSWORD_MD5) {
return md5_crypt_r(passwd, input, result, len);
}
else if (algo == PASSWORD_APACHE_MD5) {
apr_md5_encode(passwd, input, result, len);
return result;
}
}
return NULL;
}
const char * password_hash(const char * passwd, const char * salt, int algo) {
@ -64,31 +97,24 @@ const char * password_hash(const char * passwd, const char * salt, int algo) {
return password_hash_i(passwd, salt, algo, result, sizeof(result));
}
static bool password_is_implemented(int algo) {
return algo==PASSWORD_PLAIN || algo==PASSWORD_MD5 || algo==PASSWORD_APACHE_MD5;
}
int password_verify(const char * pwhash, const char * passwd) {
char salt[MAXSALTLEN+1];
char hash[64];
size_t len;
int algo;
char *pos;
const char *dol, *result;
const char *result;
assert(passwd);
assert(pwhash);
assert(pwhash[0] == '$');
algo = pwhash[1];
if (algo == PASSWORD_BCRYPT) {
char sample[200];
_crypt_blowfish_rn(passwd, pwhash, sample, sizeof(sample));
return (strcmp(sample, pwhash) == 0) ? VERIFY_OK : VERIFY_FAIL;
}
pos = strchr(pwhash+2, '$');
assert(pos && pos[0] == '$');
++pos;
dol = strchr(pos, '$');
assert(dol>pos && dol[0] == '$');
len = dol - pos;
assert(len <= MAXSALTLEN);
strncpy(salt, pos, len);
salt[len] = 0;
result = password_hash_i(passwd, salt, algo, hash, sizeof(hash));
pos = strchr(pos, '$')+1;
result = password_hash_i(passwd, pos, algo, hash, sizeof(hash));
if (!password_is_implemented(algo)) {
return VERIFY_UNKNOWN;
}

View File

@ -3,24 +3,31 @@
#include "password.h"
static void test_passwords(CuTest *tc) {
const char *hash;
const char *hash, *expect;
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify("$9$password", "password"));
expect = "$apr1$FqQLkl8g$.icQqaDJpim4BVy.Ho5660";
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "Hodor"));
hash = password_hash("Hodor", "FqQLkl8g", PASSWORD_APACHE_MD5);
CuAssertPtrNotNull(tc, hash);
CuAssertStrEquals(tc, "$apr1$FqQLkl8g$.icQqaDJpim4BVy.Ho5660", hash);
CuAssertIntEquals(tc, VERIFY_OK, password_verify(hash, "Hodor"));
CuAssertStrEquals(tc, expect, hash);
expect = "$1$ZouUn04i$yNnT1Oy8azJ5V.UM9ppP5/";
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "jollygood"));
hash = password_hash("jollygood", "ZouUn04i", PASSWORD_MD5);
CuAssertPtrNotNull(tc, hash);
CuAssertStrEquals(tc, "$1$ZouUn04i$yNnT1Oy8azJ5V.UM9ppP5/", hash);
CuAssertIntEquals(tc, VERIFY_OK, password_verify(hash, "jollygood"));
CuAssertStrEquals(tc, expect, hash);
expect = "$0$password";
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "password"));
CuAssertIntEquals(tc, VERIFY_FAIL, password_verify(expect, "arseword"));
hash = password_hash("password", "hodor", PASSWORD_PLAIN);
CuAssertPtrNotNull(tc, hash);
CuAssertStrEquals(tc, "$0$hodor$password", hash);
CuAssertIntEquals(tc, VERIFY_OK, password_verify(hash, "password"));
CuAssertIntEquals(tc, VERIFY_FAIL, password_verify(hash, "arseword"));
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify("$9$saltyfish$password", "password"));
CuAssertStrEquals(tc, expect, hash);
expect = "$2y$05$RJ8qAhu.foXyJLdc2eHTLOaK4MDYn3/v4HtOVCq0Plv2yxcrEB7Wm";
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "Hodor"));
}
CuSuite *get_password_suite(void) {