mirror of
https://github.com/zadam/trilium.git
synced 2025-03-03 18:49:27 +08:00
verifying password with hash on the backend to make sure we don't decrypt garbage and also to make sure that everything is encrypted with same password/key
This commit is contained in:
parent
53d327e435
commit
87c1a95ccc
4 changed files with 80 additions and 10 deletions
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
import getpass
|
import getpass
|
||||||
|
|
||||||
import bcrypt # pip install bcrypt
|
import scrypt # pip install scrypt
|
||||||
|
import binascii
|
||||||
|
|
||||||
password1 = getpass.getpass()
|
password1 = getpass.getpass()
|
||||||
|
|
||||||
|
@ -11,9 +12,17 @@ print('Repeat the same password:')
|
||||||
password2 = getpass.getpass()
|
password2 = getpass.getpass()
|
||||||
|
|
||||||
if password1 == password2:
|
if password1 == password2:
|
||||||
salt = bcrypt.gensalt()
|
# salt is constant
|
||||||
|
salt = "dc73b57736511340f132e4b5521d178afa6311c45e0c25e6a9339038507852a6"
|
||||||
|
|
||||||
print('Generated hash:')
|
hashed = scrypt.hash(password=password1,
|
||||||
print(bcrypt.hashpw(password1, salt))
|
salt=salt,
|
||||||
|
N=16384,
|
||||||
|
r=16,
|
||||||
|
p=1,
|
||||||
|
buflen=32)
|
||||||
|
|
||||||
|
print('Generated password hash:')
|
||||||
|
print(binascii.hexlify(hashed))
|
||||||
else:
|
else:
|
||||||
print('Entered passwords are not identical!')
|
print('Entered passwords are not identical!')
|
22
src/app.py
22
src/app.py
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import bcrypt
|
import binascii
|
||||||
|
import scrypt
|
||||||
import configparser
|
import configparser
|
||||||
from flask import Flask, request, send_from_directory
|
from flask import Flask, request, send_from_directory
|
||||||
from flask import render_template, redirect
|
from flask import render_template, redirect
|
||||||
|
@ -11,6 +12,7 @@ from notes_api import notes_api
|
||||||
from sql import connect
|
from sql import connect
|
||||||
from tree_api import tree_api
|
from tree_api import tree_api
|
||||||
from notes_move_api import notes_move_api
|
from notes_move_api import notes_move_api
|
||||||
|
from password_api import password_api
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read('config.ini')
|
config.read('config.ini')
|
||||||
|
@ -20,6 +22,7 @@ app.secret_key = config['Security']['flaskSecretKey']
|
||||||
app.register_blueprint(tree_api)
|
app.register_blueprint(tree_api)
|
||||||
app.register_blueprint(notes_api)
|
app.register_blueprint(notes_api)
|
||||||
app.register_blueprint(notes_move_api)
|
app.register_blueprint(notes_move_api)
|
||||||
|
app.register_blueprint(password_api)
|
||||||
|
|
||||||
class User(UserMixin):
|
class User(UserMixin):
|
||||||
pass
|
pass
|
||||||
|
@ -53,11 +56,26 @@ connect(documentPath)
|
||||||
|
|
||||||
hashedPassword = config['Login']['password-hash'].encode('utf-8')
|
hashedPassword = config['Login']['password-hash'].encode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def verify_password(hex_hashed_password, guessed_password):
|
||||||
|
hashed_password = binascii.unhexlify(hex_hashed_password)
|
||||||
|
|
||||||
|
salt = "dc73b57736511340f132e4b5521d178afa6311c45e0c25e6a9339038507852a6"
|
||||||
|
|
||||||
|
hashed = scrypt.hash(password=guessed_password,
|
||||||
|
salt=salt,
|
||||||
|
N=16384,
|
||||||
|
r=16,
|
||||||
|
p=1,
|
||||||
|
buflen=32)
|
||||||
|
|
||||||
|
return hashed == hashed_password
|
||||||
|
|
||||||
@app.route('/login', methods=['POST'])
|
@app.route('/login', methods=['POST'])
|
||||||
def login_post():
|
def login_post():
|
||||||
inputPassword = request.form['password'].encode('utf-8')
|
inputPassword = request.form['password'].encode('utf-8')
|
||||||
|
|
||||||
if request.form['username'] == user.id and bcrypt.hashpw(inputPassword, hashedPassword) == hashedPassword:
|
if request.form['username'] == user.id and verify_password(hashedPassword, inputPassword):
|
||||||
rememberMe = True if 'remember-me' in request.form else False
|
rememberMe = True if 'remember-me' in request.form else False
|
||||||
|
|
||||||
login_user(user, remember=rememberMe)
|
login_user(user, remember=rememberMe)
|
||||||
|
|
28
src/password_api.py
Normal file
28
src/password_api.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from flask import Blueprint, jsonify, request
|
||||||
|
from flask_login import login_required
|
||||||
|
import hashlib
|
||||||
|
import configparser
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
password_api = Blueprint('password_api', __name__)
|
||||||
|
|
||||||
|
@password_api.route('/password/verify', methods = ['POST'])
|
||||||
|
@login_required
|
||||||
|
def verifyPassword():
|
||||||
|
req = request.get_json(force=True)
|
||||||
|
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read('config.ini')
|
||||||
|
|
||||||
|
hashedPassword = config['Login']['password-hash'].encode('utf-8')
|
||||||
|
hashedPasswordBytes = binascii.unhexlify(hashedPassword)
|
||||||
|
hashedPasswordSha = hashlib.sha256(hashedPasswordBytes).hexdigest()
|
||||||
|
|
||||||
|
print(req['password'])
|
||||||
|
print(hashedPasswordSha)
|
||||||
|
|
||||||
|
isValid = req['password'] == hashedPasswordSha
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'valid': isValid
|
||||||
|
})
|
|
@ -204,9 +204,7 @@ function addRecentNote(noteTreeId, noteContentId) {
|
||||||
function deriveEncryptionKey(password) {
|
function deriveEncryptionKey(password) {
|
||||||
// why this is done is explained here: https://github.com/ricmoo/scrypt-js - "Encoding notes"
|
// why this is done is explained here: https://github.com/ricmoo/scrypt-js - "Encoding notes"
|
||||||
const normalizedPassword = password.normalize('NFKC');
|
const normalizedPassword = password.normalize('NFKC');
|
||||||
// use password as a base for salt (which is itself salted with constant) so that we don't need to store it
|
const salt = "dc73b57736511340f132e4b5521d178afa6311c45e0c25e6a9339038507852a6";
|
||||||
// this means everything is encrypted with the same salt.
|
|
||||||
const salt = sha256("Jg&)hZ$" + normalizedPassword + "*P7j.");
|
|
||||||
|
|
||||||
const passwordBuffer = new buffer.SlowBuffer(normalizedPassword);
|
const passwordBuffer = new buffer.SlowBuffer(normalizedPassword);
|
||||||
const saltBuffer = new buffer.SlowBuffer(salt);
|
const saltBuffer = new buffer.SlowBuffer(salt);
|
||||||
|
@ -228,7 +226,24 @@ function deriveEncryptionKey(password) {
|
||||||
else if (key) {
|
else if (key) {
|
||||||
console.log("Computation took " + (new Date().getTime() - startedDate.getTime()) + "ms");
|
console.log("Computation took " + (new Date().getTime() - startedDate.getTime()) + "ms");
|
||||||
|
|
||||||
resolve(key);
|
$.ajax({
|
||||||
|
url: baseUrl + 'password/verify',
|
||||||
|
type: 'POST',
|
||||||
|
data: JSON.stringify({
|
||||||
|
password: sha256(key)
|
||||||
|
}),
|
||||||
|
contentType: "application/json",
|
||||||
|
success: function (result) {
|
||||||
|
if (result.valid) {
|
||||||
|
resolve(key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
alert("Wrong password");
|
||||||
|
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// update UI with progress complete
|
// update UI with progress complete
|
||||||
|
|
Loading…
Reference in a new issue