← run

bcb-0024

1.000
6/6 tests· lib-knowledge
Challenge · difficulty 2/5
# BigCodeBench/24

Implement a file **`solution.py`** that completes the function below. Keep the given name and signature; define `task_func` at module level.

Allowed libraries: `base64`, `hashlib`, `os`.

```python
import base64
import hashlib
import os

def task_func(password, SALT_LENGTH = 32):
    """
    Hashes a password using the PBKDF2 HMAC algorithm with SHA-256 as the hashing algorithm, 
    combined with a randomly generated salt, and returns both the salt and the hashed password, 
    each base64-encoded.

    Parameters:
    password (str): The password to be hashed.
    SALT_LENGTH (int): the length of the randomly generated salt.

    Returns:
    tuple[bytes, bytes]: A tuple containing the base64-encoded salt and the base64-encoded hashed password as byte strings.

    Raises:
    ValueError if the password is None or empty

    Requirements:
    - base64
    - hashlib
    - os

    Example:
    >>> salt, hashed_password = task_func('my_password')
    >>> isinstance(salt, bytes)
    True
    >>> isinstance(hashed_password, bytes)
    True
    """
```

<!-- imported from BigCodeBench (BigCodeBench/24) -->
tests/test_bcb_0024.py
# Auto-generated from BigCodeBench BigCodeBench/24. Do not edit by hand.
import pathlib as _pathlib
exec(_pathlib.Path(__file__).with_name("solution.py").read_text(), globals())

import unittest
import base64
import hashlib
import os
class TestCases(unittest.TestCase):
    def decode_and_regenerate_password(self, encoded_salt, encoded_hashed_password, original_password):
        """ Helper function to decode base64 encoded salt and password, and regenerate the hashed password. """
        decoded_salt = base64.b64decode(encoded_salt)
        decoded_hashed_password = base64.b64decode(encoded_hashed_password)
        regenerated_hashed_password = hashlib.pbkdf2_hmac('sha256', original_password.encode(), decoded_salt, 100000)
        return regenerated_hashed_password, decoded_hashed_password
    def test_case_1(self):
        """ Testing with a simple password """
        salt, hashed_password = task_func('password123')
        self.assertTrue(isinstance(salt, bytes) and isinstance(hashed_password, bytes))
        regenerated, original = self.decode_and_regenerate_password(salt, hashed_password, 'password123')
        self.assertEqual(regenerated, original)
    def test_case_2(self):
        """ Testing with a password containing special characters """
        salt, hashed_password = task_func('p@ssw0rd$%^&*')
        self.assertTrue(isinstance(salt, bytes) and isinstance(hashed_password, bytes))
        regenerated, original = self.decode_and_regenerate_password(salt, hashed_password, 'p@ssw0rd$%^&*')
        self.assertEqual(regenerated, original)
    def test_case_3(self):
        """ Testing with a long password """
        long_password = 'a' * 1000
        salt, hashed_password = task_func(long_password)
        self.assertTrue(isinstance(salt, bytes) and isinstance(hashed_password, bytes))
        regenerated, original = self.decode_and_regenerate_password(salt, hashed_password, long_password)
        self.assertEqual(regenerated, original)
    def test_case_4(self):
        """ Testing with a short password """
        short_password = 'a'
        salt, hashed_password = task_func(short_password)
        self.assertTrue(isinstance(salt, bytes) and isinstance(hashed_password, bytes))
        regenerated, original = self.decode_and_regenerate_password(salt, hashed_password, short_password)
        self.assertEqual(regenerated, original)
    def test_case_5(self):
        """ Testing with a password that is a number """
        number_password = '1234567890'
        salt, hashed_password = task_func(number_password)
        self.assertTrue(isinstance(salt, bytes) and isinstance(hashed_password, bytes))
        regenerated, original = self.decode_and_regenerate_password(salt, hashed_password, number_password)
        self.assertEqual(regenerated, original)
    def test_invalid_input(self):
        """ Testing with invalid input such as None or empty string """
        with self.assertRaises(ValueError):
            task_func(None)
System prompt
You are an expert programmer. Solve the task exactly as specified. Output your solution as fenced code blocks using the required file name(s) and the exact function/type signatures requested. Prefer correctness; do not include prose outside code unless asked.
Proposed solution
```python
import base64
import hashlib
import os

def task_func(password, SALT_LENGTH = 32):
    """
    Hashes a password using the PBKDF2 HMAC algorithm with SHA-256 as the hashing algorithm, 
    combined with a randomly generated salt, and returns both the salt and the hashed password, 
    each base64-encoded.

    Parameters:
    password (str): The password to be hashed.
    SALT_LENGTH (int): the length of the randomly generated salt.

    Returns:
    tuple[bytes, bytes]: A tuple containing the base64-encoded salt and the base64-encoded hashed password as byte strings.

    Raises:
    ValueError if the password is None or empty

    Requirements:
    - base64
    - hashlib
    - os

    Example:
    >>> salt, hashed_password = task_func('my_password')
    >>> isinstance(salt, bytes)
    True
    >>> isinstance(hashed_password, bytes)
    True
    """
    if password is None or password == "":
        raise ValueError("Password cannot be None or empty")
    
    # Generate a random salt
    salt = os.urandom(SALT_LENGTH)
    
    # Derive a key using PBKDF2-HMAC-SHA256
    # 100,000 iterations is a standard recommendation for security
    hashed_password = hashlib.pbkdf2_hmac(
        'sha256', 
        password.encode('utf-8'), 
        salt, 
        100000
    )
    
    # Encode salt and hashed password to base64
    salt_b64 = base64.b64encode(salt)
    hashed_password_b64 = base64.b64encode(hashed_password)
    
    return salt_b64, hashed_password_b64
```

Test output (stdout)

......                                                                   [100%]
6 passed in 0.11s