diff --git a/apps/common/hashers/__init__.py b/apps/common/hashers/__init__.py new file mode 100644 index 000000000..6313fa88b --- /dev/null +++ b/apps/common/hashers/__init__.py @@ -0,0 +1 @@ +from .sm3 import PBKDF2SM3PasswordHasher diff --git a/apps/common/hashers/sm3.py b/apps/common/hashers/sm3.py new file mode 100644 index 000000000..62f811e94 --- /dev/null +++ b/apps/common/hashers/sm3.py @@ -0,0 +1,23 @@ +from gmssl import sm3, func + +from django.contrib.auth.hashers import PBKDF2PasswordHasher + + +class Hasher: + name = 'sm3' + + def __init__(self, key): + self.key = key + + def hexdigest(self): + return sm3.sm3_hash(func.bytes_to_list(self.key)) + + @staticmethod + def hash(msg): + return Hasher(msg) + + +class PBKDF2SM3PasswordHasher(PBKDF2PasswordHasher): + algorithm = "pbkdf2_sm3" + digest = Hasher.hash + diff --git a/apps/common/utils/crypto.py b/apps/common/utils/crypto.py index 3922a5462..d600e7822 100644 --- a/apps/common/utils/crypto.py +++ b/apps/common/utils/crypto.py @@ -162,34 +162,42 @@ gm_sm4_ecb_crypto = get_gm_sm4_ecb_crypto() class Crypto: - cryptoes = { + cryptor_map = { 'aes_ecb': aes_ecb_crypto, 'aes_gcm': aes_crypto, 'aes': aes_crypto, 'gm_sm4_ecb': gm_sm4_ecb_crypto, 'gm': gm_sm4_ecb_crypto, } + cryptos = [] def __init__(self): - cryptoes = self.__class__.cryptoes.copy() - crypto = cryptoes.pop(settings.SECURITY_DATA_CRYPTO_ALGO, None) - if crypto is None: + crypt_algo = settings.SECURITY_DATA_CRYPTO_ALGO + if not crypt_algo: + if settings.GMSSL_ENABLED: + crypt_algo = 'gm' + else: + crypt_algo = 'aes' + + cryptor = self.cryptor_map.get(crypt_algo, None) + if cryptor is None: raise ImproperlyConfigured( f'Crypto method not supported {settings.SECURITY_DATA_CRYPTO_ALGO}' ) - self.cryptoes = [crypto, *cryptoes.values()] + others = set(self.cryptor_map.values()) - {cryptor} + self.cryptos = [cryptor, *others] @property def encryptor(self): - return self.cryptoes[0] + return self.cryptos[0] def encrypt(self, text): return self.encryptor.encrypt(text) def decrypt(self, text): - for decryptor in self.cryptoes: + for cryptor in self.cryptos: try: - origin_text = decryptor.decrypt(text) + origin_text = cryptor.decrypt(text) if origin_text: # 有时不同算法解密不报错,但是返回空字符串 return origin_text diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 8ebc704d3..5f4514bf8 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -387,7 +387,8 @@ class Config(dict): 'SESSION_SAVE_EVERY_REQUEST': True, 'SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE': False, 'SERVER_REPLAY_STORAGE': {}, - 'SECURITY_DATA_CRYPTO_ALGO': 'aes', + 'SECURITY_DATA_CRYPTO_ALGO': None, + 'GMSSL_ENABLED': False, # 记录清理清理 'LOGIN_LOG_KEEP_DAYS': 200, diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index 519623ac9..a8e521460 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -307,6 +307,18 @@ CSRF_COOKIE_SECURE = CONFIG.CSRF_COOKIE_SECURE DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' +PASSWORD_HASHERS = [ + 'django.contrib.auth.hashers.PBKDF2PasswordHasher', + 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', + 'django.contrib.auth.hashers.Argon2PasswordHasher', + 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', +] + + +GMSSL_ENABLED = CONFIG.GMSSL_ENABLED +if GMSSL_ENABLED: + PASSWORD_HASHERS.insert(0, 'common.hashers.PBKDF2SM3PasswordHasher') + # For Debug toolbar INTERNAL_IPS = ["127.0.0.1"] if os.environ.get('DEBUG_TOOLBAR', False): @@ -315,3 +327,4 @@ if os.environ.get('DEBUG_TOOLBAR', False): DEBUG_TOOLBAR_PANELS = [ 'debug_toolbar.panels.profiling.ProfilingPanel', ] +