Merge branch 'dauth' into 'master'
Use DAuth instead of botan for password hashing. Fixes #7 Closes #7 See merge request fsimphy/calendar-webapp!15
This commit is contained in:
commit
c918e8e574
6 changed files with 31 additions and 56 deletions
6
dub.json
6
dub.json
|
@ -4,15 +4,11 @@
|
||||||
"Johannes Loher"
|
"Johannes Loher"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"dauth": "~>0.6.3",
|
||||||
"mysql-native": "~>1.1.2",
|
"mysql-native": "~>1.1.2",
|
||||||
"botan": "~>1.12.9",
|
|
||||||
"vibe-d": "~>0.8.1",
|
"vibe-d": "~>0.8.1",
|
||||||
"vibe-d:tls": "~>0.8.1",
|
|
||||||
"poodinis": "~>8.0.1"
|
"poodinis": "~>8.0.1"
|
||||||
},
|
},
|
||||||
"subConfigurations": {
|
|
||||||
"vibe-d:tls": "botan"
|
|
||||||
},
|
|
||||||
"description": "A simple webapplication to edit and view calendar entries",
|
"description": "A simple webapplication to edit and view calendar entries",
|
||||||
"copyright": "Copyright © 2017, Johannes Loher",
|
"copyright": "Copyright © 2017, Johannes Loher",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
@ -4,7 +4,7 @@ USE CalendarWebapp;
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
username CHAR(30) NOT NULL UNIQUE,
|
username CHAR(30) NOT NULL UNIQUE,
|
||||||
passwordHash CHAR(60) NOT NULL,
|
passwordHash CHAR(92) NOT NULL,
|
||||||
privilege TINYINT UNSIGNED NOT NULL,
|
privilege TINYINT UNSIGNED NOT NULL,
|
||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
@ -21,4 +21,4 @@ CREATE TABLE events (
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO users (username, passwordHash, privilege) VALUES ('foo',
|
INSERT INTO users (username, passwordHash, privilege) VALUES ('foo',
|
||||||
'$2a$10$9LBqOZV99ARiE4Nx.2b7GeYfqk2.0A32PWGu2cRGyW2hRJ0xeDfnO', 2);
|
'$5$eGohWUmw9yyiTqG7kti1MmT/jR52raEVlYuHQJa/sYk=$ucI+vTQq38Rr5RUAatd4Om0Dy9fuF0oKgkuVCuXSnxc=', 2);
|
||||||
|
|
|
@ -30,8 +30,6 @@ private:
|
||||||
public:
|
public:
|
||||||
Nullable!AuthInfo checkUser(string username, string password) @safe
|
Nullable!AuthInfo checkUser(string username, string password) @safe
|
||||||
{
|
{
|
||||||
import botan.passhash.bcrypt : checkBcrypt;
|
|
||||||
|
|
||||||
auto result = users.findOne(["username" : username]);
|
auto result = users.findOne(["username" : username]);
|
||||||
/* checkHash should be called using vibe.core.concurrency.async to
|
/* checkHash should be called using vibe.core.concurrency.async to
|
||||||
avoid blocking, but https://github.com/vibe-d/vibe.d/issues/1521 is
|
avoid blocking, but https://github.com/vibe-d/vibe.d/issues/1521 is
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
module calendarwebapp.configuration;
|
module calendarwebapp.configuration;
|
||||||
|
|
||||||
import botan.rng.auto_rng : AutoSeededRNG;
|
|
||||||
import botan.rng.rng : RandomNumberGenerator;
|
|
||||||
|
|
||||||
import calendarwebapp.authenticator : Authenticator, MongoDBAuthenticator,
|
import calendarwebapp.authenticator : Authenticator, MongoDBAuthenticator,
|
||||||
MySQLAuthenticator;
|
MySQLAuthenticator;
|
||||||
import calendarwebapp.calendarwebapp : CalendarWebapp;
|
import calendarwebapp.calendarwebapp : CalendarWebapp;
|
||||||
import calendarwebapp.event : EventStore, MongoDBEventStore, MySQLEventStore;
|
import calendarwebapp.event : EventStore, MongoDBEventStore, MySQLEventStore;
|
||||||
import calendarwebapp.passhash : BcryptPasswordHasher, PasswordHasher;
|
import calendarwebapp.passhash : PasswordHasher, SHA256PasswordHasher;
|
||||||
|
|
||||||
import mysql : MySQLPool;
|
import mysql : MySQLPool;
|
||||||
|
|
||||||
|
@ -28,9 +25,7 @@ public:
|
||||||
container.register!MongoClient.existingInstance(mongoClient);
|
container.register!MongoClient.existingInstance(mongoClient);
|
||||||
container.register!(EventStore, MySQLEventStore);
|
container.register!(EventStore, MySQLEventStore);
|
||||||
container.register!(Authenticator, MySQLAuthenticator);
|
container.register!(Authenticator, MySQLAuthenticator);
|
||||||
|
container.register!(PasswordHasher, SHA256PasswordHasher);
|
||||||
container.register!(PasswordHasher, BcryptPasswordHasher);
|
|
||||||
container.register!(RandomNumberGenerator, AutoSeededRNG);
|
|
||||||
container.register!CalendarWebapp;
|
container.register!CalendarWebapp;
|
||||||
container.register!(ValueInjector!string, StringInjector);
|
container.register!(ValueInjector!string, StringInjector);
|
||||||
container.register!(ValueInjector!MongoCollection, MongoCollectionInjector);
|
container.register!(ValueInjector!MongoCollection, MongoCollectionInjector);
|
||||||
|
|
|
@ -1,33 +1,11 @@
|
||||||
module calendarwebapp.passhash;
|
module calendarwebapp.passhash;
|
||||||
|
|
||||||
import poodinis;
|
|
||||||
|
|
||||||
interface PasswordHasher
|
interface PasswordHasher
|
||||||
{
|
{
|
||||||
string generateHash(in string password) @safe;
|
string generateHash(in string password) const @safe;
|
||||||
bool checkHash(in string password, in string hash) const @safe;
|
bool checkHash(in string password, in string hash) const @safe;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BcryptPasswordHasher : PasswordHasher
|
|
||||||
{
|
|
||||||
import botan.passhash.bcrypt : checkBcrypt, generateBcrypt;
|
|
||||||
import botan.rng.rng : RandomNumberGenerator;
|
|
||||||
|
|
||||||
string generateHash(in string password) @safe
|
|
||||||
{
|
|
||||||
return (() @trusted => generateBcrypt(password, rng, cost))();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkHash(in string password, in string hash) const @safe
|
|
||||||
{
|
|
||||||
return (()@trusted => checkBcrypt(password, hash))();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
@Autowire RandomNumberGenerator rng;
|
|
||||||
enum cost = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
class StubPasswordHasher : PasswordHasher
|
class StubPasswordHasher : PasswordHasher
|
||||||
{
|
{
|
||||||
string generateHash(in string password) const @safe pure nothrow
|
string generateHash(in string password) const @safe pure nothrow
|
||||||
|
@ -40,3 +18,19 @@ class StubPasswordHasher : PasswordHasher
|
||||||
return password == hash;
|
return password == hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SHA256PasswordHasher : PasswordHasher
|
||||||
|
{
|
||||||
|
import dauth : dupPassword, isSameHash, makeHash, parseHash;
|
||||||
|
import std.digest.sha : SHA256;
|
||||||
|
|
||||||
|
string generateHash(in string password) const @safe
|
||||||
|
{
|
||||||
|
return (() @trusted => password.dupPassword.makeHash!SHA256.toCryptString)();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkHash(in string password, in string hash) const @safe
|
||||||
|
{
|
||||||
|
return (() @trusted => isSameHash(password.dupPassword, parseHash(hash)))();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,25 +2,8 @@ module test.calendarwebapp.testpasshash;
|
||||||
|
|
||||||
import calendarwebapp.passhash;
|
import calendarwebapp.passhash;
|
||||||
|
|
||||||
import poodinis;
|
|
||||||
|
|
||||||
import unit_threaded;
|
import unit_threaded;
|
||||||
|
|
||||||
@("BcryptPasswordHasher")
|
|
||||||
@Values("", "test", "langesKompliziertesPasswort")
|
|
||||||
@system unittest
|
|
||||||
{
|
|
||||||
import botan.rng.rng : RandomNumberGenerator;
|
|
||||||
import botan.rng.auto_rng : AutoSeededRNG;
|
|
||||||
auto container = new shared DependencyContainer;
|
|
||||||
container.register!(RandomNumberGenerator, AutoSeededRNG);
|
|
||||||
container.register!(PasswordHasher, BcryptPasswordHasher);
|
|
||||||
|
|
||||||
auto hasher = container.resolve!PasswordHasher;
|
|
||||||
immutable testPassword = getValue!string;
|
|
||||||
hasher.checkHash(testPassword, hasher.generateHash(testPassword)).shouldBeTrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@("StubPasswordHasher")
|
@("StubPasswordHasher")
|
||||||
@Values("", "test", "langesKompliziertesPasswort")
|
@Values("", "test", "langesKompliziertesPasswort")
|
||||||
@safe unittest
|
@safe unittest
|
||||||
|
@ -29,3 +12,12 @@ import unit_threaded;
|
||||||
immutable testPassword = getValue!string;
|
immutable testPassword = getValue!string;
|
||||||
hasher.checkHash(testPassword, hasher.generateHash(testPassword)).shouldBeTrue;
|
hasher.checkHash(testPassword, hasher.generateHash(testPassword)).shouldBeTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@("SHA256PasswordHasher")
|
||||||
|
@Values("", "test", "langesKompliziertesPasswort")
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
immutable hasher = new SHA256PasswordHasher;
|
||||||
|
immutable testPassword = getValue!string;
|
||||||
|
hasher.checkHash(testPassword, hasher.generateHash(testPassword)).shouldBeTrue;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue