Skip to content

Commit

Permalink
Repair make_hash on Python 3.
Browse files Browse the repository at this point in the history
  • Loading branch information
albu-diku committed Oct 7, 2024
1 parent 8b3c81c commit 787f546
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
6 changes: 6 additions & 0 deletions mig/shared/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ def _is_unicode(val):
return (type(val) == _TYPE_UNICODE)


def _unicode_string_to_utf8_bytes(unicode_string):
"""Convert a unicode string value to bytes."""

return codecs.encode(unicode_string, 'utf8')


def ensure_native_string(string_or_bytes):
"""Given a supplied input which can be either a string or bytes
return a representation providing string operations while ensuring that
Expand Down
14 changes: 9 additions & 5 deletions mig/shared/pwcrypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from builtins import zip, range
from base64 import b64encode, b64decode, b16encode, b16decode, \
urlsafe_b64encode, urlsafe_b64decode
import codecs
from os import urandom
from random import SystemRandom
from string import ascii_lowercase, ascii_uppercase, digits
Expand All @@ -43,6 +44,7 @@
import time

from mig.shared.base import force_utf8, mask_creds, string_snippet
from mig.shared.compat import _unicode_string_to_utf8_bytes
from mig.shared.defaults import keyword_auto, RESET_TOKEN_TTL


Expand Down Expand Up @@ -114,12 +116,14 @@ def best_crypt_salt(configuration):
return salt_data


def make_hash(password):
def make_hash(password, _urandom=urandom):
"""Generate a random salt and return a new hash for the password."""
salt = b64encode(urandom(SALT_LENGTH))
derived = b64encode(hashlib.pbkdf2_hmac(HASH_FUNCTION,
force_utf8(password), salt,
COST_FACTOR, KEY_LENGTH))
salt = b64encode(_urandom(SALT_LENGTH))
password_bytes = _unicode_string_to_utf8_bytes(password)
password_hashed = hashlib.pbkdf2_hmac(HASH_FUNCTION,
password_bytes, salt,
COST_FACTOR, KEY_LENGTH)
derived = b64encode(password_hashed)
return 'PBKDF2${}${}${}${}'.format(HASH_FUNCTION, COST_FACTOR,
salt, derived)

Expand Down
49 changes: 49 additions & 0 deletions tests/test_mig_shared_pwcrypto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
#
# --- BEGIN_HEADER ---
#
# Copyright (C) 2003-2024 The MiG Project by the Science HPC Center at UCPH
#
# This file is part of MiG.
#
# MiG is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# MiG is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
# --- END_HEADER ---
#

"""Unit test pwcrypto functions"""

import os
import sys

sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), ".")))

from support import PY2, MigTestCase, temppath, testmain
from mig.shared.pwcrypto import *

class MigSharedPwcrypto_make_hash(MigTestCase):
def test_pickle_string(self):
expected_py2 = "PBKDF2$sha256$10000$MDAwMDAwMDAwMDAw$epib2rEg/HYTQZFnCp7hmIGZ6rzHnViy"
expected_py3 = "PBKDF2$sha256$10000$b'MDAwMDAwMDAwMDAw'$b'epib2rEg/HYTQZFnCp7hmIGZ6rzHnViy'"
expected = expected_py2 if PY2 else expected_py3

actual = make_hash('foobar', _urandom=lambda vlen: b'0' * vlen)

self.assertEqual(actual, expected, "mismatch pickling string")


if __name__ == '__main__':
testmain()

0 comments on commit 787f546

Please sign in to comment.