add key pairs for encryption, as well as better styling for posts page

This commit is contained in:
Mystikfluu 2022-06-15 00:16:16 +02:00
parent 286fe9d74b
commit 3fe83455a3
10 changed files with 241 additions and 122 deletions

View File

@ -12,10 +12,12 @@ CREATE TABLE `users` (
`User_LastIP` varchar(45) NOT NULL DEFAULT 'None',
`User_Bio` varchar(100) DEFAULT 'wow such empty',
`User_Avatar` varchar(100) DEFAULT NULL,
`User_PublicKey` varchar(830) DEFAULT NULL,
PRIMARY KEY (`User_ID`,`User_Name`),
UNIQUE KEY `User_Name_UNIQUE` (`User_Name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `posts` (
`post_id` bigint NOT NULL AUTO_INCREMENT,
`post_user_name` varchar(100) NOT NULL,

View File

@ -3,7 +3,7 @@ ul {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
background-color: #303034;
}
li {

View File

@ -1,101 +1,101 @@
* {
padding: 0px;
margin: 0px;
padding: 0px;
margin: 0px;
}
body {
background-color: lightgreen;
background-color: lightgreen;
}
header {
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 15vh;
box-shadow: 5px 5px 10px rgb(0,0,0,0.3);
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 15vh;
box-shadow: 5px 5px 10px rgb(0,0,0,0.3);
}
h1 {
letter-spacing: 1.5vw;
font-family: 'system-ui';
text-transform: uppercase;
text-align: center;
letter-spacing: 1.5vw;
font-family: 'system-ui';
text-transform: uppercase;
text-align: center;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 75vh;
width: 100%;
background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Mountains-1412683.svg/1280px-Mountains-1412683.svg.png) no-repeat center center;
background-size: cover;
display: flex;
align-items: center;
justify-content: center;
height: 75vh;
width: 100%;
background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Mountains-1412683.svg/1280px-Mountains-1412683.svg.png) no-repeat center center;
background-size: cover;
}
.form_class {
width: 500px;
padding: 40px;
border-radius: 8px;
background-color: white;
font-family: 'system-ui';
box-shadow: 5px 5px 10px rgb(0,0,0,0.3);
width: 500px;
padding: 40px;
border-radius: 8px;
background-color: white;
font-family: 'system-ui';
box-shadow: 5px 5px 10px rgb(0,0,0,0.3);
}
.form_div {
text-transform: uppercase;
text-transform: uppercase;
}
.form_div > label {
letter-spacing: 3px;
font-size: 1rem;
letter-spacing: 3px;
font-size: 1rem;
}
.info_div {
text-align: center;
margin-top: 20px;
text-align: center;
margin-top: 20px;
}
.info_div {
letter-spacing: 1px;
letter-spacing: 1px;
}
.field_class {
width: 100%;
border-radius: 6px;
border-style: solid;
border-width: 1px;
padding: 5px 0px;
text-indent: 6px;
margin-top: 10px;
margin-bottom: 20px;
font-family: 'system-ui';
font-size: 0.9rem;
letter-spacing: 2px;
width: 100%;
border-radius: 6px;
border-style: solid;
border-width: 1px;
padding: 5px 0px;
text-indent: 6px;
margin-top: 10px;
margin-bottom: 20px;
font-family: 'system-ui';
font-size: 0.9rem;
letter-spacing: 2px;
}
.submit_class {
border-style: none;
border-radius: 5px;
background-color: #FFE6D4;
padding: 8px 20px;
font-family: 'system-ui';
text-transform: uppercase;
letter-spacing: .8px;
display: block;
margin: auto;
margin-top: 10px;
box-shadow: 2px 2px 5px rgb(0,0,0,0.2);
cursor: pointer;
border-style: none;
border-radius: 5px;
background-color: #FFE6D4;
padding: 8px 20px;
font-family: 'system-ui';
text-transform: uppercase;
letter-spacing: .8px;
display: block;
margin: auto;
margin-top: 10px;
box-shadow: 2px 2px 5px rgb(0,0,0,0.2);
cursor: pointer;
}
footer {
height: 10vh;
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
box-shadow: -5px -5px 10px rgb(0,0,0,0.3);
height: 10vh;
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
box-shadow: -5px -5px 10px rgb(0,0,0,0.3);
}
footer > p {
text-align: center;
font-family: 'system-ui';
letter-spacing: 3px;
text-align: center;
font-family: 'system-ui';
letter-spacing: 3px;
}
footer > p > a {
text-decoration: none;
color: white;
font-weight: bold;
text-decoration: none;
color: white;
font-weight: bold;
}
a {
color: red;

View File

@ -1,47 +1,47 @@
* {
padding: 0px;
margin: 0px;
padding: 0px;
margin: 0px;
}
body {
background-color: lightgreen;
background-color: lightgreen;
}
header {
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 15vh;
box-shadow: 5px 5px 10px rgb(0,0,0,0.3);
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 15vh;
box-shadow: 5px 5px 10px rgb(0,0,0,0.3);
}
h1 {
letter-spacing: 1.5vw;
font-family: 'system-ui';
text-transform: uppercase;
text-align: center;
letter-spacing: 1.5vw;
font-family: 'system-ui';
text-transform: uppercase;
text-align: center;
}
main {
display: flex;
align-items: center;
justify-content: center;
height: 75vh;
width: 100%;
background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Mountains-1412683.svg/1280px-Mountains-1412683.svg.png) no-repeat center center;
background-size: cover;
display: flex;
align-items: center;
justify-content: center;
height: 75vh;
width: 100%;
background: url(https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Mountains-1412683.svg/1280px-Mountains-1412683.svg.png) no-repeat center center;
background-size: cover;
}
.info_div {
text-align: center;
margin-top: 20px;
text-align: center;
margin-top: 20px;
}
.info_div {
letter-spacing: 1px;
letter-spacing: 1px;
}
footer {
height: 10vh;
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
box-shadow: -5px -5px 10px rgb(0,0,0,0.3);
height: 10vh;
background-color: black;
color: white;
display: flex;
align-items: center;
justify-content: center;
box-shadow: -5px -5px 10px rgb(0,0,0,0.3);
}

View File

@ -7,7 +7,7 @@
}
.self {
color: gray;
color: white;
}
#username-self {
@ -27,7 +27,7 @@
}
#posts > div {
background-color: darkgray;
background-color: #303034;
padding-left: 5px;
padding-bottom: 2px;
}
@ -51,15 +51,15 @@
}
body {
background-color: black;
background-color: #1B1B1E;
}
textarea {
background-color: gray;
background-color: #1B1B1E;
}
button {
background-color: gray;
background-color: #587291;
}
* {
@ -67,6 +67,7 @@ button {
}
.post,.self,.status {
color: #ECEAF1;
width: 50%;
margin-left: 25%;
margin-right: 25%;

38
js/RSA.js Normal file
View File

@ -0,0 +1,38 @@
var RSAAPP={};RSAAPP.NoPadding="NoPadding";RSAAPP.PKCS1Padding="PKCS1Padding";RSAAPP.RawEncoding="RawEncoding";RSAAPP.NumericEncoding="NumericEncoding"
function RSAKeyPair(encryptionExponent,decryptionExponent,modulus,keylen)
{this.e=biFromHex(encryptionExponent);this.d=biFromHex(decryptionExponent);this.m=biFromHex(modulus);if(typeof(keylen)!='number'){this.chunkSize=2*biHighIndex(this.m);}
else{this.chunkSize=keylen/8;}
this.radix=16;this.barrett=new BarrettMu(this.m);}
function encryptedString(key,s,pad,encoding)
{var a=new Array();var sl=s.length;var i,j,k;var padtype;var encodingtype;var rpad;var al;var result="";var block;var crypt;var text;if(typeof(pad)=='string'){if(pad==RSAAPP.NoPadding){padtype=1;}
else if(pad==RSAAPP.PKCS1Padding){padtype=2;}
else{padtype=0;}}
else{padtype=0;}
if(typeof(encoding)=='string'&&encoding==RSAAPP.RawEncoding){encodingtype=1;}
else{encodingtype=0;}
if(padtype==1){if(sl>key.chunkSize){sl=key.chunkSize;}}
else if(padtype==2){if(sl>(key.chunkSize-11)){sl=key.chunkSize-11;}}
i=0;if(padtype==2){j=sl-1;}
else{j=key.chunkSize-1;}
while(i<sl){if(padtype){a[j]=s.charCodeAt(i);}
else{a[i]=s.charCodeAt(i);}
i++;j--;}
if(padtype==1){i=0;}
j=key.chunkSize-(sl%key.chunkSize);while(j>0){if(padtype==2){rpad=Math.floor(Math.random()*256);while(!rpad){rpad=Math.floor(Math.random()*256);}
a[i]=rpad;}
else{a[i]=0;}
i++;j--;}
if(padtype==2)
{a[sl]=0;a[key.chunkSize-2]=2;a[key.chunkSize-1]=0;}
al=a.length;for(i=0;i<al;i+=key.chunkSize){block=new BigInt();j=0;for(k=i;k<(i+key.chunkSize);++j){block.digits[j]=a[k++];block.digits[j]+=a[k++]<<8;}
crypt=key.barrett.powMod(block,key.e);if(encodingtype==1){text=biToBytes(crypt);}
else{text=(key.radix==16)?biToHex(crypt):biToString(crypt,key.radix);}
result+=text;}
return result;}
function decryptedString(key,c)
{var blocks=c.split(" ");var b;var i,j;var bi;var result="";for(i=0;i<blocks.length;++i){if(key.radix==16){bi=biFromHex(blocks[i]);}
else{bi=biFromString(blocks[i],key.radix);}
b=key.barrett.powMod(bi,key.d);for(j=0;j<=biHighIndex(b);++j){result+=String.fromCharCode(b.digits[j]&255,b.digits[j]>>8);}}
if(result.charCodeAt(result.length-1)==0){result=result.substring(0,result.length-1);}
return(result);}

View File

@ -31,7 +31,34 @@ function progressHandler(event) {
console.log(event.target.responseText);
}
function getCookie(cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for(let i = 0; i <ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
function setCookie(cname, cvalue, exdays) {
const d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
let expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
async function setuser() {
if(getCookie("priv_key") != "") {
localStorage.setItem("priv_key",getCookie("priv_key"))
setCookie("priv_key","",0)
}
let user = await (await fetch("/api/getuser")).json();
let username
let bio

View File

@ -339,12 +339,16 @@ router.use("/api/*",async function(req,res,next) {
values[1] = SHA256(values[1],values[0],HASHES_DIFF)
res.locals.bio = ""
res.locals.avatar = ""
res.locals.publicKey = ""
res.locals.privateKey = ""
con.query(sql, values, function (err, result) {
if (err) throw err;
if(result[0] && result[0].User_Name && result[0].User_Name == values[0]) {
res.locals.username = values[0];
res.locals.bio = result[0].User_Bio || ""
res.locals.avatar = result[0].User_Avatar || ""
res.locals.publicKey = result[0].User_PublicKey || ""
res.locals.privateKey = result[0].User_PrivateKey || ""
next()
} else {
res.status(400)
@ -367,7 +371,7 @@ router.get("/api/search", async function(req,res) {
}
});
}else if (type=="post") {
let sql = `select post_user_name,post_text,post_time,post_special_text,post_id from zerotwohub.posts where post_text like ? order by post_id desc limit 20;`
let sql = `select post_user_name,post_text,post_time,post_special_text,post_id from zerotwohub.posts where post_text like ? and (post_receiver_name is null or post_receiver_name = 'everyone') order by post_id desc limit 20;`
con.query(sql, [`%${arg}%`], function (err, result) {
if (err) throw err;
if(result[0]) {
@ -468,13 +472,16 @@ router.post("/api/post", async function(req,res) {
return
}
req.body.message = encodeURIComponent(req.body.message.trim())
req.body.receiver = encodeURIComponent(req.body.receiver||"")
if(req.body.receiver == "")req.body.receiver="everyone"
if(!req.body.message) {
res.json({"error":"no message to post"})
return
}
let sql = `insert into zerotwohub.posts (post_user_name,post_text,post_time) values (?,?,?);`
let values = [encodeURIComponent(res.locals.username),req.body.message,Date.now()]
let sql = `insert into zerotwohub.posts (post_user_name,post_text,post_time,post_receiver_name) values (?,?,?,?);`
let values = [encodeURIComponent(res.locals.username),req.body.message,Date.now(),req.body.receiver]
con.query(sql, values, function (err, result) {
if (err) throw err;
@ -724,16 +731,34 @@ router.post("/register",async function(req,res) {
res.redirect("/register?success=false&reason=already_exists")
return
}
let hashed_pw = SHA256(password,username,HASHES_DB)
let less_hashed_pw = SHA256(password,username,HASHES_DIFF)
let hashed_pw = SHA256(less_hashed_pw,username,HASHES_COOKIE)
let ip = req.socket.remoteAddress
let setTo = username + " " + SHA256(password,username,HASHES_COOKIE)
let cookiesigned = signature.sign(setTo, cookiesecret+ip);
ip = SHA256(ip,setTo,HASHES_DB)
let values = [encodeURIComponent(username),hashed_pw, Date.now(), ip, ip]
let sql = `INSERT INTO zerotwohub.users (User_Name, User_PW, User_CreationStamp, User_CreationIP, User_LastIP) VALUES (?, ?, ?, ? ,?);`
const {
publicKey,
privateKey,
} = crypto.generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: password
}
});
let values = [encodeURIComponent(username),hashed_pw, Date.now(), ip, ip, publicKey.toString(), privateKey.toString()]
let sql = `INSERT INTO zerotwohub.users (User_Name, User_PW, User_CreationStamp, User_CreationIP, User_LastIP, User_PublicKey, User_PrivateKey) VALUES (?, ?, ?, ?, ?, ?, ?);`
con.query(sql, values, function (err, result) {
if (err) throw err;
res.cookie('AUTH_COOKIE',cookiesigned, { maxAge: Math.pow(10,10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS });
res.cookie("priv_key",privateKey.toString(), { maxAge: Math.pow(10,10), httpOnly: false, secure: DID_I_FINALLY_ADD_HTTPS }) //only meant to be used as temporary storage, moved to localStorage on user page
res.redirect("/user?success=true")
});
})
@ -784,26 +809,50 @@ router.post("/login",async function(req,res) {
res.send("no password given")
return
}
let less_hashed_pw = SHA256(password,username,HASHES_DIFF)
let hashed_pw = SHA256(less_hashed_pw,username,HASHES_COOKIE)
let hashed_pw = SHA256(password,username,HASHES_DB)
let userexistssql = `SELECT User_Name,User_PW,User_LastIP from zerotwohub.users where User_Name = ? and User_PW = ?;`
let userexistssql = `SELECT * from zerotwohub.users where User_Name = ? and User_PW = ?;`
con.query(userexistssql,[encodeURIComponent(username),hashed_pw],function(error,result) {
if(result && result[0]) {
let ip = req.socket.remoteAddress
let setTo = username + " " + SHA256(password,username,HASHES_COOKIE)
let cookiesigned = signature.sign(setTo, cookiesecret+ip);
res.cookie('AUTH_COOKIE',cookiesigned, { maxAge: Math.pow(10,10), httpOnly: true, secure: DID_I_FINALLY_ADD_HTTPS });
res.redirect("/user?success=true")
ip = SHA256(ip,setTo,HASHES_DB)
if(result[0].User_PublicKey == null) {
const {
publicKey,
privateKey,
} = crypto.generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: password
}
});
res.cookie("priv_key",privateKey.toString(), { maxAge: Math.pow(10,10), httpOnly: false, secure: DID_I_FINALLY_ADD_HTTPS }) //only meant to be used as temporary storage, moved to localStorage on user page
let sql = `update zerotwohub.users set User_PublicKey=?,User_PrivateKey=? where User_Name = ?;`
con.query(sql,[publicKey.toString(),privateKey.toString(),encodeURIComponent(username)],function(error,result) {
if(error)throw error
})
} else {
res.cookie("priv_key",result[0].User_PrivateKey, { maxAge: Math.pow(10,10), httpOnly: false, secure: DID_I_FINALLY_ADD_HTTPS }) //only meant to be used as temporary storage, moved to localStorage on user page
}
if(result[0].User_LastIP != ip) {
let sql = `update zerotwohub.users set User_LastIP = ? where User_Name = ?;`
con.query(sql,[ip,encodeURIComponent(username)],function(error,result) {
if(error)throw error
})
}
res.redirect("/user?success=true")
} else {
res.redirect("/login?success=false?reason=noUser")
}

View File

@ -4,8 +4,9 @@
<link rel="stylesheet" href="/css/logon.css">
<script type="text/javascript">
function login() {
const user = document.getElementById("user").value
const pw = document.getElementById("pass").value
localStorage.setItem("decryption_key",pw)
//yes I know this is not secure, but at this point I think it'd be better to trust the client for end-to-end encryption
}
</script>
<script src="/js/addnavbar.js" charset="utf-8"></script>

View File

@ -4,8 +4,9 @@
<link rel="stylesheet" href="/css/logon.css">
<script type="text/javascript">
function register() {
const user = document.getElementById("user").value
const pw = document.getElementById("pass").value
localStorage.setItem("decryption_key",pw)
//yes I know this is not secure, but at this point I think it'd be better to trust the client for end-to-end encryption
}
</script>
<script src="/js/addnavbar.js" charset="utf-8"></script>