The arena of proper auth & data security standards is often some of the most misunderstood, confusing, and tricky aspects of building Node apps. Using open source auth techniques and proper data encryption standards, we’ll learn how to make intelligent decisions on creating a solid infrastructure to protect our users and data. We’ll dive into auth systems, data attack vectors, how to protect your systems, and common security pitfalls in Node.
8. Brute Force Attacks!
Calculate all key variations within a given length, then
trying each one until the password is guessed. !
Protect via: Key stretching, CAPTCHA, 2FA!
!
Dictionary Attacks!
Use a list of predetermined words/phrase to guess password.!
Protect via: Salting!
!
Rainbow Tables!
Use precalculated password hashes to break encryption.!
Protect via: Salting !
Protecting Against Password Attacks!
10. //hashing identical messages with no salt!
hash('mechagodzilla') = !
162e0a91026a28f1f2afa11099d1fcbdd9f2e351095ebb196c90e10290ef1227!
hash('mechagodzilla') = !
162e0a91026a28f1f2afa11099d1fcbdd9f2e351095ebb196c90e10290ef1227!
!
//hashing identical messages with random salt!
hash('mechagodzilla' + '458cf2979ef27397db67077775225334') = !
f3499a916612e285612b32702114751f557a70606c32b54b92de55153d40d3b6!
hash('mechagodzilla' + 'ef5b72eff781b09a0784438af742dd6e') = !
7e29c5c48f44755598dec3549155ad66f1af4671091353be4c4d7694d71dc866!
hash('mechagodzilla' + 'cc989b105a1c6a5f0fb460e29dd272f3') = !
6dedd3dbb0639e6e00ca0bf6272c141fb741e24925cb7548491479a1df2c215e!
Hashing with and without salts!
11. Storing Salts!
Store alongside the hash!
!
Salt Reuse!
Salts should be be unique per password!
!
Salt Length!
Same size as hash? 64 bits? 128 bits?!
Considerations when using Salts!
12. bcrypt!
Designed for password security, based on the blowfish
cipher, CPU & RAM intensive.!
!
PBKDF2!
Comes from RSA laboratories, performs the HMAC (hash +
key) over a specific number of iterations.!
!
scrypt!
Designed to make it costly to perform large-scale
hardware attacks by requiring large amounts of memory!
Password Encryption Algorithms!
13. !
var bcrypt = require('bcrypt');!
!
app.post("/register", function(req, res){!
//capture user login information!
var username = req.body.username;!
var password = req.body.password;!
!
//generate salt, then hash!
bcrypt.genSalt(10, function(err, salt) {!
bcrypt.hash(password, salt, function(err, key) {!
console.log('key: ' + key.toString('hex'));!
console.log('salt: ' + salt.toString('hex'));!
});!
});!
});!
!
Hashing with bcrypt!
14. !
var bcrypt = require('bcrypt');!
!
app.post("/login", function(req, res){!
//capture user login information!
var username = req.body.username;!
var password = req.body.password;!
!
//fetch user record from database !
//required info: stored hash!
!
//compare password from login to stored user hash!
bcrypt.compare(password, hash, function(err, res){!
//returns true or false!
});!
});!
!
Login Hash Comparison with bcrypt!
15. !
var crypto = require('crypto');!
!
app.post("/register", function(req, res){!
//capture user login information!
var username = req.body.username;!
var password = req.body.password;!
!
//generate salt, then hash!
crypto.randomBytes(32, function(ex, salt){!
crypto.pbkdf2(password, salt, 4096, 512, 'sha256', function(err, key){!
if (err) throw err;!
//store username, hashed password, and salt in your database!
});!
});!
});!
!
Hashing with PBKDF2!
16. !
var crypto = require('crypto');!
!
app.post("/login", function(req, res){!
//capture user login information!
var username = req.body.username;!
var password = req.body.password;!
!
var dbsalt = 'USER RECORD SALT FROM YOUR DATABASE';!
var dbhash = 'USER RECORD KEY FROM YOUR DATABASE';!
!
//generate hash with login attempt, then compare to stored user hash!
crypto.pbkdf2(password, dbsalt, 4096, 512, 'sha256', function(err, comparehash){!
if (err) throw err;!
if (dbhash.toString('hex') === comparehash.toString('hex')){ !
//passwords match!
} else { !
//passwords don't match!
}!
});!
});!
!
Login Hash Comparison with PBKDF2!
26. //handle all POST requests!
app.post('/', function (req, res){!
var message = req.body;!
res.send('Message received:' + querystring.stringify(message));!
});!
!
//set certificate options!
var options = {!
key: fs.readFileSync('server.key'),!
cert: fs.readFileSync('server.crt'),!
passphrase: 'YOUR KEY PASSWORD' !
};!
!
//create server with certificate options!
https.createServer(options, app).listen(3000, function () {!
console.log('Server started: Listening on port 3000');!
});!
Setting up Express server for HTTPS traffic!
31. Encryption (ECB, CBC, OFB, CFB, CTR)!
Data privacy and confidentiality mode. Attacker
cannot obtain info on the plaintext data.!
!
Authentication(CMAC)!
Data authenticity mode. Receiver can validate
whether cleartext came from intended sender.!
!
Authenticated Encryption (CCM, GCM, KW/KWP/TKW)!
Includes both data privacy and authenticity.!
Modes of Operation!
32. var crypto = require('crypto');!
!
var text = "Encryption Testing AES";!
var key = crypto.randomBytes(32); //256 bit shared secret!
var iv = crypto.randomBytes(16); //initialization vector - 16 bytes!
var algorithm = 'aes-256-ctr'; //cypher and mode of operation!
!
//encrypt!
var cipher = crypto.createCipher(algorithm, key, iv);!
var encrypted = cipher.update(text, 'utf8', 'hex');!
encrypted += cipher.final('hex');!
console.log("Encrypted: " + encrypted);!
Configuring and encrypting message!
33. //----!
// data sent to server: ciphertext (encrypted var)!
// data known by server: key!
//----!
!
//cypher and mode of operation!
var algorithm = 'aes-256-gcm'; !
!
//decrypt!
var decipher = crypto.createDecipher(algorithm, key, iv);!
var decrypted = decipher.update(encrypted, 'hex', 'utf8');!
decrypted += decipher.final('utf8');!
console.log("Decrypted: " + decrypted);!
Decrypting ciphertext!