Skip to content

Commit 5942cc6

Browse files
heavycrystalGustedlance6716
authored
add support for MariaDB ED25519 plugin (#998)
Co-authored-by: Gusted <[email protected]>> Co-authored-by: lance6716 <[email protected]>
1 parent 5fc8c87 commit 5942cc6

File tree

5 files changed

+55
-2
lines changed

5 files changed

+55
-2
lines changed

client/auth.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
const defaultAuthPluginName = mysql.AUTH_NATIVE_PASSWORD
1616

1717
// defines the supported auth plugins
18-
var supportedAuthPlugins = []string{mysql.AUTH_NATIVE_PASSWORD, mysql.AUTH_SHA256_PASSWORD, mysql.AUTH_CACHING_SHA2_PASSWORD}
18+
var supportedAuthPlugins = []string{mysql.AUTH_NATIVE_PASSWORD, mysql.AUTH_SHA256_PASSWORD, mysql.AUTH_CACHING_SHA2_PASSWORD, mysql.AUTH_MARIADB_ED25519}
1919

2020
// helper function to determine what auth methods are allowed by this client
2121
func authPluginAllowed(pluginName string) bool {
@@ -172,6 +172,15 @@ func (c *Conn) genAuthResponse(authData []byte) ([]byte, bool, error) {
172172
// see: https://dev.mysql.com/doc/internals/en/public-key-retrieval.html
173173
return []byte{1}, false, nil
174174
}
175+
case mysql.AUTH_MARIADB_ED25519:
176+
if len(authData) != 32 {
177+
return nil, false, mysql.ErrMalformPacket
178+
}
179+
res, err := mysql.CalcEd25519Password(authData, c.password)
180+
if err != nil {
181+
return nil, false, err
182+
}
183+
return res, false, nil
175184
default:
176185
// not reachable
177186
return nil, false, fmt.Errorf("auth plugin '%s' is not supported", c.authPluginName)
@@ -195,7 +204,7 @@ func (c *Conn) genAttributes() []byte {
195204
// See: http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
196205
func (c *Conn) writeAuthHandshake() error {
197206
if !authPluginAllowed(c.authPluginName) {
198-
return fmt.Errorf("unknow auth plugin name '%s'", c.authPluginName)
207+
return fmt.Errorf("unknown auth plugin name '%s'", c.authPluginName)
199208
}
200209

201210
// Set default client capabilities that reflect the abilities of this library

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ require (
2020
)
2121

2222
require (
23+
filippo.io/edwards25519 v1.1.0 // indirect
2324
github.com/davecgh/go-spew v1.1.1 // indirect
2425
github.com/kr/pretty v0.3.1 // indirect
2526
github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
2+
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
13
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
24
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
35
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=

mysql/const.go

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const (
2424
AUTH_CLEAR_PASSWORD = "mysql_clear_password"
2525
AUTH_CACHING_SHA2_PASSWORD = "caching_sha2_password"
2626
AUTH_SHA256_PASSWORD = "sha256_password"
27+
AUTH_MARIADB_ED25519 = "client_ed25519"
2728
)
2829

2930
// SERVER_STATUS_flags_enum

mysql/util.go

+40
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"crypto/rsa"
88
"crypto/sha1"
99
"crypto/sha256"
10+
"crypto/sha512"
1011
"encoding/binary"
1112
"fmt"
1213
"io"
@@ -15,6 +16,7 @@ import (
1516
"strings"
1617
"time"
1718

19+
"filippo.io/edwards25519"
1820
"github.com/Masterminds/semver"
1921
"github.com/go-mysql-org/go-mysql/utils"
2022
"github.com/pingcap/errors"
@@ -83,6 +85,44 @@ func CalcCachingSha2Password(scramble []byte, password string) []byte {
8385
return message1
8486
}
8587

88+
// Taken from https://github.com/go-sql-driver/mysql/pull/1518
89+
func CalcEd25519Password(scramble []byte, password string) ([]byte, error) {
90+
// Derived from https://github.com/MariaDB/server/blob/d8e6bb00888b1f82c031938f4c8ac5d97f6874c3/plugin/auth_ed25519/ref10/sign.c
91+
// Code style is from https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:src/crypto/ed25519/ed25519.go;l=207
92+
h := sha512.Sum512([]byte(password))
93+
94+
s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
95+
if err != nil {
96+
return nil, err
97+
}
98+
A := (&edwards25519.Point{}).ScalarBaseMult(s)
99+
100+
mh := sha512.New()
101+
mh.Write(h[32:])
102+
mh.Write(scramble)
103+
messageDigest := mh.Sum(nil)
104+
r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest)
105+
if err != nil {
106+
return nil, err
107+
}
108+
109+
R := (&edwards25519.Point{}).ScalarBaseMult(r)
110+
111+
kh := sha512.New()
112+
kh.Write(R.Bytes())
113+
kh.Write(A.Bytes())
114+
kh.Write(scramble)
115+
hramDigest := kh.Sum(nil)
116+
k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest)
117+
if err != nil {
118+
return nil, err
119+
}
120+
121+
S := k.MultiplyAdd(k, s, r)
122+
123+
return append(R.Bytes(), S.Bytes()...), nil
124+
}
125+
86126
func EncryptPassword(password string, seed []byte, pub *rsa.PublicKey) ([]byte, error) {
87127
plain := make([]byte, len(password)+1)
88128
copy(plain, password)

0 commit comments

Comments
 (0)