Skip to content
Snippets Groups Projects
Commit ea63b8b5 authored by Jukka-Pekka Sirkiä's avatar Jukka-Pekka Sirkiä
Browse files

First commit

parents
No related branches found
No related tags found
No related merge requests found
node_modules/
*.env
*.db
.vscode
\ No newline at end of file
# Secure password hashing server
This is a Node.js application implementing a secure password hashing server. The application is created for the fourth weekly exercise on the course DTEK8102 Privacy and Security for Software Systems.
\ No newline at end of file
This diff is collapsed.
{
"name": "hashing-server",
"version": "1.0.0",
"description": "Server for secure password hashing",
"main": "index.js",
"scripts": {
"start": "node src/index.js",
"watch": "nodemon src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jukka-Pekka Sirkiä",
"license": "UNLICENSED",
"dependencies": {
"axios": "^0.19.0",
"body-parser": "^1.19.0",
"express": "^4.17.1",
"nodemon": "^2.0.2",
"sqlite3": "^4.1.1"
}
}
const userDataServices = require('../services/userData');
const storeUsernameAndPassword = (req, res) => {
userDataServices.storeUsernameAndPassword(req.body.username, req.body.password, (err, data) => {
if (err) res.status(503).send('Server error');
res.status(200).json(data);
});
};
module.exports = {
storeUsernameAndPassword
};
\ No newline at end of file
const sqlite3 = require('sqlite3').verbose();
const fs = require('fs');
const dbPath = './src/database/app.db';
// Open the database.
const db = new sqlite3.Database(dbPath, (err) => {
if (err)
return console.error('Could not connect to the database.');
console.log('Connected to the database.');
});
// Function to initialize the database.
const initializeDatabase = () => {
// Load the SQL script from a file.
var sql = fs.readFileSync(__dirname + '/initializeDatabase.sql').toString();
// Execute the script.
db.exec(sql, (err) => {
if (err)
return console.error('Failed to initialize the database.');
console.log('Database initialized.');
});
};
// Function for adding a row to a table.
const addRow = (tableName, values, callback) => {
// Create the SQL script from the parameters.
var sql = `INSERT INTO ${tableName} VALUES(`;
for (var i = 0; i < values.length; i++) {
if (i !== (values.length - 1))
sql += '?, ';
else
sql += '?)';
}
// Execute the SQL script.
db.run(sql, values, (err) => {
if (err) {
console.error(`Failed to add a row to the table "${tableName}"`);
console.error(err);
return callback(err);
}
console.log(`Row was added to the table "${tableName}".`);
callback(null);
});
};
// Function for getting a row from the "users" table.
const getUser = (tableName, username, callback) => {
// The SQL query.
const sql = `SELECT * FROM ${tableName} where username=${username}`;
// Execute the SQL query.
db.all(sql, [], (err, rows) => {
if (err) {
console.error(`Failed to add a user to the table "${tableName}".`);
console.error(err);
return callback(err);
}
console.log('Database query for getting user data was executed.');
callback(null, rows);
});
};
module.exports = {
initializeDatabase,
addRow,
getUser,
};
\ No newline at end of file
-- Create users table.
DROP TABLE IF EXISTS users;
CREATE TABLE users (
username TEXT NOT NULL UNIQUE,
password_salt INTEGER NOT NULL,
password_hash INTEGER NOT NULL
);
\ No newline at end of file
const express = require('express');
const bodyParser = require('body-parser');
const router = require('./routes/routes');
const startServer = () => {
const app = express();
app.use(bodyParser.json());
app.use('/', router);
const PORT = 8000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
};
const initializeDatabase = () => {
const dataAccess = require('./database/dataAccess');
dataAccess.initializeDatabase();
};
initializeDatabase();
startServer();
\ No newline at end of file
post http://localhost:8000/api/v1/userData
content-type: application/json
{
"username": "Superuser",
"password": "StrongPassword"
}
\ No newline at end of file
const express = require('express');
const router = express.Router();
const controllers = require('../controllers/controllers');
router.post('/api/v1/userData', controllers.storeUsernameAndPassword);
module.exports = router;
\ No newline at end of file
const hashing = require('../utils/hashing');
const dataAccess = require('../database/dataAccess');
const storeUsernameAndPassword = (username, password, callback) => {
// Create a unique salt.
hashing.getSalt((err, salt) => {
if (err) return callback(err);
// Create a hash.
hashing.getHash(password, salt, (err, hash) => {
if (err) return callback(err);
// Store the username, the salt and the hash to the database.
dataAccess.addRow('users', [username, salt, hash], (err, val) => {
if (err) return callback(err);
callback(null, {username, password, salt: salt.toString('hex'), hash});
});
});
});
};
module.exports = {
storeUsernameAndPassword
};
\ No newline at end of file
const crypto = require('crypto');
// Get 32-bytes long salt based on cryptographically secure random number.
const getSalt = callback => {
crypto.randomBytes(32, (err, buf) => {
if (err) {
console.error('There was an error in creating the salt:\n', err);
return callback(err);
}
return callback(null, buf);
});
};
// Create a password hash based on the scrypt function.
const getHash = (password, salt, callback) => {
let options = {
N: 16384,
r: 8,
p: 1,
};
crypto.scrypt(password, salt, 64, options, (err, hash) => {
if (err) {
console.error('There was an error in creating the password hash:\n', err);
return callback(err);
}
return callback(null, hash.toString('hex'));
});
};
module.exports = {
getSalt,
getHash
};
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment