def test_recovery_key(self): prv_key, _ = GCE.generate_keypair() bck_key, rec_key = GCE.generate_recovery_key(prv_key) plain_rec_key = GCE.asymmetric_decrypt(prv_key, Base64Encoder.decode(rec_key)) x = GCE.symmetric_decrypt(plain_rec_key, Base64Encoder.decode(bck_key)) self.assertEqual(x, prv_key)
def login(session, tid, username, password, authcode, client_using_tor, client_ip): """ login returns a session """ user = None users = session.query(User).filter(User.username == username, User.state != 'disabled', User.tid == tid).distinct() for u in users: if GCE.check_password(u.hash_alg, password, u.salt, u.password): user = u break # Fix for issue: https://github.com/globaleaks/GlobaLeaks/issues/2563 if State.tenant_cache[1].creation_date < 1551740400: u_password = '******'' + u.password + '\'' if GCE.check_password(u.hash_alg, password, u.salt, u_password): user = u break if user is None: log.debug("Login: Invalid credentials") Settings.failed_login_attempts += 1 raise errors.InvalidAuthentication connection_check(client_ip, tid, user.role, client_using_tor) crypto_prv_key = '' if State.tenant_cache[tid].encryption: if user.crypto_prv_key: user_key = GCE.derive_key(password.encode('utf-8'), user.salt) crypto_prv_key = GCE.symmetric_decrypt(user_key, user.crypto_prv_key) else: # Force the password change on which the user key will be created user.password_change_needed = True if user.two_factor_enable: if authcode != '': if user.crypto_pub_key: two_factor_secret = GCE.asymmetric_decrypt( crypto_prv_key, user.two_factor_secret).decode('utf-8') else: two_factor_secret = user.two_factor_secret.decode('utf-8') # RFC 6238: step size 30 sec; valid_window = 1; total size of the window: 1.30 sec if not pyotp.TOTP(two_factor_secret).verify(authcode, valid_window=1): raise errors.InvalidTwoFactorAuthCode else: raise errors.TwoFactorAuthCodeRequired user.last_login = datetime_now() return Sessions.new(tid, user.id, user.tid, user.role, user.password_change_needed, user.two_factor_enable, crypto_prv_key)
def login_whistleblower(session, tid, receipt): """ login_whistleblower returns a session """ x = None algorithms = [x[0] for x in session.query(WhistleblowerTip.hash_alg).filter(WhistleblowerTip.tid == tid).distinct()] if algorithms: hashes = [] for alg in algorithms: hashes.append(GCE.hash_password(receipt, State.tenant_cache[tid].receipt_salt, alg)) x = session.query(WhistleblowerTip, InternalTip) \ .filter(WhistleblowerTip.receipt_hash.in_(hashes), WhistleblowerTip.tid == tid, InternalTip.id == WhistleblowerTip.id, InternalTip.tid == WhistleblowerTip.tid).one_or_none() if x is None: log.debug("Whistleblower login: Invalid receipt") Settings.failed_login_attempts += 1 raise errors.InvalidAuthentication wbtip = x[0] itip = x[1] itip.wb_last_access = datetime_now() crypto_prv_key = '' if State.tenant_cache[tid].encryption and wbtip.crypto_prv_key: user_key = GCE.derive_key(receipt.encode('utf-8'), State.tenant_cache[tid].receipt_salt) crypto_prv_key = GCE.symmetric_decrypt(user_key, wbtip.crypto_prv_key) return Sessions.new(tid, wbtip.id, tid, 'whistleblower', False, crypto_prv_key)
def decrypt_tip(user_key, tip_prv_key, tip): tip_key = GCE.asymmetric_decrypt(user_key, tip_prv_key) for questionnaire in tip['questionnaires']: questionnaire['answers'] = json.loads(GCE.asymmetric_decrypt(tip_key, base64.b64decode(questionnaire['answers'].encode())).decode()) for k in ['whistleblower_identity']: if k in tip['data'] and tip['data'][k]: tip['data'][k] = json.loads(GCE.asymmetric_decrypt(tip_key, base64.b64decode(tip['data'][k].encode())).decode()) # Fix for issue: https://github.com/globaleaks/GlobaLeaks/issues/2612 # The bug is due to the fact that the data was initially saved as an array of one entry if k == 'whistleblower_identity' and isinstance(tip['data'][k], list): tip['data'][k] = tip['data'][k][0] for x in tip['comments'] + tip['messages']: x['content'] = GCE.asymmetric_decrypt(tip_key, base64.b64decode(x['content'].encode())).decode() for x in tip['wbfiles'] + tip['rfiles']: for k in ['name', 'description', 'type', 'size']: if k in x: x[k] = GCE.asymmetric_decrypt(tip_key, base64.b64decode(x[k].encode())).decode() if k == 'size': x[k] = int(x[k]) return tip
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_encrypt_and_decrypt_file(self): chunk_size = 1 prv_key, pub_key = GCE.generate_keypair() a = __file__ b = os.path.join(Settings.tmp_path, 'b') c = os.path.join(Settings.tmp_path, 'c') with open(a, 'rb') as input_fd, GCE.streaming_encryption_open( 'ENCRYPT', pub_key, b) as seo: chunk = input_fd.read(1) while (True): x = input_fd.read(1) if not x: seo.encrypt_chunk(chunk, 1) break seo.encrypt_chunk(chunk, 0) chunk = x with open(c, 'wb') as output_fd,\ GCE.streaming_encryption_open('DECRYPT', prv_key, b) as seo: while (True): last, data = seo.decrypt_chunk() output_fd.write(data) if last: break self.assertFalse(filecmp.cmp(a, b, False)) self.assertTrue(filecmp.cmp(a, c, False))
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_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 login_whistleblower(session, tid, receipt): """ login_whistleblower returns a session """ x = None algorithms = [x[0] for x in session.query(WhistleblowerTip.hash_alg).filter(WhistleblowerTip.tid == tid).distinct()] if algorithms: hashes = [] for alg in algorithms: hashes.append(GCE.hash_password(receipt, State.tenant_cache[tid].receipt_salt, alg)) x = session.query(WhistleblowerTip, InternalTip) \ .filter(WhistleblowerTip.receipt_hash.in_(hashes), WhistleblowerTip.tid == tid, InternalTip.id == WhistleblowerTip.id, InternalTip.tid == WhistleblowerTip.tid).one_or_none() if x is None: log.debug("Whistleblower login: Invalid receipt") Settings.failed_login_attempts += 1 raise errors.InvalidAuthentication wbtip = x[0] itip = x[1] itip.wb_last_access = datetime_now() crypto_prv_key = '' if State.tenant_cache[1].encryption and wbtip.crypto_prv_key: user_key = GCE.derive_key(receipt.encode('utf-8'), State.tenant_cache[tid].receipt_salt) crypto_prv_key = GCE.symmetric_decrypt(user_key, wbtip.crypto_prv_key) return Sessions.new(tid, wbtip.id, 'whistleblower', False, crypto_prv_key)
def test_encrypt_and_decrypt_file(self): chunk_size = 1 prv_key, pub_key = GCE.generate_keypair() a = __file__ b = os.path.join(Settings.tmp_path, 'b') c = os.path.join(Settings.tmp_path, 'c') with open(a, 'rb') as input_fd, GCE.streaming_encryption_open('ENCRYPT', pub_key, b) as seo: chunk = input_fd.read(1) while(True): x = input_fd.read(1) if not x: seo.encrypt_chunk(chunk, 1) break seo.encrypt_chunk(chunk, 0) chunk = x with open(c, 'wb') as output_fd,\ GCE.streaming_encryption_open('DECRYPT', prv_key, b) as seo: while(True): last, data = seo.decrypt_chunk() output_fd.write(data) if last: break self.assertFalse(filecmp.cmp(a, b, False)) self.assertTrue(filecmp.cmp(a, c, False))
def login_whistleblower(session, tid, receipt): """ Login transaction for whistleblowers' access :param session: An ORM session :param tid: A tenant ID :param receipt: A provided receipt :return: Returns a user session in case of success """ x = None algorithms = [x[0] for x in session.query(WhistleblowerTip.hash_alg).filter(WhistleblowerTip.tid == tid).distinct()] if algorithms: hashes = [GCE.hash_password(receipt, State.tenant_cache[tid].receipt_salt, alg) for alg in algorithms] x = session.query(WhistleblowerTip, InternalTip) \ .filter(WhistleblowerTip.receipt_hash.in_(hashes), WhistleblowerTip.tid == tid, InternalTip.id == WhistleblowerTip.id).one_or_none() if x is None: login_failure(tid, 1) wbtip = x[0] itip = x[1] itip.wb_last_access = datetime_now() crypto_prv_key = '' if wbtip.crypto_prv_key: user_key = GCE.derive_key(receipt.encode(), State.tenant_cache[tid].receipt_salt) crypto_prv_key = GCE.symmetric_decrypt(user_key, Base64Encoder.decode(wbtip.crypto_prv_key)) return Sessions.new(tid, wbtip.id, tid, 'whistleblower', False, False, crypto_prv_key, '')
def db_update_node(session, tid, user_session, request, language): """ Transaction to update the node configuration :param session: An ORM session :param tid: A tenant ID :param user_session: The current user session :param request: The request data :param language: the language in which to localize data :return: Return the serialized configuration for the specified tenant """ config = ConfigFactory(session, tid) enable_escrow = not config.get_val('escrow') and request.get('escrow', False) disable_escrow = user_session.ek and config.get_val('escrow') and not request.get('escrow', False) config.update('node', request) if request['enable_ricochet_panel'] and not request['ricochet_address']: request['enable_ricochet_panel'] = False # Validate that IP addresses/ranges we're getting are goo if 'ip_filter_admin' in request and request['ip_filter_admin_enable'] and request['ip_filter_admin']: parse_csv_ip_ranges_to_ip_networks(request['ip_filter_admin']) if 'languages_enabled' in request and 'default_language' in request: db_update_enabled_languages(session, tid, request['languages_enabled'], request['default_language']) if language in db_get_languages(session, tid): ConfigL10NFactory(session, tid).update('node', request, language) if enable_escrow: crypto_escrow_prv_key, State.tenant_cache[tid].crypto_escrow_pub_key = GCE.generate_keypair() user = db_get(session, models.User, models.User.id == user_session.user_id) user.crypto_escrow_prv_key = Base64Encoder.encode(GCE.asymmetric_encrypt(user.crypto_pub_key, crypto_escrow_prv_key)) if tid == 1: session.query(models.User).update({'password_change_needed': True}, synchronize_session=False) else: session.query(models.User).filter(models.User.tid == tid).update({'password_change_needed': True}, synchronize_session=False) if disable_escrow: if tid == 1: session.query(models.User).update({'crypto_escrow_bkp1_key': ''}, synchronize_session=False) else: session.query(models.User).update({'crypto_escrow_bkp2_key': ''}, synchronize_session=False) session.query(models.User).filter(models.User.tid == tid).update({'crypto_escrow_prv_key': ''}, synchronize_session=False) config.set_val('crypto_escrow_pub_key', State.tenant_cache[tid].crypto_escrow_pub_key) db_refresh_memory_variables(session, [tid]) if tid == 1: log.setloglevel(config.get_val('log_level')) return db_admin_serialize_node(session, tid, language)
def login(session, tid, username, password, authcode, client_using_tor, client_ip): """ Login transaction for users' access :param session: An ORM session :param tid: A tenant ID :param username: A provided username :param password: A provided password :param authcode: A provided authcode :param client_using_tor: A boolean signaling Tor usage :param client_ip: The client IP :return: Returns a user session in case of success """ user = None for u in session.query(User).filter(User.username == username, User.state == 'enabled', User.tid == tid): if GCE.check_password(u.hash_alg, password, u.salt, u.password): user = u break if user is None: log.debug("Login: Invalid credentials") login_error(tid) connection_check(tid, client_ip, user.role, client_using_tor) crypto_prv_key = '' if user.crypto_prv_key: user_key = GCE.derive_key(password.encode(), user.salt) crypto_prv_key = GCE.symmetric_decrypt( user_key, Base64Encoder.decode(user.crypto_prv_key)) elif State.tenant_cache[tid].encryption: # Force the password change on which the user key will be created user.password_change_needed = True # Require password change if password change threshold is exceeded if State.tenant_cache[tid].password_change_period > 0 and \ user.password_change_date < datetime_now() - timedelta(days=State.tenant_cache[tid].password_change_period): user.password_change_needed = True if user.two_factor_enable: if authcode != '': # RFC 6238: step size 30 sec; valid_window = 1; total size of the window: 1.30 sec if not pyotp.TOTP(user.two_factor_secret).verify(authcode, valid_window=1): raise errors.InvalidTwoFactorAuthCode else: raise errors.TwoFactorAuthCodeRequired user.last_login = datetime_now() return Sessions.new(tid, user.id, user.tid, user.role, user.password_change_needed, user.two_factor_enable, crypto_prv_key, user.crypto_escrow_prv_key)
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 login(session, tid, username, password, authcode, client_using_tor, client_ip): """ login returns a session """ user = None users = session.query(User).filter(User.username == username, User.state != u'disabled', UserTenant.user_id == User.id, UserTenant.tenant_id == tid).distinct() for u in users: if GCE.check_password(u.hash_alg, password, u.salt, u.password): user = u break if user is None: log.debug("Login: Invalid credentials") Settings.failed_login_attempts += 1 raise errors.InvalidAuthentication connection_check(client_ip, tid, user.role, client_using_tor) if State.tenant_cache[ 1].two_factor_auth and user.last_login != datetime_null(): token = TwoFactorTokens.get(user.id) if token is not None and authcode != '': if token.token == authcode: TwoFactorTokens.revoke(user.id) else: raise errors.InvalidTwoFactorAuthCode elif token is None and authcode == '': token = TwoFactorTokens.new(user.id) data = {'type': '2fa', 'authcode': str(token.token)} data['node'] = db_admin_serialize_node(session, tid, user.language) data['notification'] = db_get_notification(session, tid, user.language) subject, body = Templating().get_mail_subject_and_body(data) State.sendmail(1, user.mail_address, subject, body) raise errors.TwoFactorAuthCodeRequired else: raise errors.TwoFactorAuthCodeRequired user.last_login = datetime_now() crypto_prv_key = '' if State.tenant_cache[1].encryption and user.crypto_prv_key: user_key = GCE.derive_key(password.encode('utf-8'), user.salt) crypto_prv_key = GCE.symmetric_decrypt(user_key, user.crypto_prv_key) return Sessions.new(tid, user.id, user.role, user.password_change_needed, crypto_prv_key)
def get(self, rtip_id): tip_export = yield get_tip_export(self.request.tid, self.current_user.user_id, rtip_id, self.request.language) if tip_export['crypto_tip_prv_key']: tip_export['tip'] = yield deferToThread( decrypt_tip, self.current_user.cc, tip_export['crypto_tip_prv_key'], tip_export['tip']) for file_dict in tip_export['tip']['rfiles'] + tip_export['tip'][ 'wbfiles']: if file_dict.get('status', '') == 'encrypted' or file_dict.get('forged'): continue tip_prv_key = GCE.asymmetric_decrypt( self.current_user.cc, tip_export['crypto_tip_prv_key']) file_dict['fo'] = GCE.streaming_encryption_open( 'DECRYPT', tip_prv_key, file_dict['path']) del file_dict['path'] for file_dict in tip_export['tip']['rfiles']: file_dict['name'] = 'files/' + file_dict['name'] if file_dict.get('status', '') == 'encrypted': file_dict['name'] += '.pgp' for file_dict in tip_export['tip']['wbfiles']: file_dict[ 'name'] = 'files_attached_from_recipients/' + file_dict['name'] tip_export['comments'] = tip_export['tip']['comments'] tip_export['messages'] = tip_export['tip']['messages'] files = tip_export['tip']['rfiles'] + tip_export['tip']['wbfiles'] del tip_export['tip']['rfiles'], tip_export['tip']['wbfiles'] export_template = Templating().format_template( tip_export['notification']['export_template'], tip_export).encode() export_template = msdos_encode(export_template.decode()).encode() files.append({ 'fo': BytesIO(export_template), 'name': 'data.txt', 'forged': True }) self.request.setHeader(b'X-Download-Options', b'noopen') self.request.setHeader(b'Content-Type', b'application/octet-stream') self.request.setHeader(b'Content-Disposition', b'attachment; filename="submission.zip"') self.zip_stream = iter(ZipStream(files)) yield ZipStreamProducer(self, self.zip_stream).start()
def login(session, tid, username, password, client_using_tor, client_ip): """ login returns a session """ user = None users = session.query(User).filter(User.username == username, User.state != u'disabled', UserTenant.user_id == User.id, UserTenant.tenant_id == tid).distinct() for u in users: if GCE.check_password(u.hash_alg, password, u.salt, u.password): user = u break if user is None: log.debug("Login: Invalid credentials") Settings.failed_login_attempts += 1 raise errors.InvalidAuthentication if not client_using_tor and not State.tenant_cache[tid]['https_' + user.role]: log.err("Denied login request over Web for role '%s'" % user.role) raise errors.TorNetworkRequired # Check if we're doing IP address checks today if State.tenant_cache[tid]['ip_filter_authenticated_enable']: ip_networks = parse_csv_ip_ranges_to_ip_networks( State.tenant_cache[tid]['ip_filter_authenticated']) if isinstance(client_ip, binary_type): client_ip = client_ip.decode() client_ip_obj = ipaddress.ip_address(client_ip) # Safety check, we always allow localhost to log in success = False if client_ip_obj.is_loopback is True: success = True for ip_network in ip_networks: if client_ip_obj in ip_network: success = True if success is not True: raise errors.AccessLocationInvalid user.last_login = datetime_now() crypto_prv_key = '' if State.tenant_cache[1].encryption and user.crypto_prv_key: user_key = GCE.derive_key(password.encode('utf-8'), user.salt) crypto_prv_key = GCE.symmetric_decrypt(user_key, user.crypto_prv_key) return Sessions.new(tid, user.id, user.role, user.password_change_needed, crypto_prv_key)
def validate_password_reset(session, reset_token, auth_code, recovery_key): """ Retrieves a user given a password reset validation token :param session: An ORM session :param reset_token: A reset token :param auth_code: A two factor authentication code (optional) :param recovery_key: An encryption recovery key (optional) :return: A descriptor describing the result of the operation """ now = datetime.now() prv_key = '' user = session.query(models.User).filter( models.User.reset_password_token == reset_token, models.User.reset_password_date >= now - timedelta(hours=72) ).one_or_none() # If the authentication token is invalid if user is None: return {'status': 'invalid_reset_token_provided'} # If encryption is enabled require the recovery key if user.crypto_prv_key: try: x = State.TempKeys.pop(user.id, None) if x: enc_key = GCE.derive_key(reset_token.encode(), user.salt) prv_key = GCE.symmetric_decrypt(enc_key, Base64Encoder.decode(x.key)) else: recovery_key = recovery_key.replace('-', '').upper() + '====' recovery_key = Base32Encoder.decode(recovery_key.encode()) prv_key = GCE.symmetric_decrypt(recovery_key, Base64Encoder.decode(user.crypto_bkp_key)) except: return {'status': 'require_recovery_key'} elif user.two_factor_enable: two_factor_secret = user.two_factor_secret if not pyotp.TOTP(two_factor_secret).verify(auth_code, valid_window=1): return {'status': 'require_two_factor_authentication'} # Token is used, void it out user.reset_password_token = None user.reset_password_date = now # Require password change user.password_change_needed = True session = Sessions.new(user.tid, user.id, user.tid, user.role, user.password_change_needed, user.two_factor_enable, prv_key, user.crypto_escrow_prv_key) return {'status': 'success', 'token': session.id}
def get(self, rfile_id): rfile, tip_prv_key = yield self.download_rfile(self.request.tid, self.current_user.user_id, rfile_id) filelocation = os.path.join(Settings.attachments_path, rfile['filename']) directory_traversal_check(Settings.attachments_path, filelocation) if tip_prv_key: tip_prv_key = GCE.asymmetric_decrypt(self.current_user.cc, tip_prv_key) fo = GCE.streaming_encryption_open('DECRYPT', tip_prv_key, filelocation) yield self.write_file_as_download_fo(rfile['name'], fo) else: yield self.write_file_as_download(rfile['name'], filelocation)
def generate_password_reset_token(session, tid, user_session, user_id): user = session.query(User).filter(User.tid == tid, User.id == user_id).one_or_none() if user is None: return db_generate_password_reset_token(session, user) if user_session.ek and user.crypto_pub_key: crypto_escrow_prv_key = GCE.asymmetric_decrypt(user_session.cc, Base64Encoder.decode(user_session.ek)) user_cc = GCE.asymmetric_decrypt(crypto_escrow_prv_key, Base64Encoder.decode(user.crypto_escrow_bkp1_key)) enc_key = GCE.derive_key(user.reset_password_token.encode(), user.salt) key = Base64Encoder.encode(GCE.symmetric_encrypt(enc_key, user_cc)) State.TempKeys[user_id] = TempKey(key)
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 decrypt_tip(user_key, tip_prv_key, tip): tip_key = GCE.asymmetric_decrypt(user_key, tip_prv_key) for questionnaire in tip['questionnaires']: questionnaire['answers'] = json.loads(GCE.asymmetric_decrypt(tip_key, base64.b64decode(questionnaire['answers'].encode())).decode()) for k in ['whistleblower_identity']: if k in tip['data'] and tip['data'][k]['encrypted'] and tip['data'][k]['value']: tip['data'][k]['value'] = json.loads(GCE.asymmetric_decrypt(tip_key, base64.b64decode(tip['data'][k]['value'].encode())).decode()) for x in tip['comments'] + tip['messages']: x['content'] = GCE.asymmetric_decrypt(tip_key, base64.b64decode(x['content'].encode())).decode() return tip
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 create_comment(session, tid, wbtip_id, user_key, content): wbtip, itip = session.query(models.WhistleblowerTip, models.InternalTip)\ .filter(models.WhistleblowerTip.id == wbtip_id, models.InternalTip.id == models.WhistleblowerTip.id, models.InternalTip.tid == tid).one_or_none() if wbtip is None: raise errors.ModelNotFound(models.WhistleblowerTip) itip.update_date = itip.wb_last_access = datetime_now() comment = models.Comment() comment.internaltip_id = wbtip_id comment.type = u'whistleblower' if itip.crypto_tip_pub_key: comment.content = base64.b64encode(GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, content)).decode() else: comment.content = content session.add(comment) session.flush() ret = serialize_comment(session, comment) ret['content'] = content return ret
def get_recovery_key(session, user_tid, user_id, user_cc): user = db_get_user(session, user_tid, user_id) if not user.crypto_rec_key: return '' return Base32Encoder().encode(GCE.asymmetric_decrypt(user_cc, user.crypto_rec_key)).replace(b'=', b'')
def create_message(session, tid, wbtip_id, user_key, receiver_id, content): wbtip, itip, rtip_id = session.query(models.WhistleblowerTip, models.InternalTip, models.ReceiverTip.id) \ .filter(models.WhistleblowerTip.id == wbtip_id, models.ReceiverTip.internaltip_id == wbtip_id, models.ReceiverTip.receiver_id == receiver_id, models.InternalTip.id == models.WhistleblowerTip.id, models.InternalTip.tid == tid).one_or_none() if wbtip is None: raise errors.ModelNotFound(models.WhistleblowerTip) itip.update_date = itip.wb_last_access = datetime_now() msg = models.Message() msg.receivertip_id = rtip_id msg.type = u'whistleblower' if itip.crypto_tip_pub_key: msg.content = base64.b64encode(GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, content)).decode() else: msg.content = content session.add(msg) session.flush() ret = serialize_message(session, msg) ret['content'] = content return ret
def create_message(session, tid, user_id, rtip_id, content): """ Transaction for registering a new message :param session: An ORM session :param tid: A tenant ID :param user_id: The user id of the user creating the message :param rtip_id: The rtip associated to the message to be created :param content: The content of the message :return: A serialized descriptor of the message """ rtip, itip = db_access_rtip(session, tid, user_id, rtip_id) itip.update_date = rtip.last_access = datetime_now() _content = content if itip.crypto_tip_pub_key: _content = base64.b64encode( GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, content)).decode() msg = models.Message() msg.receivertip_id = rtip.id msg.type = 'receiver' msg.content = _content session.add(msg) session.flush() ret = serialize_message(session, msg) ret['content'] = content return ret
def create_comment(session, tid, user_id, rtip_id, content): """ Transaction for registering a new comment :param session: An ORM session :param tid: A tenant ID :param user_id: The user id of the user creating the comment :param rtip_id: The rtip associated to the comment to be created :param content: The content of the comment :return: A serialized descriptor of the comment """ rtip, itip = db_access_rtip(session, tid, user_id, rtip_id) itip.update_date = rtip.last_access = datetime_now() _content = content if itip.crypto_tip_pub_key: _content = base64.b64encode( GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, content)).decode() comment = models.Comment() comment.internaltip_id = itip.id comment.type = 'receiver' comment.author_id = rtip.receiver_id comment.content = _content session.add(comment) session.flush() ret = serialize_comment(session, comment) ret['content'] = content return ret
def register_ifile_on_db(session, tid, internaltip_id, uploaded_file): now = datetime_now() itip = session.query(models.InternalTip) \ .filter(models.InternalTip.id == internaltip_id, models.InternalTip.tid == tid).one() itip.update_date = now itip.wb_last_access = now if itip.crypto_tip_pub_key: for k in ['name', 'type', 'size']: uploaded_file[k] = base64.b64encode( GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, uploaded_file[k])) new_file = models.InternalFile() new_file.name = uploaded_file['name'] new_file.content_type = uploaded_file['type'] new_file.size = uploaded_file['size'] new_file.internaltip_id = internaltip_id new_file.filename = uploaded_file['filename'] new_file.submission = uploaded_file['submission'] new_file.internaltip_id = internaltip_id session.add(new_file) return serializers.serialize_ifile(session, new_file)
def create_message(session, tid, wbtip_id, receiver_id, content): wbtip, itip, rtip_id = db_get(session, (models.WhistleblowerTip, models.InternalTip, models.ReceiverTip.id), (models.WhistleblowerTip.id == wbtip_id, models.ReceiverTip.internaltip_id == wbtip_id, models.ReceiverTip.receiver_id == receiver_id, models.InternalTip.id == models.WhistleblowerTip.id, models.InternalTip.enable_two_way_messages.is_(True), models.InternalTip.status != 'closed', models.InternalTip.tid == tid)) itip.update_date = itip.wb_last_access = datetime_now() _content = content if itip.crypto_tip_pub_key: _content = base64.b64encode(GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, content)).decode() msg = models.Message() msg.receivertip_id = rtip_id msg.type = 'whistleblower' msg.content = _content session.add(msg) session.flush() ret = serialize_message(session, msg) ret['content'] = content return ret
def store_additional_questionnaire_answers(session, tid, tip_id, answers, language): itip = session.query(models.InternalTip) \ .filter(models.InternalTip.id == tip_id, models.InternalTip.status != 'closed', models.InternalTip.tid == tid).one() if not itip.additional_questionnaire_id: return steps = db_get_questionnaire(session, tid, itip.additional_questionnaire_id, None)['steps'] questionnaire_hash = db_archive_questionnaire_schema(session, steps) db_save_plaintext_answers(session, tid, itip.id, answers, itip.crypto_tip_pub_key != '') if itip.crypto_tip_pub_key: answers = base64.b64encode( GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, json.dumps(answers).encode())).decode() db_set_internaltip_answers(session, itip.id, questionnaire_hash, answers) itip.additional_questionnaire_id = ''
def create_comment(session, tid, wbtip_id, content): wbtip, itip = db_get(session, (models.WhistleblowerTip, models.InternalTip), (models.WhistleblowerTip.id == wbtip_id, models.InternalTip.id == models.WhistleblowerTip.id, models.InternalTip.enable_two_way_comments.is_(True), models.InternalTip.status != 'closed', models.InternalTip.tid == tid)) itip.update_date = itip.wb_last_access = datetime_now() _content = content if itip.crypto_tip_pub_key: _content = base64.b64encode(GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, content)).decode() comment = models.Comment() comment.internaltip_id = wbtip_id comment.type = 'whistleblower' comment.content = _content session.add(comment) session.flush() ret = serialize_comment(session, comment) ret['content'] = content return ret
def register_wbfile_on_db(session, tid, rtip_id, uploaded_file): rtip, itip = session.query(models.ReceiverTip, models.InternalTip) \ .filter(models.ReceiverTip.id == rtip_id, models.ReceiverTip.internaltip_id == models.InternalTip.id, models.InternalTip.tid == tid).one() itip.update_date = rtip.last_access = datetime_now() if itip.crypto_tip_pub_key: for k in ['name', 'description', 'type', 'size']: uploaded_file[k] = base64.b64encode( GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, text_type(uploaded_file[k]))) new_file = models.WhistleblowerFile() new_file.name = uploaded_file['name'] new_file.description = uploaded_file['description'] new_file.content_type = uploaded_file['type'] new_file.size = uploaded_file['size'] new_file.receivertip_id = rtip_id new_file.filename = uploaded_file['filename'] session.add(new_file) return serializers.serialize_wbfile(session, tid, new_file)
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 get_internalfiles_by_receipt(self, session, receipt): hashed_receipt = GCE.hash_password(receipt, State.tenant_cache[1].receipt_salt) ifiles = session.query(models.InternalFile) \ .filter(models.InternalFile.internaltip_id == models.WhistleblowerTip.id, models.WhistleblowerTip.receipt_hash == hashed_receipt) return [models.serializers.serialize_ifile(session, ifile) for ifile in ifiles]
def get(self): user = yield get_user(self.request.tid, self.current_user.user_id, self.request.language) user['cc'] = '' if self.current_user.cc: user['cc'] = GCE.export_private_key(self.current_user.cc) returnValue(user)
def update_identity_information(session, tid, tip_id, identity_field_id, wbi, language): itip = models.db_get(session, models.InternalTip, models.InternalTip.id == tip_id, models.InternalTip.tid == tid) if itip.crypto_tip_pub_key: wbi = base64.b64encode(GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, json.dumps(wbi).encode())).decode() db_set_internaltip_data(session, itip.id, 'identity_provided', True, False) db_set_internaltip_data(session, itip.id, 'whistleblower_identity', wbi, True) now = datetime_now() itip.update_date = now itip.wb_last_access = now
def write_encrypted_file(key, sf, dest_path): try: with sf.open('rb') as encrypted_file, \ GCE.streaming_encryption_open('ENCRYPT', key, dest_path) as seo: chunk = encrypted_file.read(abstract.FileDescriptor.bufferSize) while True: x = encrypted_file.read(abstract.FileDescriptor.bufferSize) if not x: seo.encrypt_chunk(chunk, 1) break seo.encrypt_chunk(chunk, 0) chunk = x except Exception as excep: log.err("Unable to create plaintext file %s: %s", dest_path, excep)
def create_message(session, tid, user_id, user_key, rtip_id, content): rtip, itip = db_access_rtip(session, tid, user_id, rtip_id) itip.update_date = rtip.last_access = datetime_now() msg = models.Message() msg.receivertip_id = rtip.id msg.type = u'receiver' if itip.crypto_tip_pub_key: msg.content = base64.b64encode(GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, content)).decode() else: msg.content = content session.add(msg) session.flush() ret = serialize_message(session, msg) ret['content'] = content return ret
def create_comment(session, tid, user_id, user_key, rtip_id, content): rtip, itip = db_access_rtip(session, tid, user_id, rtip_id) itip.update_date = rtip.last_access = datetime_now() comment = models.Comment() comment.internaltip_id = itip.id comment.type = u'receiver' comment.author_id = rtip.receiver_id if itip.crypto_tip_pub_key: comment.content = base64.b64encode(GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, content)).decode() else: comment.content = content session.add(comment) session.flush() ret = serialize_comment(session, comment) ret['content'] = content return ret
# -*- 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)
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_crypto_generate_encrypt_decrypt_message(self): prv_key, pub_key = GCE.generate_keypair() enc = GCE.asymmetric_encrypt(pub_key, message) dec = GCE.asymmetric_decrypt(prv_key, enc) self.assertEqual(dec, message)
# -*- 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 login(session, tid, username, password, authcode, client_using_tor, client_ip): """ login returns a session """ user = None users = session.query(User).filter(User.username == username, User.state != u'disabled', UserTenant.user_id == User.id, UserTenant.tenant_id == tid).distinct() for u in users: if GCE.check_password(u.hash_alg, password, u.salt, u.password): user = u break # Fix for issue: https://github.com/globaleaks/GlobaLeaks/issues/2563 if State.tenant_cache[1].creation_date < datetime.timestamp(datetime(2019, 5, 3, 0, 0)): u_password = '******'' + u.password + '\'' if GCE.check_password(u.hash_alg, password, u.salt, u_password): user = u break if user is None: log.debug("Login: Invalid credentials") Settings.failed_login_attempts += 1 raise errors.InvalidAuthentication connection_check(client_ip, tid, user.role, client_using_tor) if State.tenant_cache[1].two_factor_auth and user.last_login != datetime_null(): token = TwoFactorTokens.get(user.id) if token is not None and authcode != '': if token.token == authcode: TwoFactorTokens.revoke(user.id) else: raise errors.InvalidTwoFactorAuthCode elif token is None and authcode == '': token = TwoFactorTokens.new(user.id) data = { 'type': '2fa', 'authcode': str(token.token) } data['node'] = db_admin_serialize_node(session, tid, user.language) data['notification'] = db_get_notification(session, tid, user.language) subject, body = Templating().get_mail_subject_and_body(data) State.sendmail(1, user.mail_address, subject, body) raise errors.TwoFactorAuthCodeRequired else: raise errors.TwoFactorAuthCodeRequired user.last_login = datetime_now() crypto_prv_key = '' if State.tenant_cache[1].encryption and user.crypto_prv_key: user_key = GCE.derive_key(password.encode('utf-8'), user.salt) crypto_prv_key = GCE.symmetric_decrypt(user_key, user.crypto_prv_key) return Sessions.new(tid, user.id, user.role, user.password_change_needed, crypto_prv_key)
def test_derive_key(self): GCE.derive_key(password, salt)
def db_create_submission(session, tid, request, token, client_using_tor): if not request['receivers']: raise errors.InputValidationError("need at least one recipient") answers = request['answers'] context, questionnaire = session.query(models.Context, models.Questionnaire) \ .filter(models.Context.id == request['context_id'], models.Questionnaire.id == models.Context.questionnaire_id, models.Questionnaire.tid.in_(set([1, tid]))).one_or_none() if not context: raise errors.ModelNotFound(models.Context) steps = db_get_questionnaire(session, tid, questionnaire.id, None)['steps'] questionnaire_hash = db_archive_questionnaire_schema(session, steps) itip = models.InternalTip() itip.tid = tid itip.status = db_get_id_for_system_status(session, tid, u'new') itip.progressive = db_assign_submission_progressive(session, tid) itip.additional_questionnaire_id = context.additional_questionnaire_id if context.tip_timetolive > 0: itip.expiration_date = get_expiration(context.tip_timetolive) # Evaluate the score level itip.total_score = request['total_score'] # The status https is used to keep track of the security level adopted by the whistleblower itip.https = not client_using_tor itip.context_id = context.id itip.enable_two_way_comments = context.enable_two_way_comments itip.enable_two_way_messages = context.enable_two_way_messages itip.enable_attachments = context.enable_attachments x = session.query(models.Field, models.FieldAttr.value) \ .filter(models.Field.template_id == u'whistleblower_identity', models.Field.step_id == models.Step.id, models.Step.questionnaire_id == context.questionnaire_id, models.FieldAttr.field_id == models.Field.id, models.FieldAttr.name == u'visibility_subject_to_authorization').one_or_none() whistleblower_identity = None can_access_whistleblower_identity = True if x: whistleblower_identity = x[0] can_access_whistleblower_identity = not x[1] itip.enable_whistleblower_identity = whistleblower_identity is not None itip.preview = extract_answers_preview(steps, answers) session.add(itip) session.flush() crypto_is_available = State.tenant_cache[1].encryption # Evaluate if encryption is available if crypto_is_available: users_count = session.query(models.User) \ .filter(models.User.id.in_(request['receivers']), models.User.crypto_prv_key != b'').count() crypto_is_available = users_count == len(request['receivers']) if crypto_is_available: crypto_tip_prv_key, itip.crypto_tip_pub_key = GCE.generate_keypair() # Evaluate if the whistleblower tip should be generated if ((not context.enable_scoring_system) or (context.score_threshold_receipt == 0) or (context.score_threshold_receipt == 1 and itip.total_score >= 2) or (context.score_threshold_receipt == 2 and itip.total_score == 3)): receipt = GCE.generate_receipt() receipt_salt = State.tenant_cache[tid].receipt_salt wbtip = models.WhistleblowerTip() wbtip.id = itip.id wbtip.tid = tid wbtip.hash_alg = GCE.HASH wbtip.receipt_hash = GCE.hash_password(receipt, receipt_salt) # Evaluate if the whistleblower tip should be encrypted if crypto_is_available: crypto_tip_prv_key, itip.crypto_tip_pub_key = GCE.generate_keypair() wb_key = GCE.derive_key(receipt.encode(), receipt_salt) wb_prv_key, wb_pub_key = GCE.generate_keypair() wbtip.crypto_prv_key = GCE.symmetric_encrypt(wb_key, wb_prv_key) wbtip.crypto_pub_key = wb_pub_key wbtip.crypto_tip_prv_key = GCE.asymmetric_encrypt(wb_pub_key, crypto_tip_prv_key) session.add(wbtip) else: receipt = '' # Apply special handling to the whistleblower identity question if itip.enable_whistleblower_identity and request['identity_provided'] and answers[whistleblower_identity.id]: if crypto_is_available: wbi = base64.b64encode(GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, json.dumps(answers[whistleblower_identity.id][0]).encode())).decode() answers[whistleblower_identity.id] = '' else: wbi = answers[whistleblower_identity.id][0] db_set_internaltip_data(session, itip.id, 'identity_provided', True, False) db_set_internaltip_data(session, itip.id, 'whistleblower_identity', wbi, crypto_is_available) if crypto_is_available: answers = base64.b64encode(GCE.asymmetric_encrypt(itip.crypto_tip_pub_key, json.dumps(answers).encode())).decode() else: db_save_questionnaire_answers(session, tid, itip.id, answers) db_set_internaltip_answers(session, itip.id, questionnaire_hash, answers, crypto_is_available) for filedesc in token.uploaded_files: new_file = models.InternalFile() new_file.tid = tid new_file.encrypted = crypto_is_available new_file.name = filedesc['name'] new_file.description = "" new_file.content_type = filedesc['type'] new_file.size = filedesc['size'] new_file.internaltip_id = itip.id new_file.submission = filedesc['submission'] new_file.filename = filedesc['filename'] session.add(new_file) log.debug("=> file associated %s|%s (%d bytes)", new_file.name, new_file.content_type, new_file.size) if context.maximum_selectable_receivers > 0 and \ len(request['receivers']) > context.maximum_selectable_receivers: raise errors.InputValidationError("selected an invalid number of recipients") for user in session.query(models.User).filter(models.User.id.in_(request['receivers'])): if not crypto_is_available and not user.pgp_key_public and not State.tenant_cache[tid].allow_unencrypted: continue _tip_key = b'' if crypto_is_available: _tip_key = GCE.asymmetric_encrypt(user.crypto_pub_key, crypto_tip_prv_key) db_create_receivertip(session, user, itip, can_access_whistleblower_identity, _tip_key) return { 'receipt': receipt, 'score': itip.total_score }
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 test_crypto_generate_key_encrypt_decrypt_key(self): enc_key = GCE.generate_key() enc = GCE.symmetric_encrypt(enc_key, message) dec = GCE.symmetric_decrypt(enc_key, enc) self.assertEqual(dec, message)
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
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_check_password(self): hash = GCE.hash_password(password, salt) self.assertTrue(GCE.check_password(GCE.HASH, password, salt, hash)) self.assertFalse(GCE.check_password(GCE.HASH, password, salt, 'nohashnoparty'))