User IP Hashes are now salted with 24 bits from a cryptographically secure random generation function formatted into base 64 for extra privacy/security.
This commit is contained in:
parent
75301ec7d9
commit
ade2a4210d
|
|
@ -132,7 +132,6 @@ class chatPreprocessor{
|
||||||
commandObj.links = [];
|
commandObj.links = [];
|
||||||
|
|
||||||
//For each link sent from the client
|
//For each link sent from the client
|
||||||
//this.rawData.links.forEach((link) => {
|
|
||||||
for (const link of commandObj.rawData.links){
|
for (const link of commandObj.rawData.links){
|
||||||
//Add a marked link object to our links array
|
//Add a marked link object to our links array
|
||||||
commandObj.links.push(await linkUtils.markLink(link));
|
commandObj.links.push(await linkUtils.markLink(link));
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,6 @@ const userBanSchema = new mongoose.Schema({
|
||||||
* @returns {Mongoose.Document} Found ban Document if one exists.
|
* @returns {Mongoose.Document} Found ban Document if one exists.
|
||||||
*/
|
*/
|
||||||
userBanSchema.statics.checkBanByIP = async function(ip){
|
userBanSchema.statics.checkBanByIP = async function(ip){
|
||||||
//Get hash of ip
|
|
||||||
const ipHash = hashUtil.hashIP(ip);
|
|
||||||
//Get all bans
|
//Get all bans
|
||||||
const banDB = await this.find({});
|
const banDB = await this.find({});
|
||||||
//Create null variable to hold any found ban
|
//Create null variable to hold any found ban
|
||||||
|
|
@ -106,7 +104,7 @@ userBanSchema.statics.checkBanByIP = async function(ip){
|
||||||
const curHash = ban.ips.hashed[ipIndex];
|
const curHash = ban.ips.hashed[ipIndex];
|
||||||
|
|
||||||
//Check the current hash against the given hash
|
//Check the current hash against the given hash
|
||||||
if(ipHash == curHash){
|
if(hashUtil.compareIPHash(ip, curHash)){
|
||||||
//If it matches we found the ban
|
//If it matches we found the ban
|
||||||
foundBan = ban;
|
foundBan = ban;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -757,8 +757,6 @@ userSchema.methods.tattooIPRecord = async function(ip){
|
||||||
lastLog: new Date()
|
lastLog: new Date()
|
||||||
};
|
};
|
||||||
|
|
||||||
//We should really start using for loops and stop acting like its 2008
|
|
||||||
//Though to be quite honest this bit would be particularly brutal without them
|
|
||||||
//For every user in the userlist
|
//For every user in the userlist
|
||||||
for(let curUser of users){
|
for(let curUser of users){
|
||||||
//Ensure we're not checking the user against itself
|
//Ensure we're not checking the user against itself
|
||||||
|
|
@ -766,7 +764,7 @@ userSchema.methods.tattooIPRecord = async function(ip){
|
||||||
//For every IP record in the current user
|
//For every IP record in the current user
|
||||||
for(let curRecord of curUser.recentIPs){
|
for(let curRecord of curUser.recentIPs){
|
||||||
//If it matches the current ipHash
|
//If it matches the current ipHash
|
||||||
if(curRecord.ipHash == ipHash){
|
if(hashUtil.compareIPHash(ip, curRecord.ipHash)){
|
||||||
//Check if we've already marked the user as an alt
|
//Check if we've already marked the user as an alt
|
||||||
const foundAlt = this.alts.indexOf(curUser._id);
|
const foundAlt = this.alts.indexOf(curUser._id);
|
||||||
|
|
||||||
|
|
@ -803,7 +801,7 @@ userSchema.methods.tattooIPRecord = async function(ip){
|
||||||
//Look for matching ip record
|
//Look for matching ip record
|
||||||
function checkHash(ipRecord){
|
function checkHash(ipRecord){
|
||||||
//return matching records
|
//return matching records
|
||||||
return ipRecord.ipHash == ipHash;
|
return hashUtil.compareIPHash(ip, ipRecord.ipHash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,17 +60,40 @@ module.exports.compareLegacyPassword = function(pass, hash){
|
||||||
*
|
*
|
||||||
* Provides a basic level of privacy by only logging salted hashes of IP's
|
* Provides a basic level of privacy by only logging salted hashes of IP's
|
||||||
* @param {String} ip - IP to hash
|
* @param {String} ip - IP to hash
|
||||||
* @returns {String} Hashed/Peppered IP Adress
|
* @param {String} salt - (optional) string to salt IP with, leave empty to default to a securely generated string encoded in base64
|
||||||
|
* @returns {String} Hashed/Peppered/Salted IP Address
|
||||||
*/
|
*/
|
||||||
module.exports.hashIP = function(ip){
|
module.exports.hashIP= function(ip, salt){
|
||||||
//Create hash object
|
//Create hash object
|
||||||
const hashObj = crypto.createHash('sha512');
|
const hashObj = crypto.createHash('sha512');
|
||||||
|
|
||||||
//add IP and pepper to the hash
|
//If we wheren't provided salt
|
||||||
hashObj.update(`${ip}${config.secrets.ipSecret}`);
|
if(salt == null){
|
||||||
|
//Generate salt with cryptographically secure rng function
|
||||||
|
const rawSalt = crypto.randomBytes(24);
|
||||||
|
//Convert generated salt to base64
|
||||||
|
salt = rawSalt.toString('base64');
|
||||||
|
}
|
||||||
|
|
||||||
//return the IP hash as a string
|
//Generate new salted hash
|
||||||
return hashObj.digest('hex');
|
hashObj.update(`${ip}${config.secrets.ipSecret}${salt}`);
|
||||||
|
|
||||||
|
//Convert hash data into a base64 string
|
||||||
|
const hash = hashObj.digest('base64');
|
||||||
|
|
||||||
|
//Return salty hash
|
||||||
|
return `${salt}$${hash}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.compareIPHash = function(ip, hash){
|
||||||
|
//Split hash by salt delimiter
|
||||||
|
const splitHash = hash.split("$");
|
||||||
|
|
||||||
|
//Re-generate hash from received plaintext IP and salt scraped from existing hash
|
||||||
|
const tempHash = module.exports.hashIP(ip, splitHash[0]);
|
||||||
|
|
||||||
|
//If the hash we calculates matches the original
|
||||||
|
return tempHash == hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue