authentication.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package binlog
  2. import (
  3. "bytes"
  4. "crypto/sha1"
  5. "crypto/sha256"
  6. "fmt"
  7. )
  8. type AuthResponsePacket struct {
  9. PacketLength uint64
  10. SequenceID uint64
  11. Status uint64
  12. PluginName string
  13. AuthPluginData *bytes.Buffer
  14. }
  15. func (c *Conn) decodeAuthResponsePacket() (*AuthResponsePacket, error) {
  16. packet := AuthResponsePacket{}
  17. packet.PacketLength = c.getInt(TypeFixedInt, 3)
  18. packet.SequenceID = c.getInt(TypeFixedInt, 1)
  19. packet.Status = c.getInt(TypeFixedInt, 1)
  20. packet.PluginName = c.getString(TypeNullTerminatedString, 0)
  21. packet.AuthPluginData = c.readBytes(20)
  22. err := c.scanner.Err()
  23. if err != nil {
  24. return nil, err
  25. }
  26. return &packet, err
  27. }
  28. func (c *Conn) writeAuthSwitchPacket(ap *AuthResponsePacket) error {
  29. salt := ap.AuthPluginData.Bytes()
  30. password := []byte(c.HandshakeResponse.AuthResponse)
  31. c.authenticate(salt, password)
  32. if c.Flush() != nil {
  33. return c.Flush()
  34. }
  35. return nil
  36. }
  37. func (c *Conn) authenticate(salt []byte, password []byte) {
  38. var ar []byte
  39. salt = salt[:20] // trim null byte from end.
  40. switch c.Handshake.AuthPluginName {
  41. case "mysql_native_password":
  42. ar = c.nativeSha1Auth(salt, password)
  43. case "caching_sha2_password":
  44. fmt.Println(len(salt))
  45. ar = c.cachingSha2Auth(salt, password)
  46. }
  47. hr := c.HandshakeResponse
  48. hr.AuthResponseLength = uint64(len(ar))
  49. if hr.ClientFlag.PluginAuthLenEncClientData {
  50. c.putInt(TypeLenEncInt, hr.AuthResponseLength, 0)
  51. c.putBytes(ar)
  52. } else if hr.ClientFlag.SecureConnection {
  53. c.putInt(TypeFixedInt, hr.AuthResponseLength, 1)
  54. c.putBytes(ar)
  55. } else {
  56. c.putString(TypeNullTerminatedString, string(ar))
  57. }
  58. }
  59. func (c *Conn) nativeSha1Auth(salt []byte, password []byte) []byte {
  60. pHash := c.sha1Hash(password)
  61. pHashHash := c.sha1Hash(pHash)
  62. spHash := c.sha1Hash(append(salt, pHashHash...))
  63. for i := range pHash {
  64. pHash[i] ^= spHash[i]
  65. }
  66. return pHash
  67. }
  68. func (c *Conn) cachingSha2Auth(salt []byte, password []byte) []byte {
  69. if len(password) < 1 {
  70. return nil
  71. }
  72. pHash := c.sha256Hash(password)
  73. pHashHash := c.sha256Hash(pHash)
  74. pHashHashHash := c.sha256Hash(pHashHash)
  75. authData := c.sha256Hash(append(pHashHashHash, salt...))
  76. for i := range pHash {
  77. pHash[i] ^= authData[i]
  78. }
  79. return pHash
  80. }
  81. func (c *Conn) sha1Hash(word []byte) []byte {
  82. s := sha1.New()
  83. s.Write(word)
  84. return s.Sum(nil)
  85. }
  86. func (c *Conn) sha256Hash(word []byte) []byte {
  87. s := sha256.New()
  88. s.Write(word)
  89. return s.Sum(nil)
  90. }