簡體   English   中英

為什么在 python 和 php 上使用加鹽的 hash 會給我不同的結果?

[英]Why does using salted hash on python and php give me different results?

我在將代碼從 PHP 轉換為 Python 時遇到了問題。最初,有一個 PHP 代碼創建了經過驗證的加鹽 hash 密碼,並且該代碼工作正常並執行其功能。 但是我需要將此代碼傳輸到 python。但是,最終生成的 hash 與在 PHP 上獲得的代碼不匹配。請幫助我。

這是工作正常的 PHP 代碼:

<?php
$username = 'test';
$password = '1234';
$salt = '5CD6A52E4F7046241C1607233395461D69D8C21709DD661FA1E9A24C8DF39647';

$g = gmp_init(7);
$N = gmp_init('894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7', 16);

$h1 = sha1(strtoupper($username . ':' . $password), TRUE);
$h2 = sha1($salt . $h1, TRUE);
$h2 = gmp_import($h2, 1, GMP_LSW_FIRST);

// g^h2 mod N
$verifier = gmp_powm($g, $h2, $N);

// convert back to a byte array (little-endian)
$verifier = gmp_export($verifier, 1, GMP_LSW_FIRST);

// pad to 32 bytes, remember that zeros go on the end in little-endian!
$verifier = str_pad($verifier, 32, chr(0), STR_PAD_RIGHT);

ECHO 'Verifier FINAL ', $verifier;
?>

這是我堅持使用的 python 代碼,它不會產生正確的 hash:

import hashlib
import secrets
import sys

USERNAME = 'test'
PASSWORD = '1234'
salt = '5CD6A52E4F7046241C1607233395461D69D8C21709DD661FA1E9A24C8DF39647'

g = 7
N = '894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7'

N = int('{0:08b}'.format(int(N, 16)), 2)

h1 = str(hashlib.sha1(str((USERNAME + ':' + PASSWORD).upper()).encode('utf-8')).hexdigest())
h2 = str(hashlib.sha1(str(salt + h1).encode('utf-8')).hexdigest())
h2 = int('{0:08b}'.format(int(h2, 16)), 2)

verifier = pow(g, h2, N)
verifier = format(verifier, "x").upper()
verifier = verifier.ljust(64, '0')

print('Verifier FINAL : ', verifier)
print('Verifier should be: E08847151054CB20CCD00A546A85D9A4E6EB882EDAB678DD8C68BB28DA22C678')

就是這樣,我設法完全編寫了一個用於生成哈希並檢查它們的庫。

import hashlib
import secrets

ACCOUNT_NAME = 'MyTestLogin'
ACCOUNT_PASSWORD = 'MyTestPassword'

def calculateSRP6Verifier(ACCOUNT_NAME: str, ACCOUNT_PASSWORD: str, SALT: str):
    g = int(7)
    N = int('894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7', 16)
    h1 = bytes.fromhex(hashlib.sha1(((ACCOUNT_NAME + ':' + ACCOUNT_PASSWORD).upper()).encode()).hexdigest())
    h2 = int(bytes.fromhex(hashlib.sha1(bytes.fromhex(SALT) + h1).hexdigest())[::-1].hex(), 16)
    VERIFIER = bytes.fromhex(format(pow(g, h2, N), 'X').ljust(64, '0'))[::-1].hex().upper()
    return VERIFIER

def getRegistrationData(ACCOUNT_NAME: str, ACCOUNT_PASSWORD: str):
    SALT = secrets.token_hex(32)
    VERIFIER = calculateSRP6Verifier(ACCOUNT_NAME, ACCOUNT_PASSWORD, SALT)
    return SALT.upper(), VERIFIER

def verifySRP6(ACCOUNT_NAME: str, ACCOUNT_PASSWORD: str, SALT: str, VERIFIER: str):
    g = int(7)
    N = int('894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7', 16)
    x = int(bytes.fromhex(hashlib.sha1(bytes.fromhex(SALT) + bytes.fromhex(hashlib.sha1(((ACCOUNT_NAME + ':' + ACCOUNT_PASSWORD).upper()).encode()).hexdigest())).hexdigest())[::-1].hex(), 16)
    VERIFIER = bytes.fromhex(format(pow(g, x, N), "X").ljust(64, '0'))[::-1].hex().upper()
    return VERIFIER
    
RESULT = getRegistrationData(ACCOUNT_NAME, ACCOUNT_PASSWORD)
print('This is SRP6 crypto library for Trinity Core 335a World of Warcraft server.')
print('')
print('Login   : ' + ACCOUNT_NAME)
print('Password: ' + ACCOUNT_PASSWORD)
print('')
print('salt    : ' + RESULT[0])
print('verifier: ' + RESULT[1])

# Note, that SALT and VERIFIER saved to the database as a binary string (not as hexadecimal, that returned from getRegistrationData() function)!
# Therefore, when inserting data into the MySQL database, you need to use such a query:
sql = "INSERT INTO account (username, salt, verifier, email) VALUES ('" + ACCOUNT_NAME.upper() + "', X'" + SALT + "', X'" + VERIFIER + "', '" + ACCOUNT_EMAIL.upper() + "')"



# This is simple example, how registration data is being verified.
#
#CODE - is return from verifySRP6() function
#VERIFIER and SALT - saved data from the MySQL database, from account table, converted from binary to hexadecimal string in upper() mode.
# MySQL query must be:
#    cursor.execute("SELECT salt FROM account WHERE username = '" + ACCOUNT_NAME.upper() + "'")
#    SALT = (cursor.fetchone()['salt']).hex().upper()
#    cursor.execute("SELECT verifier FROM account WHERE username = '" + ACCOUNT_NAME.upper() + "'")
#    VERIFIER = (cursor.fetchone()['verifier']).hex().upper()
#
#
#CODE = verifySRP6(ACCOUNT_NAME, ACCOUNT_PASSWORD, SALT, VERIFIER)
#print('check   :', CODE)
#if(VERIFIER == CODE):
#    print('Password is OK!')
#else:
#    print('Wrong password!')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM