@@ -814,6 +814,32 @@ function verify_hash($hash, $password) {
814814 $ hash = $ components [4 ];
815815 return hash_equals (hash_pbkdf2 ('sha1 ' , $ password , $ salt , $ rounds ), $ hash );
816816
817+ case "PBKDF2-SHA512 " :
818+ // Handle FreeIPA-style hash: {PBKDF2-SHA512}10000$<base64_salt>$<base64_hash>
819+ $ components = explode ('$ ' , $ hash );
820+ if (count ($ components ) !== 3 ) return false ;
821+
822+ // 1st part: iteration count (integer)
823+ $ iterations = intval ($ components [0 ]);
824+ if ($ iterations <= 0 ) return false ;
825+
826+ // 2nd part: salt (base64-encoded)
827+ $ salt = $ components [1 ];
828+ // 3rd part: hash (base64-encoded)
829+ $ stored_hash_b64 = $ components [2 ];
830+
831+ // Decode salt and hash from base64
832+ $ salt_bin = base64_decode ($ salt , true );
833+ $ hash_bin = base64_decode ($ stored_hash_b64 , true );
834+ if ($ salt_bin === false || $ hash_bin === false ) return false ;
835+ // Get length of hash in bytes
836+ $ hash_len = strlen ($ hash_bin );
837+ if ($ hash_len === 0 ) return false ;
838+
839+ // Calculate PBKDF2-SHA512 hash for provided password
840+ $ test_hash = hash_pbkdf2 ('sha512 ' , $ password , $ salt_bin , $ iterations , $ hash_len , true );
841+ return hash_equals ($ hash_bin , $ test_hash );
842+
817843 case "PLAIN-MD4 " :
818844 return hash_equals (hash ('md4 ' , $ password ), $ hash );
819845
0 commit comments