forked from Tnze/go-mc
-
Notifications
You must be signed in to change notification settings - Fork 1
/
session.go
93 lines (80 loc) · 2.09 KB
/
session.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package sign
import (
"crypto/sha256"
"encoding/binary"
"io"
"github.com/google/uuid"
"github.com/maxsupermanhd/go-vmc/v762/chat"
pk "github.com/maxsupermanhd/go-vmc/v762/net/packet"
"github.com/maxsupermanhd/go-vmc/v762/yggdrasil/user"
)
type Message struct {
Prev Prev
Signature *Signature
*MessageBody
Unsigned *chat.Message
FilterMask
}
type Prev struct {
Index int
Sender uuid.UUID
Session uuid.UUID
}
type Session struct {
SessionID uuid.UUID
PublicKey user.PublicKey
valid bool
lastMsg *Message
}
func (s Session) WriteTo(w io.Writer) (n int64, err error) {
n1, err := pk.UUID(s.SessionID).WriteTo(w)
if err != nil {
return n1, err
}
n2, err := s.PublicKey.WriteTo(w)
return n1 + n2, err
}
func (s *Session) ReadFrom(r io.Reader) (n int64, err error) {
n1, err := ((*pk.UUID)(&s.SessionID)).ReadFrom(r)
if err != nil {
return n1, err
}
n2, err := s.PublicKey.ReadFrom(r)
return n1 + n2, err
}
func (s *Session) InitValidate() {
s.valid = true
s.lastMsg = nil
}
func (s *Session) VerifyAndUpdate(msg *Message) bool {
s.valid = s.valid && s.verifyHash(msg) && s.verifyChain(msg)
if s.valid {
s.lastMsg = msg
return true
}
return false
}
func (s *Session) verifyHash(msg *Message) bool {
h := sha256.New()
// 1
_ = binary.Write(h, binary.BigEndian, int32(1))
// Prev
_, _ = h.Write(msg.Prev.Sender[:])
_, _ = h.Write(msg.Prev.Session[:])
_ = binary.Write(h, binary.BigEndian, msg.Prev.Index)
// Body
_ = binary.Write(h, binary.BigEndian, msg.Salt)
_ = binary.Write(h, binary.BigEndian, msg.Timestamp.Unix())
content := []byte(msg.PlainMsg)
_ = binary.Write(h, binary.BigEndian, int32(len(content)))
_, _ = h.Write(content)
// Body.LastSeen
_ = binary.Write(h, binary.BigEndian, int32(len(msg.LastSeen)))
for _, v := range msg.LastSeen {
_, _ = h.Write((*v)[:])
}
return s.PublicKey.VerifyMessage(h.Sum(nil), msg.Signature[:]) == nil
}
func (s *Session) verifyChain(msg *Message) bool {
return s.lastMsg != nil && (msg.Prev.Index < s.lastMsg.Prev.Index || msg.Prev.Sender != s.lastMsg.Prev.Sender || msg.Prev.Session != s.lastMsg.Prev.Session)
}