将WordPress密码存储函数转换为Python的问题求助
WordPress密码哈希Python实现问题
三周前我在Stack Overflow上发布了一个问题,想弄清楚WordPress是怎么把密码存储到数据库里的。有人建议我去看源码,我尝试了但不太懂PHP,所以正在把相关函数转换成Python代码。以下是我目前的进展:
我的Python代码
import base64 from email.encoders import encode_base64 from hashlib import md5 prefix = '$P$B' salt = 'KcFRBGXE' password = '^zVw*wSFshV2' # 登录时输入的密码 real_hashed_pass = '$P$BKcFRBGXEWOVYQShBC1edT7f3e3Nca1' # WordPress数据库中存储的哈希值 hashed_pass = md5((salt + password).encode('utf-8')).hexdigest() for i in range(8193): hashed_pass = md5((hashed_pass + password).encode('utf-8')).hexdigest() # for i in range(17): # hashed_pass = base64.standard_b64encode(hashed_pass) hashed_pass = prefix + salt + hashed_pass print(hashed_pass == real_hashed_pass)
WordPress相关PHP代码
<?php class PasswordHash { var $itoa64; var $iteration_count_log2; var $portable_hashes; var $random_state; function __construct($iteration_count_log2, $portable_hashes) { $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) $iteration_count_log2 = 8; $this->iteration_count_log2 = $iteration_count_log2; $this->portable_hashes = $portable_hashes; $this->random_state = microtime(); if (function_exists('getmypid')) $this->random_state .= getmypid(); } function encode64($input, $count) { $output = ''; $i = 0; do { $value = ord($input[$i++]); $output .= $this->itoa64[$value & 0x3f]; if ($i < $count) $value |= ord($input[$i]) << 8; $output .= $this->itoa64[($value >> 6) & 0x3f]; if ($i++ >= $count) break; if ($i < $count) $value |= ord($input[$i]) << 16; $output .= $this->itoa64[($value >> 12) & 0x3f]; if ($i++ >= $count) break; $output .= $this->itoa64[($value >> 18) & 0x3f]; } while ($i < $count); return $output; } function crypt_private($password, $setting) { $output = '*0'; if (substr($setting, 0, 2) === $output) $output = '*1'; $id = substr($setting, 0, 3); # 我们用"$P$",phpBB3用"$H$"表示同样的东西 if ($id !== '$P$' && $id !== '$H$') return $output; $count_log2 = strpos($this->itoa64, $setting[3]); if ($count_log2 < 7 || $count_log2 > 30) return $output; $count = 1 << $count_log2; $salt = substr($setting, 4, 8); if (strlen($salt) !== 8) return $output; # 我们不得不使用MD5,因为它是所有在用PHP版本都支持的唯一加密原语。 # 在PHP中实现自己的底层加密会导致性能大幅下降,进而降低迭代次数, # 使得哈希更容易被非PHP代码破解。 $hash = md5($salt . $password, TRUE); do { $hash = md5($hash . $password, TRUE); } while (--$count); $output = substr($setting, 0, 12); $output .= $this->encode64($hash, 16); return $output; } function CheckPassword($password, $stored_hash) { if ( strlen( $password ) > 4096 ) { return false; } $hash = $this->crypt_private($password, $stored_hash); if ($hash[0] === '*') $hash = crypt($password, $stored_hash); # 这不是恒定时间比较。为了保持代码简洁,我们目前依赖盐值的不可预测性来保证时序安全, # 至少在非回退情况下(即使用/dev/urandom和bcrypt时)是这样的。 return $hash === $stored_hash; } }
我的目标是让Python代码生成和WordPress代码完全一致的哈希密码。我觉得问题出在被注释掉的循环部分,但不知道该怎么修复。
感谢帮忙!
内容的提问来源于stack exchange,提问作者SaltyBoy
相关产品推荐
相关产品推荐

