diff --git a/change-password.py b/change-password.py new file mode 100644 index 000000000..23b77dbed --- /dev/null +++ b/change-password.py @@ -0,0 +1,74 @@ +#!/usr/bin/python + +import src.config_provider +import src.sql +import base64 +import getpass +from Crypto.Cipher import AES +from Crypto.Util import Counter +import binascii + +import src.my_scrypt + +currentPassword = getpass.getpass(prompt="Enter current password: ") + +currentPasswordHash = binascii.hexlify(src.my_scrypt.getVerificationHash(currentPassword)) + +config = src.config_provider.getConfig() + +if currentPasswordHash != config['Login']['passwordHash']: + print("Given password doesn't match hash") + exit(-1) + +currentPasswordEncryptionKey = src.my_scrypt.getEncryptionHash(currentPassword) + +newPassword1 = getpass.getpass(prompt="Enter new password: ") +newPassword2 = getpass.getpass(prompt="Repeat the same password: ") + +if newPassword1 != newPassword2: + print('Entered passwords are not identical!') + exit(-1) + +newPasswordVerificationKey = binascii.hexlify(src.my_scrypt.getVerificationHash(newPassword1)) +newPasswordEncryptionKey = src.my_scrypt.getEncryptionHash(newPassword1) + +src.sql.connect(config['Document']['documentPath']) + +encryptedNotes = src.sql.getResults("select note_id, note_title, note_text from notes where encryption = 1") + +def decrypt(encryptedBase64): + encryptedBytes = base64.b64decode(encryptedBase64) + + aes = getAes(currentPasswordEncryptionKey) + return aes.decrypt(encryptedBytes) + +def encrypt(plainText): + aes = getAes(newPasswordEncryptionKey) + encryptedBytes = aes.encrypt(plainText) + + return base64.b64encode(encryptedBytes) + +def getAes(key): + return AES.new(key, AES.MODE_CTR, counter=Counter.new(128, initial_value=5)) + +for note in encryptedNotes: + decryptedTitle = decrypt(note['note_title']) + decryptedText = decrypt(note['note_text']) + + reEncryptedTitle = encrypt(decryptedTitle) + reEncryptedText = encrypt(decryptedText) + + print (reEncryptedTitle) + print (reEncryptedText) + + src.sql.execute("update notes set note_title = ?, note_text = ? where note_id = ?", + [reEncryptedTitle, reEncryptedText, note['note_id']]) + + print("Note " + note['note_id'] + " reencrypted with new password") + +print("New password hash is: " + newPasswordVerificationKey) +print("Set this value to passwordHash value in config.ini") + +src.sql.commit() + +print("Changes committed. All encrypted notes were re-encrypted successfully with new password key.") \ No newline at end of file diff --git a/config-sample.ini b/config-sample.ini index c748cb6d6..9b07d5da7 100644 --- a/config-sample.ini +++ b/config-sample.ini @@ -17,7 +17,7 @@ certKeyPath=cert.key # Enter below credentials with with which you want to authenticate to Notecase web app username=your_username # This is bcrypt password hash. You can use generate-password.py (in this directory) to hash your password -password-hash=$2b$12$FHT8keXp3BGTfzAV/VnrkuLpkwN8Vpj5iIh4RwCbHTNWYSBI9hGAK +passwordHash=$2b$12$FHT8keXp3BGTfzAV/VnrkuLpkwN8Vpj5iIh4RwCbHTNWYSBI9hGAK [Sync] sync-server-url=https://localhost:57201 diff --git a/generate-password.py b/generate-password.py index 7aaab2297..31ed2568c 100644 --- a/generate-password.py +++ b/generate-password.py @@ -1,28 +1,15 @@ #!/usr/bin/python import getpass - -import scrypt # pip install scrypt -import binascii +import src.my_scrypt password1 = getpass.getpass() - -print('Repeat the same password:') - -password2 = getpass.getpass() +password2 = getpass.getpass(prompt='Repeat the same password:') if password1 == password2: - # salt is constant - salt = "dc73b57736511340f132e4b5521d178afa6311c45e0c25e6a9339038507852a6" - - hashed = scrypt.hash(password=password1, - salt=salt, - N=16384, - r=8, - p=1, - buflen=32) + hash = src.my_scrypt.getVerificationHash(password1) print('Generated password hash:') - print(binascii.hexlify(hashed)) + print(hash) else: print('Entered passwords are not identical!') \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/app.py b/src/app.py index 831d4db50..f324e1040 100644 --- a/src/app.py +++ b/src/app.py @@ -2,7 +2,6 @@ import os import binascii import scrypt -import configparser from flask import Flask, request, send_from_directory from flask import render_template, redirect from flask_cors import CORS @@ -13,9 +12,9 @@ from sql import connect from tree_api import tree_api from notes_move_api import notes_move_api from password_api import password_api +import config_provider -config = configparser.ConfigParser() -config.read('config.ini') +config = config_provider.getConfig() app = Flask(__name__) app.secret_key = config['Security']['flaskSecretKey'] @@ -54,7 +53,7 @@ documentPath = config['Document']['documentPath'] connect(documentPath) -hashedPassword = config['Login']['password-hash'].encode('utf-8') +hashedPassword = config['Login']['passwordHash'].encode('utf-8') def verify_password(hex_hashed_password, guessed_password): diff --git a/src/config_provider.py b/src/config_provider.py new file mode 100644 index 000000000..ebf36f81a --- /dev/null +++ b/src/config_provider.py @@ -0,0 +1,7 @@ +import configparser + +def getConfig(): + config = configparser.ConfigParser() + config.read('config.ini') + + return config \ No newline at end of file diff --git a/src/my_scrypt.py b/src/my_scrypt.py new file mode 100644 index 000000000..f17780cba --- /dev/null +++ b/src/my_scrypt.py @@ -0,0 +1,21 @@ +import scrypt # pip install scrypt + +def getVerificationHash(password): + salt = "dc73b57736511340f132e4b5521d178afa6311c45e0c25e6a9339038507852a6" + + return getScryptHash(password, salt) + +def getEncryptionHash(password): + salt = "2503bfc386bc028772f803887eaaf4d4a5c1019036873e4ba5de79a4efb7e8d8" + + return getScryptHash(password, salt) + +def getScryptHash(password, salt): + hashed = scrypt.hash(password=password, + salt=salt, + N=16384, + r=8, + p=1, + buflen=32) + + return hashed \ No newline at end of file diff --git a/src/password_api.py b/src/password_api.py index f3f464d17..ce93fcaa9 100644 --- a/src/password_api.py +++ b/src/password_api.py @@ -1,8 +1,8 @@ from flask import Blueprint, jsonify, request from flask_login import login_required import hashlib -import configparser import binascii +import config_provider password_api = Blueprint('password_api', __name__) @@ -11,16 +11,12 @@ password_api = Blueprint('password_api', __name__) def verifyPassword(): req = request.get_json(force=True) - config = configparser.ConfigParser() - config.read('config.ini') + config = config_provider.getConfig() - hashedPassword = config['Login']['password-hash'].encode('utf-8') + hashedPassword = config['Login']['passwordHash'].encode('utf-8') hashedPasswordBytes = binascii.unhexlify(hashedPassword) hashedPasswordSha = hashlib.sha256(hashedPasswordBytes).hexdigest() - print(req['password']) - print(hashedPasswordSha) - isValid = req['password'] == hashedPasswordSha return jsonify({ diff --git a/src/sql.py b/src/sql.py index 14e85a019..c007e302a 100644 --- a/src/sql.py +++ b/src/sql.py @@ -1,6 +1,8 @@ import base64 import sqlite3 +conn = None + def dict_factory(cursor, row): d = {} for idx, col in enumerate(cursor.description):