def db_admin_update_user(session, tid, user_id, request, language): """ Updates the specified user. """ fill_localized_keys(request, models.User.localized_keys, language) user = db_get_user(session, tid, user_id) if user.username != request['username']: check = session.query(models.User).filter( models.User.username == text_type(request['username']), models.User.tid == tid).one_or_none() if check is not None: raise errors.InputValidationError('Username already in use') user.update(request) password = request['password'] if password: user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() user.password = GCE.hash_password(password, user.salt) user.password_change_date = datetime_now() user.crypto_prv_key = b'' user.crypto_pub_key = b'' # The various options related in manage PGP keys are used here. parse_pgp_options(user, request) if user.role == 'admin': db_refresh_memory_variables(session, [tid]) return user
def db_create_user(session, tid, request, language): """ Transaction for creating a new user :param session: An ORM session :param tid: A tenant ID :param request: The request data :param language: The language of the request :return: The serialized descriptor of the created object """ request['tid'] = tid fill_localized_keys(request, models.User.localized_keys, language) if not request['public_name']: request['public_name'] = request['name'] user = models.User(request) if not request['username']: user.username = user.id user.salt = GCE.generate_salt() # The various options related in manage PGP keys are used here. parse_pgp_options(user, request) session.add(user) session.flush() if request.get('send_account_activation_link', False): db_generate_password_reset_token(session, user) return user
def set_user_password(tid, user, password, cc): # Regenerate the password hash only if different from the best choice on the platform if user.hash_alg != 'ARGON2': user.hash_alg = 'ARGON2' user.salt = GCE.generate_salt() password_hash = GCE.hash_password(password, user.salt) # Check that the new password is different form the current password if user.password == password_hash: raise errors.PasswordReuseError user.password = password_hash user.password_change_date = datetime_now() if not State.tenant_cache[tid].encryption and cc == '': return None enc_key = GCE.derive_key(password.encode(), user.salt) if not cc: # The first password change triggers the generation # of the user encryption private key and its backup cc, user.crypto_pub_key = GCE.generate_keypair() user.crypto_bkp_key, user.crypto_rec_key = GCE.generate_recovery_key(cc) user.crypto_prv_key = Base64Encoder.encode(GCE.symmetric_encrypt(enc_key, cc)) if State.tenant_cache[1].crypto_escrow_pub_key: user.crypto_escrow_bkp1_key = Base64Encoder.encode(GCE.asymmetric_encrypt(State.tenant_cache[1].crypto_escrow_pub_key, cc)) if State.tenant_cache[tid].crypto_escrow_pub_key: user.crypto_escrow_bkp2_key = Base64Encoder.encode(GCE.asymmetric_encrypt(State.tenant_cache[tid].crypto_escrow_pub_key, cc)) return cc
def db_admin_update_user(session, tid, user_id, request, language): """ Updates the specified user. """ fill_localized_keys(request, models.User.localized_keys, language) user = db_get_user(session, tid, user_id) if user.username != request['username']: check = session.query(models.User).filter(models.User.username == text_type(request['username']), models.UserTenant.user_id == models.User.id, models.UserTenant.tenant_id == tid).one_or_none() if check is not None: raise errors.InputValidationError('Username already in use') user.update(request) password = request['password'] if password: user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() user.password = GCE.hash_password(password, user.salt) user.password_change_date = datetime_now() user.crypto_prv_key = b'' user.crypto_pub_key = b'' # The various options related in manage PGP keys are used here. parse_pgp_options(user, request) if user.role == 'admin': db_refresh_memory_variables(session, [tid]) return user
def db_admin_update_user(session, tid, user_session, user_id, request, language): """ Transaction for updating an existing user :param session: An ORM session :param tid: A tenant ID :param user_session: The current user session :param user_id: The ID of the user to update :param request: The request data :param language: The language of the request :return: The serialized descriptor of the updated object """ fill_localized_keys(request, models.User.localized_keys, language) user = db_get_user(session, tid, user_id) if user.username != request['username']: check = session.query(models.User).filter( models.User.username == request['username'], models.User.tid == tid).one_or_none() if check is not None: raise errors.InputValidationError('Username already in use') user.update(request) password = request['password'] if password and (not user.crypto_pub_key or user_session.ek): if user.crypto_pub_key and user_session.ek: enc_key = GCE.derive_key(password.encode(), user.salt) crypto_escrow_prv_key = GCE.asymmetric_decrypt( user_session.cc, Base64Encoder.decode(user_session.ek)) if tid == 1: user_cc = GCE.asymmetric_decrypt( crypto_escrow_prv_key, Base64Encoder.decode(user.crypto_escrow_bkp1_key)) else: user_cc = GCE.asymmetric_decrypt( crypto_escrow_prv_key, Base64Encoder.decode(user.crypto_escrow_bkp2_key)) user.crypto_prv_key = Base64Encoder.encode( GCE.symmetric_encrypt(enc_key, user_cc)) if user.hash_alg != 'ARGON2': user.hash_alg = 'ARGON2' user.salt = GCE.generate_salt() user.password = GCE.hash_password(password, user.salt) user.password_change_date = datetime_now() user.password_change_needed = True # The various options related in manage PGP keys are used here. parse_pgp_options(user, request) return user_serialize_user(session, user, language)
def db_create_user(session, tid, request, language): request['tid'] = tid fill_localized_keys(request, models.User.localized_keys, language) if request['username']: user = session.query(models.User).filter( models.User.username == text_type(request['username']), models.UserTenant.user_id == models.User.id, models.UserTenant.tenant_id == tid).one_or_none() if user is not None: raise errors.InputValidationError('Username already in use') user = models.User({ 'tid': tid, 'username': request['username'], 'role': request['role'], 'state': u'enabled', 'name': request['name'], 'description': request['description'], 'language': language, 'password_change_needed': request['password_change_needed'], 'mail_address': request['mail_address'], 'can_edit_general_settings': request['can_edit_general_settings'] }) if not request['username']: user.username = user.id = uuid4() password = u'password' if request['password']: password = request['password'] user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() user.password = GCE.hash_password(password, user.salt) # The various options related in manage PGP keys are used here. parse_pgp_options(user, request) session.add(user) session.flush() db_create_usertenant_association(session, user.id, tid) return user
def db_create_user(session, tid, request, language): request['tid'] = tid fill_localized_keys(request, models.User.localized_keys, language) if request['username']: user = session.query(models.User).filter(models.User.username == text_type(request['username']), models.UserTenant.user_id == models.User.id, models.UserTenant.tenant_id == tid).one_or_none() if user is not None: raise errors.InputValidationError('Username already in use') user = models.User({ 'tid': tid, 'username': request['username'], 'role': request['role'], 'state': u'enabled', 'name': request['name'], 'description': request['description'], 'language': language, 'password_change_needed': request['password_change_needed'], 'mail_address': request['mail_address'], 'can_edit_general_settings': request['can_edit_general_settings'] }) if not request['username']: user.username = user.id = uuid4() password = u'password' if request['password']: password = request['password'] user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() user.password = GCE.hash_password(password, user.salt) # The various options related in manage PGP keys are used here. parse_pgp_options(user, request) session.add(user) session.flush() db_create_usertenant_association(session, user.id, tid) return user
def db_admin_update_user(session, tid, user_session, user_id, request, language): """ Transaction for updating an existing user :param session: An ORM session :param tid: A tenant ID :param user_session: The current user session :param user_id: The ID of the user to update :param request: The request data :param language: The language of the request :return: The serialized descriptor of the updated object """ fill_localized_keys(request, models.User.localized_keys, language) user = db_get_user(session, tid, user_id) user.update(request) password = request['password'] if password and (not user.crypto_pub_key or user_session.ek): if user.crypto_pub_key and user_session.ek: enc_key = GCE.derive_key(password.encode(), user.salt) crypto_escrow_prv_key = GCE.asymmetric_decrypt(user_session.cc, Base64Encoder.decode(user_session.ek)) if user_session.user_tid == 1: user_cc = GCE.asymmetric_decrypt(crypto_escrow_prv_key, Base64Encoder.decode(user.crypto_escrow_bkp1_key)) else: user_cc = GCE.asymmetric_decrypt(crypto_escrow_prv_key, Base64Encoder.decode(user.crypto_escrow_bkp2_key)) user.crypto_prv_key = Base64Encoder.encode(GCE.symmetric_encrypt(enc_key, user_cc)) if user.hash_alg != 'ARGON2': user.hash_alg = 'ARGON2' user.salt = GCE.generate_salt() user.password = GCE.hash_password(password, user.salt) user.password_change_date = datetime_now() State.log(tid=tid, type='change_password', user_id=user_session.user_id, object_id=user_id) # The various options related in manage PGP keys are used here. parse_pgp_options(user, request) return user_serialize_user(session, user, language)
# -*- coding: utf-8 -*- from globaleaks import __version__, DATABASE_VERSION from globaleaks.models.config_desc import Unicode, Int, Bool from globaleaks.utils.crypto import GCE from globaleaks.utils.utility import datetime_null, iso_strf_time GLConfig_v_35 = { 'private': { 'receipt_salt': Unicode(default=GCE.generate_salt()), 'smtp_password': Unicode(default='yes_you_really_should_change_me'), 'version': Unicode(default=Unicode(__version__)), 'version_db': Int(default=DATABASE_VERSION), 'https_priv_key': Unicode(), 'https_priv_gen': Bool(default=False), 'https_csr': Unicode(), 'https_cert': Unicode(), 'https_chain': Unicode(), 'https_dh_params': Unicode(), 'https_enabled': Bool(default=False), }, 'notification': { 'server': Unicode(default='demo.globaleaks.org'), 'port': Int(default=9267), 'username': Unicode(default='hey_you_should_change_me'), # See smtp_password in private for password 'source_email': Unicode(default='*****@*****.**'),
# -*- coding: utf-8 import filecmp import os from globaleaks.settings import Settings from globaleaks.tests import helpers from globaleaks.utils.crypto import GCE password = b'password' message = b'message' salt = GCE.generate_salt() class TestCryptoUtils(helpers.TestGL): def test_set_params(self): GCE.set_params(123, 321) self.assertEqual(GCE.ALGORITM_CONFIGURATION['ARGON2']['MEMLIMIT'], 123) self.assertEqual(GCE.ALGORITM_CONFIGURATION['ARGON2']['OPSLIMIT'], 321) GCE.set_params(27, 1) def test_auto_tune(self): GCE.auto_tune() self.assertTrue(GCE.ALGORITM_CONFIGURATION['ARGON2']['MEMLIMIT'] > 27) GCE.set_params(27, 1) def test_generate_key(self): GCE.generate_key()
# -*- encoding: utf-8 -*- from globaleaks import __version__, DATABASE_VERSION from globaleaks.models.config_desc import Unicode, Int, Bool from globaleaks.utils.crypto import GCE from globaleaks.utils.utility import datetime_null, iso_strf_time GLConfig_v_37 = { 'private': { 'receipt_salt': Unicode(default=GCE.generate_salt()), 'smtp_password': Unicode(default=u'yes_you_really_should_change_me'), 'version': Unicode(default=Unicode(__version__)), 'version_db': Int(default=DATABASE_VERSION), 'https_priv_key': Unicode(), 'https_priv_gen': Bool(default=False), 'https_csr': Unicode(), 'https_cert': Unicode(), 'https_chain': Unicode(), 'https_dh_params': Unicode(), 'https_enabled': Bool(default=False), }, 'notification': { 'server': Unicode(default=u'demo.globaleaks.org'), 'port': Int(default=9267), 'username': Unicode(default=u'hey_you_should_change_me'), # See smtp_password in private for password 'source_name': Unicode(default=u'GlobaLeaks - CHANGE EMAIL ACCOUNT USED FOR NOTIFICATION'),
def db_user_update_user(session, tid, user_session, request): """ Updates the specified user. This version of the function is specific for users that with comparison with admins can change only few things: - real name - email address - preferred language - the password (with old password check) - pgp key raises: globaleaks.errors.ResourceNotFound` if the receiver does not exist. """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] new_password = request['password'] old_password = request['old_password'] if new_password: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, old_password, user.salt, user.password): raise errors.InvalidOldPassword # Regenerate the password hash only if different from the best choice on the platform if user.hash_alg != GCE.HASH: user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() password_hash = GCE.hash_password(new_password, user.salt) # Check that the new password is different form the current password if user.password == password_hash: raise errors.PasswordReuseError user.password = password_hash user.password_change_date = datetime_now() if State.tenant_cache[tid].encryption: enc_key = GCE.derive_key(request['password'].encode(), user.salt) if not user_session.cc: # Th First first password change triggers the generation # of the user encryption private key and its backup user_session.cc, user.crypto_pub_key = GCE.generate_keypair() user.crypto_bkp_key, user.crypto_rec_key = GCE.generate_recovery_key( user_session.cc) # If the user had already enabled two factor before encryption was not enable # encrypt the two factor secret if user.two_factor_secret: user.two_factor_secret = GCE.asymmetric_encrypt( user.crypto_pub_key, user.two_factor_secret) user.crypto_prv_key = GCE.symmetric_encrypt( enc_key, user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey(32) user_desc = user_serialize_user(session, user, user.language) user_desc['mail_address'] = request['mail_address'] template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, tid, user.language), 'notification': db_get_notification(session, tid, user.language) } State.format_and_send_mail(session, tid, user_desc, template_vars) # If the platform allows users to change PGP keys, process it if State.tenant_cache[tid]['enable_user_pgp_key_upload'] is True: parse_pgp_options(user, request) return user
def db_user_update_user(session, tid, user_session, request): """ Updates the specified user. This version of the function is specific for users that with comparison with admins can change only few things: - real name - email address - preferred language - the password (with old password check) - pgp key raises: globaleaks.errors.ResourceNotFound` if the receiver does not exist. """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] new_password = request['password'] old_password = request['old_password'] if new_password: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, old_password, user.salt, user.password): raise errors.InvalidOldPassword user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() user.password = GCE.hash_password(new_password, user.salt) user.password_change_date = datetime_now() if State.tenant_cache[1].encryption: enc_key = GCE.derive_key(request['password'].encode(), user.salt) if not user_session.cc: user_session.cc, user.crypto_pub_key = GCE.generate_keypair() user.crypto_prv_key = GCE.symmetric_encrypt(enc_key, user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey(32) user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, 1, user.language), 'notification': db_get_notification(session, tid, user.language) } State.format_and_send_mail(session, tid, user_desc, template_vars) # If the platform allows users to change PGP keys, process it if State.tenant_cache[tid]['enable_user_pgp_key_upload'] is True: parse_pgp_options(user, request) return user
def db_user_update_user(session, state, tid, user_session, request): """ Updates the specified user. This version of the function is specific for users that with comparison with admins can change only few things: - real name - email address - preferred language - the password (with old password check) - pgp key raises: globaleaks.errors.ResourceNotFound` if the receiver does not exist. """ from globaleaks.handlers.admin.notification import db_get_notification from globaleaks.handlers.admin.node import db_admin_serialize_node user = models.db_get(session, models.User, models.User.id == user_session.user_id) user.language = request.get('language', State.tenant_cache[tid].default_language) user.name = request['name'] new_password = request['password'] old_password = request['old_password'] if new_password: if user.password_change_needed: user.password_change_needed = False else: if not GCE.check_password(user.hash_alg, old_password, user.salt, user.password): raise errors.InvalidOldPassword user.hash_alg = GCE.HASH user.salt = GCE.generate_salt() user.password = GCE.hash_password(new_password, user.salt) user.password_change_date = datetime_now() if State.tenant_cache[1].encryption: enc_key = GCE.derive_key(request['password'].encode(), user.salt) if not user_session.cc: user_session.cc, user.crypto_pub_key = GCE.generate_keypair() user.crypto_prv_key = GCE.symmetric_encrypt( enc_key, user_session.cc) # If the email address changed, send a validation email if request['mail_address'] != user.mail_address: user.change_email_address = request['mail_address'] user.change_email_date = datetime_now() user.change_email_token = generateRandomKey(32) user_desc = user_serialize_user(session, user, user.language) template_vars = { 'type': 'email_validation', 'user': user_desc, 'new_email_address': request['mail_address'], 'validation_token': user.change_email_token, 'node': db_admin_serialize_node(session, 1, user.language), 'notification': db_get_notification(session, tid, user.language) } state.format_and_send_mail(session, tid, user_desc, template_vars) # If the platform allows users to change PGP keys, process it if State.tenant_cache[tid]['enable_user_pgp_key_upload'] is True: parse_pgp_options(state, user, request) return user
def db_create_user(session, tid, request, language): """ Transaction for creating a new user :param session: An ORM session :param tid: A tenant ID :param request: The request data :param language: The language of the request :return: The serialized descriptor of the created object """ request['tid'] = tid fill_localized_keys(request, models.User.localized_keys, language) if request['username']: user = session.query(models.User).filter( models.User.username == request['username'], models.User.tid == tid).one_or_none() if user is not None: raise errors.InputValidationError('Username already in use') user = models.User({ 'tid': tid, 'username': request['username'], 'role': request['role'], 'state': 'enabled', 'name': request['name'], 'description': request['description'], 'public_name': request['public_name'] if request['public_name'] else request['name'], 'language': language, 'password_change_needed': request['password_change_needed'], 'mail_address': request['mail_address'], 'can_edit_general_settings': request['can_edit_general_settings'] }) if not request['username']: user.username = user.id = uuid4() user.salt = GCE.generate_salt() # The various options related in manage PGP keys are used here. parse_pgp_options(user, request) session.add(user) session.flush() if request.get('send_account_activation_link', False): db_generate_password_reset_token(session, user) return user
from globaleaks.utils import process, tempdict, token, utility from globaleaks.utils.crypto import GCE from globaleaks.utils.objectdict import ObjectDict from globaleaks.utils.securetempfile import SecureTemporaryFile from globaleaks.utils.utility import datetime_null, datetime_now, datetime_to_ISO8601, \ sum_dicts from globaleaks.utils.log import log GCE.ALGORITM_CONFIGURATION['KDF']['ARGON2']['OPSLIMIT'] = GCE.ALGORITM_CONFIGURATION['HASH']['ARGON2']['OPSLIMIT'] = 1 GCE.ALGORITM_CONFIGURATION['HASH']['SCRYPT']['N'] = 1<<1 ################################################################################ # BEGIN MOCKS NECESSARY FOR DETERMINISTIC ENCRYPTION VALID_PASSWORD1 = u'ACollectionOfDiplomaticHistorySince_1966_ToThe_Pr esentDay#' VALID_PASSWORD2 = VALID_PASSWORD1 VALID_SALT1 = GCE.generate_salt() VALID_SALT2 = GCE.generate_salt() VALID_HASH1 = GCE.hash_password(VALID_PASSWORD1, VALID_SALT1) VALID_HASH2 = GCE.hash_password(VALID_PASSWORD2, VALID_SALT2) VALID_BASE64_IMG = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=' INVALID_PASSWORD = u'antani' KEY = GCE.generate_key() USER_KEY = GCE.derive_key(VALID_PASSWORD1, VALID_SALT1) USER_PRV_KEY, USER_PUB_KEY = GCE.generate_keypair() USER_PRV_KEY_ENC = GCE.symmetric_encrypt(USER_KEY, USER_PRV_KEY) GCE_orig_generate_key = GCE.generate_key GCE_orig_generate_keypair = GCE.generate_keypair @staticmethod
from globaleaks.utils.securetempfile import SecureTemporaryFile from globaleaks.utils.utility import datetime_null, datetime_now, datetime_to_ISO8601, \ sum_dicts from globaleaks.utils.log import log from globaleaks.workers import process from globaleaks.workers.supervisor import ProcessSupervisor GCE.ALGORITM_CONFIGURATION['KDF']['ARGON2']['OPSLIMIT'] = GCE.ALGORITM_CONFIGURATION['HASH']['ARGON2']['OPSLIMIT'] = 1 GCE.ALGORITM_CONFIGURATION['HASH']['SCRYPT']['N'] = 1<<1 ################################################################################ # BEGIN MOCKS NECESSARY FOR DETERMINISTIC ENCRYPTION VALID_PASSWORD1 = u'ACollectionOfDiplomaticHistorySince_1966_ToThe_Pr esentDay#' VALID_PASSWORD2 = VALID_PASSWORD1 VALID_SALT1 = GCE.generate_salt() VALID_SALT2 = GCE.generate_salt() VALID_HASH1 = GCE.hash_password(VALID_PASSWORD1, VALID_SALT1) VALID_HASH2 = GCE.hash_password(VALID_PASSWORD2, VALID_SALT2) VALID_BASE64_IMG = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=' INVALID_PASSWORD = u'antani' KEY = GCE.generate_key() USER_KEY = GCE.derive_key(VALID_PASSWORD1, VALID_SALT1) USER_PRV_KEY, USER_PUB_KEY = GCE.generate_keypair() USER_PRV_KEY_ENC = GCE.symmetric_encrypt(USER_KEY, USER_PRV_KEY) GCE_orig_generate_key = GCE.generate_key GCE_orig_generate_keypair = GCE.generate_keypair @staticmethod
# -*- coding: utf-8 import filecmp import os from globaleaks.settings import Settings from globaleaks.tests import helpers from globaleaks.utils.crypto import GCE password = b'password' message = b'message' salt = GCE.generate_salt() class TestCryptoUtils(helpers.TestGL): def test_generate_key(self): GCE.generate_key() def test_generate_keypair(self): key = GCE.generate_key() prv_key, pub_key = GCE.generate_keypair() prv_key_enc = GCE.symmetric_encrypt(key, prv_key) self.assertEqual(prv_key, GCE.symmetric_decrypt(key, prv_key_enc)) def test_export_import_key(self): x1, _ = GCE.generate_keypair() x2 = GCE.export_private_key(x1) x3 = GCE.import_private_key(x2) self.assertEqual(x1, x3._private_key) def test_derive_key(self): GCE.derive_key(password, salt)