package main import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/rsa" "encoding/json" "errors" "fmt" "github.com/Tnze/go-mc/net" pk "github.com/Tnze/go-mc/net/packet" "io" "net/http" "net/url" ) var hasJoinedURL = func() *url.URL { u, err := url.Parse("https://sessionserver.mojang.com/session/minecraft/hasJoined") if err != nil { panic(err) } return u }() func (s *Server) encryptionRequest(conn net.Conn) ([]byte, error) { verify := make([]byte, 4) _, _ = rand.Read(verify) return verify, conn.WritePacket(pk.Marshal(0x01, pk.String(""), pk.ByteArray(s.publicKey), pk.ByteArray(verify), )) } type profile struct { ID string `json:"id"` Name string `json:"name"` } func (p *profile) UUID() string { return fmt.Sprintf("%s-%s-%s-%s-%s", p.ID[:8], p.ID[8:12], p.ID[12:16], p.ID[16:20], p.ID[20:32]) } func (s *Server) encryptionResponse(conn net.Conn, username string, verify []byte) (*profile, []byte, error) { var ( p pk.Packet sharedSecret pk.ByteArray verifyToken pk.ByteArray ) err := conn.ReadPacket(&p) if err != nil { return nil, nil, fmt.Errorf("could not read packet: %w", err) } err = p.Scan(&sharedSecret, &verifyToken) if err != nil { return nil, nil, fmt.Errorf("could not scan packet: %w", err) } valid, err := s.verify(verifyToken, verify) if err != nil || !valid { return nil, nil, errors.New("could not verify token") } secret, err := rsa.DecryptPKCS1v15(rand.Reader, s.privateKey, sharedSecret) if err != nil { return nil, nil, fmt.Errorf("could not decrypt secret: %w", err) } serverID, err := digest(secret, s.publicKey) if err != nil { return nil, nil, fmt.Errorf("could not create digest: %w", err) } u := *hasJoinedURL q := u.Query() q.Set("username", username) q.Set("serverId", serverID) u.RawQuery = q.Encode() res, err := http.Get(u.String()) if err != nil { return nil, nil, fmt.Errorf("could not join server API: %w", err) } defer res.Body.Close() var player profile if err := json.NewDecoder(res.Body).Decode(&player); err != nil { return nil, nil, fmt.Errorf("could not decode profile: %w", err) } return &player, secret, nil } func (s *Server) verify(encryptedVerifyToken, actualVerifyToken []byte) (bool, error) { decryptedVerifyToken, err := rsa.DecryptPKCS1v15(rand.Reader, s.privateKey, encryptedVerifyToken) if err != nil { return false, fmt.Errorf("error decrypting verify token: %v", err) } return bytes.Equal(decryptedVerifyToken, actualVerifyToken), nil } func encryptedConn(conn net.Conn, secret []byte) (io.Writer, error) { block, err := aes.NewCipher(secret) if err != nil { return nil, err } return &cipher.StreamWriter{ S: newCFB8(block, secret, false), W: conn, }, nil }