@@ -56,6 +56,7 @@ func CalcNativePassword(scramble, password []byte) []byte {
56
56
return Xor (scrambleHash , stage1 )
57
57
}
58
58
59
+ // Xor hash1 modified in-place with XOR against hash2
59
60
func Xor (hash1 []byte , hash2 []byte ) []byte {
60
61
for i := range hash1 {
61
62
hash1 [i ] ^= hash2 [i ]
@@ -64,7 +65,7 @@ func Xor(hash1 []byte, hash2 []byte) []byte {
64
65
}
65
66
66
67
// 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 {
68
69
crypt := sha1 .New ()
69
70
crypt .Write (seed )
70
71
crypt .Write (stage2 )
@@ -75,8 +76,8 @@ func Stage1FromReply(scramble []byte, seed []byte, stage2 []byte) []byte {
75
76
76
77
// FROM vitess.io/vitess/go/mysql/auth_server.go
77
78
// 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
80
81
func DecodePasswordHex (hexEncodedPassword string ) ([]byte , error ) {
81
82
if hexEncodedPassword [0 ] == '*' {
82
83
hexEncodedPassword = hexEncodedPassword [1 :]
@@ -114,7 +115,7 @@ func CompareNativePassword(reply []byte, stored []byte, seed []byte) bool {
114
115
}
115
116
116
117
// hash_stage1 = xor(reply, sha1(public_seed, hash_stage2))
117
- stage1 := Stage1FromReply (reply , seed , stored )
118
+ stage1 := stage1FromReply (reply , seed , stored )
118
119
// andidate_hash2 = sha1(hash_stage1)
119
120
crypt := sha1 .New ()
120
121
crypt .Write (stage1 )
@@ -146,11 +147,7 @@ func CalcCachingSha2Password(scramble []byte, password []byte) []byte {
146
147
crypt .Write (scramble )
147
148
message2 := crypt .Sum (nil )
148
149
149
- for i := range message1 {
150
- message1 [i ] ^= message2 [i ]
151
- }
152
-
153
- return message1
150
+ return Xor (message1 , message2 )
154
151
}
155
152
156
153
// Taken from https://github.com/go-sql-driver/mysql/pull/1518
@@ -239,9 +236,7 @@ func hashCrypt256(source, salt string, iterations uint64) (string, error) {
239
236
hashInput := []byte (source + salt )
240
237
var hash [32 ]byte
241
238
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 )
245
240
hashInput = hash [:]
246
241
}
247
242
@@ -275,7 +270,7 @@ func Check256HashingPassword(pwhash []byte, password string) (bool, error) {
275
270
return false , err
276
271
}
277
272
278
- return bytes . Equal (pwhash , []byte (newHash )), nil
273
+ return subtle . ConstantTimeCompare (pwhash , []byte (newHash )) == 1 , nil
279
274
}
280
275
281
276
// NewSha256PasswordHash creates a new password hash for sha256_password
0 commit comments