@@ -56,6 +56,7 @@ func CalcNativePassword(scramble, password []byte) []byte {
5656 return Xor (scrambleHash , stage1 )
5757}
5858
59+ // Xor hash1 modified in-place with XOR against hash2
5960func Xor (hash1 []byte , hash2 []byte ) []byte {
6061 for i := range hash1 {
6162 hash1 [i ] ^= hash2 [i ]
@@ -64,7 +65,7 @@ func Xor(hash1 []byte, hash2 []byte) []byte {
6465}
6566
6667// hash_stage1 = xor(reply, sha1(public_seed, hash_stage2))
67- func Stage1FromReply (scramble []byte , seed []byte , stage2 []byte ) []byte {
68+ func stage1FromReply (scramble []byte , seed []byte , stage2 []byte ) []byte {
6869 crypt := sha1 .New ()
6970 crypt .Write (seed )
7071 crypt .Write (stage2 )
@@ -75,8 +76,8 @@ func Stage1FromReply(scramble []byte, seed []byte, stage2 []byte) []byte {
7576
7677// FROM vitess.io/vitess/go/mysql/auth_server.go
7778// DecodePasswordHex decodes the standard format used by MySQL
78- // for 4.1 style password hashes. It drops the optionally leading * before
79- // decoding the rest as a hex encoded string.
79+ // Password hashes in the 4.1 format always begin with a * character
80+ // see https://dev.mysql.com/doc/mysql-security-excerpt/5.7/en/password-hashing.html
8081func DecodePasswordHex (hexEncodedPassword string ) ([]byte , error ) {
8182 if hexEncodedPassword [0 ] == '*' {
8283 hexEncodedPassword = hexEncodedPassword [1 :]
@@ -114,7 +115,7 @@ func CompareNativePassword(reply []byte, stored []byte, seed []byte) bool {
114115 }
115116
116117 // hash_stage1 = xor(reply, sha1(public_seed, hash_stage2))
117- stage1 := Stage1FromReply (reply , seed , stored )
118+ stage1 := stage1FromReply (reply , seed , stored )
118119 // andidate_hash2 = sha1(hash_stage1)
119120 crypt := sha1 .New ()
120121 crypt .Write (stage1 )
@@ -146,11 +147,7 @@ func CalcCachingSha2Password(scramble []byte, password []byte) []byte {
146147 crypt .Write (scramble )
147148 message2 := crypt .Sum (nil )
148149
149- for i := range message1 {
150- message1 [i ] ^= message2 [i ]
151- }
152-
153- return message1
150+ return Xor (message1 , message2 )
154151}
155152
156153// Taken from https://github.com/go-sql-driver/mysql/pull/1518
@@ -239,9 +236,7 @@ func hashCrypt256(source, salt string, iterations uint64) (string, error) {
239236 hashInput := []byte (source + salt )
240237 var hash [32 ]byte
241238 for i := uint64 (0 ); i < actualIterations ; i ++ {
242- h := sha256 .New ()
243- h .Write (hashInput )
244- hash = sha256 .Sum256 (h .Sum (nil ))
239+ hash = sha256 .Sum256 (hashInput )
245240 hashInput = hash [:]
246241 }
247242
@@ -275,7 +270,7 @@ func Check256HashingPassword(pwhash []byte, password string) (bool, error) {
275270 return false , err
276271 }
277272
278- return bytes . Equal (pwhash , []byte (newHash )), nil
273+ return subtle . ConstantTimeCompare (pwhash , []byte (newHash )) == 1 , nil
279274}
280275
281276// NewSha256PasswordHash creates a new password hash for sha256_password
0 commit comments