From 19bcd82dc5c37dbb4ad953b1593cd52ca3d3a4e0 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 9 Jul 2019 23:11:06 -0400 Subject: [PATCH 1/5] Create README.MD --- README.MD | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 README.MD diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..e72e3f2 --- /dev/null +++ b/README.MD @@ -0,0 +1,17 @@ +# SponsorBlocker Server + +SponsorBlocker is an extension that will skip over sponsored segments of YouTube videos. SponsorBlocker is a crowdsourced browser extension that let's anyone submit the start and end time's of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment. + +This is the server backend for it + +# Server + +This is a simple Sqlite database that will hold all the timing data. + +To make sure that this project doesn't die, I have made the database publicly downloadable at https://sponsor.ajay.app/database.db. So, you can download a backup or get archive.org to take a backup if you do desire. + +Hopefully this project can be combined with projects like [this](https://github.com/Sponsoff/sponsorship_remover) and use this data to create a neural network to predict when sponsored segments happen. That project is sadly abandoned now, so I have decided to attempt to revive this idea. + +# Client + +The client web browser extension is available here: https://github.com/ajayyy/SponsorBlocker From 27a6741d3ed0c7950f9b77324498df5be6f76793 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Wed, 17 Jul 2019 22:04:04 -0400 Subject: [PATCH 2/5] Update README.MD --- README.MD | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.MD b/README.MD index e72e3f2..2dbf70b 100644 --- a/README.MD +++ b/README.MD @@ -1,6 +1,6 @@ -# SponsorBlocker Server +# SponsorBlock Server -SponsorBlocker is an extension that will skip over sponsored segments of YouTube videos. SponsorBlocker is a crowdsourced browser extension that let's anyone submit the start and end time's of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment. +SponsorBlock is an extension that will skip over sponsored segments of YouTube videos. SponsorBlock is a crowdsourced browser extension that let's anyone submit the start and end time's of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment. This is the server backend for it @@ -14,4 +14,4 @@ Hopefully this project can be combined with projects like [this](https://github. # Client -The client web browser extension is available here: https://github.com/ajayyy/SponsorBlocker +The client web browser extension is available here: https://github.com/ajayyy/SponsorBlock From af1ae4346f6bfe411124b7546dc429e07ea5d3ff Mon Sep 17 00:00:00 2001 From: Official Noob <31563761+OfficialNoob@users.noreply.github.com> Date: Tue, 30 Jul 2019 18:14:25 +0100 Subject: [PATCH 3/5] Added hash function and BehindProxy bool --- index.js | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/index.js b/index.js index 49adcbb..1eaaf32 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ var express = require('express'); var http = require('http'); - +var BehindProxy = true // Create a service (the app object is just a callback). var app = express(); @@ -16,6 +16,14 @@ var db = new sqlite3.Database('./databases/sponsorTimes.db'); //where the more sensitive data such as IP addresses are stored var privateDB = new sqlite3.Database('./databases/private.db'); +function hash (value, times=5000) { // Should be bcrypt!!! + for (let i = 0; i < times; i++) { + let hashCreator = crypto.createHash('sha256'); + value = hashCreator.update(value).digest('hex'); + } + return value; +} + // Create an HTTP service. http.createServer(app).listen(80); @@ -98,15 +106,9 @@ app.get('/api/postVideoSponsorTimes', function (req, res) { userID = getHashedUserID(userID); //x-forwarded-for if this server is behind a proxy - let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; - - //hash the ip so no one can get it from the database - let hashedIP = ip + globalSalt; - //hash it 5000 times, this makes it very hard to brute force - for (let i = 0; i < 5000; i++) { - let hashCreator = crypto.createHash('sha256'); - hashedIP = hashCreator.update(hashedIP).digest('hex'); - } + let ip = BehindProxy ? req.headers['x-forwarded-for'] || req.connection.remoteAddress; + //hash the ip 5000 times so no one can get it from the database + let hashedIP = hash(ip + globalSalt); startTime = parseFloat(startTime); endTime = parseFloat(endTime); @@ -186,13 +188,8 @@ app.get('/api/voteOnSponsorTime', function (req, res) { //x-forwarded-for if this server is behind a proxy let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; - //hash the ip so no one can get it from the database - let hashedIP = ip + globalSalt; - //hash it 5000 times, this makes it very hard to brute force - for (let i = 0; i < 5000; i++) { - let hashCreator = crypto.createHash('sha256'); - hashedIP = hashCreator.update(hashedIP).digest('hex'); - } + //hash the ip 5000 times so no one can get it from the database + let hashedIP = hash(ip + globalSalt); //check if vote has already happened privateDB.prepare("SELECT type FROM votes WHERE userID = ? AND UUID = ?").get(userID, UUID, function(err, row) { @@ -294,14 +291,8 @@ app.get('/database.db', function (req, res) { }); function getHashedUserID(userID) { - //hash the userID so no one can get it from the database - let hashedUserID = userID; - //hash it 5000 times, this makes it very hard to brute force - for (let i = 0; i < 5000; i++) { - let hashCreator = crypto.createHash('sha256'); - hashedUserID = hashCreator.update(hashedUserID).digest('hex'); - } - + //hash the userID 5000 times so no one can get it from the database + let hashedUserID = hash(userID); return hashedUserID; } @@ -494,4 +485,4 @@ function getWeightedRandomChoice(choices, weights, amountOfChoices) { finalChoices: finalChoices, choicesDealtWith: choicesDealtWith }; -} \ No newline at end of file +} From c67fb34588dc55b929bfdb4d40e551aec8ea2c0a Mon Sep 17 00:00:00 2001 From: Official Noob <31563761+OfficialNoob@users.noreply.github.com> Date: Tue, 30 Jul 2019 18:43:23 +0100 Subject: [PATCH 4/5] Removed uuidv1 and added GetIP() --- index.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index 1eaaf32..08eb1d7 100644 --- a/index.js +++ b/index.js @@ -4,9 +4,6 @@ var BehindProxy = true // Create a service (the app object is just a callback). var app = express(); -//uuid service -var uuidv1 = require('uuid/v1'); - //hashing service var crypto = require('crypto'); @@ -29,7 +26,7 @@ http.createServer(app).listen(80); //global salt that is added to every ip before hashing to // make it even harder for someone to decode the ip -var globalSalt = "49cb0d52-1aec-4b89-85fc-fab2c53062fb"; +var globalSalt = "49cb0d52-1aec-4b89-85fc-fab2c53062fb"; // Should not be global //setup CORS correctly app.use(function(req, res, next) { @@ -87,6 +84,10 @@ app.get('/api/getVideoSponsorTimes', function (req, res) { }); }); +function GetIP (req) { + return BehindProxy ? req.headers['x-forwarded-for'] || req.connection.remoteAddress; +} + //add the post function app.get('/api/postVideoSponsorTimes', function (req, res) { let videoID = req.query.videoID; @@ -104,11 +105,9 @@ app.get('/api/postVideoSponsorTimes', function (req, res) { //hash the userID userID = getHashedUserID(userID); - - //x-forwarded-for if this server is behind a proxy - let ip = BehindProxy ? req.headers['x-forwarded-for'] || req.connection.remoteAddress; + //hash the ip 5000 times so no one can get it from the database - let hashedIP = hash(ip + globalSalt); + let hashedIP = hash(GetIP() + globalSalt); startTime = parseFloat(startTime); endTime = parseFloat(endTime); @@ -186,7 +185,7 @@ app.get('/api/voteOnSponsorTime', function (req, res) { userID = getHashedUserID(userID + UUID); //x-forwarded-for if this server is behind a proxy - let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; + let ip = GetIP(); //hash the ip 5000 times so no one can get it from the database let hashedIP = hash(ip + globalSalt); @@ -292,8 +291,7 @@ app.get('/database.db', function (req, res) { function getHashedUserID(userID) { //hash the userID 5000 times so no one can get it from the database - let hashedUserID = hash(userID); - return hashedUserID; + return hash(userID); } //This function will find sponsor times that are contained inside of eachother, called similar sponsor times @@ -455,7 +453,7 @@ function getWeightedRandomChoice(choices, weights, amountOfChoices) { } //iterate and find amountOfChoices choices - let randomNumber = Math.random(); + let randomNumber = Math.random(); // Not cryptographically-secure //this array will keep adding to this variable each time one sqrt vote has been dealt with //this is the sum of all the sqrtVotes under this index let currentVoteNumber = 0; From d5d33f0e9b9eb04c1bb318772000ec61b48993b0 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Wed, 31 Jul 2019 23:32:25 -0400 Subject: [PATCH 5/5] Reformatted and fixed missing parameters. --- index.js | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/index.js b/index.js index 08eb1d7..a086606 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,5 @@ var express = require('express'); var http = require('http'); -var BehindProxy = true // Create a service (the app object is just a callback). var app = express(); @@ -13,14 +12,6 @@ var db = new sqlite3.Database('./databases/sponsorTimes.db'); //where the more sensitive data such as IP addresses are stored var privateDB = new sqlite3.Database('./databases/private.db'); -function hash (value, times=5000) { // Should be bcrypt!!! - for (let i = 0; i < times; i++) { - let hashCreator = crypto.createHash('sha256'); - value = hashCreator.update(value).digest('hex'); - } - return value; -} - // Create an HTTP service. http.createServer(app).listen(80); @@ -28,6 +19,9 @@ http.createServer(app).listen(80); // make it even harder for someone to decode the ip var globalSalt = "49cb0d52-1aec-4b89-85fc-fab2c53062fb"; // Should not be global +//if so, it will use the x-forwarded header instead of the ip address of the connection +var behindProxy = true; + //setup CORS correctly app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); @@ -84,8 +78,8 @@ app.get('/api/getVideoSponsorTimes', function (req, res) { }); }); -function GetIP (req) { - return BehindProxy ? req.headers['x-forwarded-for'] || req.connection.remoteAddress; +function getIP(req) { + return behindProxy ? req.headers['x-forwarded-for'] : req.connection.remoteAddress; } //add the post function @@ -104,10 +98,10 @@ app.get('/api/postVideoSponsorTimes', function (req, res) { } //hash the userID - userID = getHashedUserID(userID); + userID = getHash(userID); //hash the ip 5000 times so no one can get it from the database - let hashedIP = hash(GetIP() + globalSalt); + let hashedIP = getHash(getIP(req) + globalSalt); startTime = parseFloat(startTime); endTime = parseFloat(endTime); @@ -182,13 +176,13 @@ app.get('/api/voteOnSponsorTime', function (req, res) { } //hash the userID - userID = getHashedUserID(userID + UUID); + userID = getHash(userID + UUID); //x-forwarded-for if this server is behind a proxy - let ip = GetIP(); + let ip = getIP(req); //hash the ip 5000 times so no one can get it from the database - let hashedIP = hash(ip + globalSalt); + let hashedIP = getHash(ip + globalSalt); //check if vote has already happened privateDB.prepare("SELECT type FROM votes WHERE userID = ? AND UUID = ?").get(userID, UUID, function(err, row) { @@ -269,7 +263,7 @@ app.get('/api/getViewsForUser', function (req, res) { } //hash the userID - userID = getHashedUserID(userID); + userID = getHash(userID); //up the view count by one db.prepare("SELECT SUM(views) as viewCount FROM sponsorTimes WHERE userID = ?").get(userID, function(err, row) { @@ -289,11 +283,6 @@ app.get('/database.db', function (req, res) { res.sendFile("./databases/sponsorTimes.db", { root: __dirname }); }); -function getHashedUserID(userID) { - //hash the userID 5000 times so no one can get it from the database - return hash(userID); -} - //This function will find sponsor times that are contained inside of eachother, called similar sponsor times //Only one similar time will be returned, randomly generated based on the sqrt of votes. //This allows new less voted items to still sometimes appear to give them a chance at getting votes. @@ -453,7 +442,8 @@ function getWeightedRandomChoice(choices, weights, amountOfChoices) { } //iterate and find amountOfChoices choices - let randomNumber = Math.random(); // Not cryptographically-secure + let randomNumber = Math.random(); + //this array will keep adding to this variable each time one sqrt vote has been dealt with //this is the sum of all the sqrtVotes under this index let currentVoteNumber = 0; @@ -484,3 +474,12 @@ function getWeightedRandomChoice(choices, weights, amountOfChoices) { choicesDealtWith: choicesDealtWith }; } + +function getHash(value, times=5000) { + for (let i = 0; i < times; i++) { + let hashCreator = crypto.createHash('sha256'); + value = hashCreator.update(value).digest('hex'); + } + + return value; +} \ No newline at end of file