как заставить mkpasswd и python hashlib.pbkdf2 выдавать один и тот же результат (т.Е. производный ключ)

#python #linux #hash #openssl #pbkdf2

#python #linux #хэш #openssl #pbkdf2

Вопрос:

Я обнаружил, что mkpasswd и openssl passwd (с одной стороны) не выдают тот же «производный ключ», что и python hashlib.pbkdf2_hmac() и mbedtls.pbkdf2 (с другой стороны), хотя оба утверждают, что реализуют один и тот же стандарт (PBKDF2).

Я пытаюсь вычислить хэши паролей Linux во встроенной системе. Я использую библиотеку mbedtls, которая имеет функцию: mbedtls_pkcs5_pbkdf2_hmac() . С теми же параметрами: SHA256, 5000 раундов, ‘TestPasswort’ и ‘SALTsaltSALTsalt’ я могу воспроизвести результат с помощью pythons hashlib:

 $ python3
>>> import hashlib
>>> dk = hashlib.pbkdf2_hmac('sha256', b'TestPasswort' , b'SALTsaltSALTsalt', 5000)
>>> dk.hex()
'c27f613f2c4515136f5741a6b80f2fd05c4e3070ab03cb588be842afff6263fe'
 

В качестве второго шага я запускаю результат (32 байта) через модифицированный кодировщик base64 (см. Ссылку ниже).
Конечный результат:
kbxVDml33FBjJo4ai.wjo3lCA50f.whMWyV0fzxWMzs

С другой стороны, mkpasswd и openssl выдают разные результаты (но согласуются между собой):

 mkpasswd -m sha-256 -R 5000 --salt=SALTsaltSALTsalt TestPasswort
$5$rounds=5000$SALTsaltSALTsalt$NEAgjfoV3kysMtvGP0sS8D0LU9hZlXRnx/g4zn7QPb/

openssl passwd -5  --salt=SALTsaltSALTsalt TestPasswort
$5$SALTsaltSALTsalt$NEAgjfoV3kysMtvGP0sS8D0LU9hZlXRnx/g4zn7QPb/
 

Однако:

 kbxVDml33FBjJo4ai.wjo3lCA50f.whMWyV0fzxWMzs         
 

и:

 NEAgjfoV3kysMtvGP0sS8D0LU9hZlXRnx/g4zn7QPb/
 

явно разные.

Я делаю здесь простую ошибку? Как я могу заставить python hashlib.pbkdf2 и openssl passwd выдавать один и тот же результат или, по крайней мере, сопоставлять их?

————для ссылки мой модифицированный кодировщик base64:——————-

 #!/bin/python3
ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
digits = '0123456789'
##note the difference to base64 here:
base64_alphabet = './'   digits   ascii_uppercase   ascii_lowercase     

to_encode = input("base64 encoder ->  ")

chunks_8bit = ''
for bits in to_encode   :
    y = int(bits,16)
    chunks_8bit = chunks_8bit format(y,'04b')

chunks_6bit = [chunks_8bit[bits:bits 6] for bits in range(0,len(chunks_8bit),6)]
padding_amount = ( 6 - len(chunks_6bit[len(chunks_6bit)-1]) )
chunks_6bit[len(chunks_6bit)-1]  = padding_amount * '0'

encoded = ''.join([base64_alphabet[int(bits,2)] for bits in chunks_6bit])
print('Base64 encoded version of {to_encode} is: {result}'.format(to_encode = to_encode,    result = encoded))`
 

Ответ №1:

Я сам нашел ответ: openssl passwd и mkpasswd не реализуют PBKDF2, но: sha-crypt; см., Например, Здесь: https://code.woboq.org/userspace/glibc/crypt/sha256-crypt.c.html и вот здесь: https://www.akkadia.org/drepper/SHA-crypt.txt

Базовый алгоритм тот же, т.Е. Повторное применение хэш-функции, например, sha-256. Поэтому я был введен в заблуждение, полагая, что sha256-crypt будет реализовывать PBKDF2 с sha256 в качестве хэш-функции.