From 780260c3bfc3893608a479a36f589e7a41f84961 Mon Sep 17 00:00:00 2001 From: patyhank Date: Tue, 14 Jun 2022 10:19:48 +0800 Subject: [PATCH] supported 1.19 key authentication --- bot/login.go | 56 ++++++++++++++++++++++++++++++++++++++++------------ bot/mcbot.go | 22 ++++++++++----------- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/bot/login.go b/bot/login.go index 95eaf74..1a1066c 100644 --- a/bot/login.go +++ b/bot/login.go @@ -2,15 +2,19 @@ package bot import ( "bytes" + "crypto" "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/rsa" "crypto/sha1" + "crypto/sha256" "crypto/x509" "encoding/json" + "encoding/pem" "fmt" "github.com/Tnze/go-mc/yggdrasil/userApi" + randN "golang.org/x/exp/rand" "io" "net/http" "strings" @@ -190,19 +194,45 @@ func genEncryptionKeyResponse(shareSecret, publicKey, verifyToken []byte, keyPai err = fmt.Errorf("encryption share secret fail: %v", err) return } + if keyPair != nil { + privateKeyBlock, _ := pem.Decode([]byte(keyPair.KeyPair.PrivateKey)) + privateKey, err := x509.ParsePKCS8PrivateKey(privateKeyBlock.Bytes) + if err != nil { + err = fmt.Errorf("decode user private key fail: %v", err) + return erp, err + } - verifyT, err := rsa.EncryptPKCS1v15(rand.Reader, rsaKey, verifyToken) - if err != nil { - err = fmt.Errorf("encryption verfy tokenfail: %v", err) - return + l := randN.Int63() + var b bytes.Buffer + pk.Long(l).WriteTo(&b) + + key := privateKey.(*rsa.PrivateKey) + hash := sha256.New() + hash.Write(verifyToken) + hash.Write(b.Bytes()) + signedData, err := key.Sign(rand.Reader, hash.Sum(nil), crypto.SHA256) + if err != nil { + err = fmt.Errorf("sign verifyToken fail: %v", err) + return erp, err + } + return pk.Marshal( + 0x01, + pk.ByteArray(cryptPK), + pk.Boolean(false), + pk.Long(l), + pk.ByteArray(signedData), + ), nil + } else { + verifyT, err := rsa.EncryptPKCS1v15(rand.Reader, rsaKey, verifyToken) + if err != nil { + err = fmt.Errorf("encryption verfy tokenfail: %v", err) + return erp, err + } + return pk.Marshal( + 0x01, + pk.ByteArray(cryptPK), + pk.Boolean(true), + pk.ByteArray(verifyT), + ), nil } - - // currently broken - - return pk.Marshal( - 0x01, - pk.ByteArray(cryptPK), - pk.Boolean(true), - pk.ByteArray(verifyT), - ), nil } diff --git a/bot/mcbot.go b/bot/mcbot.go index 0a12bef..ed5e0ee 100644 --- a/bot/mcbot.go +++ b/bot/mcbot.go @@ -6,6 +6,8 @@ package bot import ( "context" + "encoding/base64" + "encoding/pem" "errors" "github.com/Tnze/go-mc/yggdrasil/userApi" "net" @@ -75,6 +77,7 @@ func (c *Client) join(ctx context.Context, d *mcnet.Dialer, addr string) error { // Login Start pair, err := userApi.GetOrFetchKeyPair(c.Auth.AsTk) if err != nil { + // (No Signature) err = c.Conn.WritePacket(pk.Marshal( packetid.LoginStart, pk.String(c.Auth.Name), @@ -84,22 +87,17 @@ func (c *Client) join(ctx context.Context, d *mcnet.Dialer, addr string) error { return LoginErr{"login start (without sig)", err} } } else { - // Login Start (With Signature) (Currently not supported) + // Login Start (With Signature) + block, _ := pem.Decode([]byte(pair.KeyPair.PublicKey)) + sig, _ := base64.StdEncoding.DecodeString(pair.PublicKeySignature) err = c.Conn.WritePacket(pk.Marshal( packetid.LoginStart, pk.String(c.Auth.Name), - pk.Boolean(false), + pk.Boolean(true), + pk.Long(pair.ExpiresAt.UnixMilli()), + pk.ByteArray(block.Bytes), + pk.ByteArray(sig), )) - /* block, _ := pem.Decode([]byte(pair.KeyPair.PublicKey)) - sig, _ := base64.StdEncoding.DecodeString(pair.PublicKeySignature) - err = c.Conn.WritePacket(pk.Marshal( - packetid.LoginStart, - pk.String(c.Auth.Name), - pk.Boolean(true), - pk.Long(pair.ExpiresAt.UnixMilli()), - pk.ByteArray(block.Bytes), - pk.ByteArray(sig), - ))*/ if err != nil { return LoginErr{"login start (with sig)", err} }