Repository: nbd-wtf/go-nostr

Issue:
CheckID panics when event.ID has incorrect lenght.
There is a very nasty problem with `event.CheckID`, that has been exploited in the wild. To reproduce, run the following

```golang
package main

import (
	"github.com/nbd-wtf/go-nostr"
)

func main() {
	bad := nostr.Event{} // same with nostr.Event{ID: "a"}
	bad.CheckID()
}
```
Which produces

```
filippo@pop-os:~/Documents/Vertex/bug-hunt$ go run main.go 
panic: runtime error: index out of range [0] with length 0

goroutine 1 [running]:
github.com/nbd-wtf/go-nostr.(*Event).CheckID(0xc000058ed8)
        /home/filippo/go/pkg/mod/github.com/nbd-wtf/go-nostr@v0.51.6/event.go:42 +0xd5
main.main()
        /home/filippo/Documents/Vertex/bug-hunt/main.go:9 +0x3d
exit status 2
```

The fix requires simply to check the lenght of the event.ID at the beginning, which also improves performance if the ID is malformed.

Just to give more context, my Khatru relay panicked multiple times because of this.
```
Mar 20 00:07:48 vertex relay[2346757]: panic: runtime error: index out of range [0] with length 0
Mar 20 00:07:48 vertex relay[2346757]: goroutine 281 [running]:
Mar 20 00:07:48 vertex relay[2346757]: github.com/nbd-wtf/go-nostr.(*Event).CheckID(0x40002203f8)
Mar 20 00:07:48 vertex relay[2346757]:         /home/admin/go/pkg/mod/github.com/nbd-wtf/go-nostr@v0.49.7/event.go:42 +0xec
Mar 20 00:07:48 vertex relay[2346757]: github.com/fiatjaf/khatru.(*Relay).HandleWebsocket.func2.2({0x4000152600, 0x158, 0x200})
Mar 20 00:07:48 vertex relay[2346757]:         /home/admin/go/pkg/mod/github.com/fiatjaf/khatru@v0.15.0/handlers.go:156 +0xa20
Mar 20 00:07:48 vertex relay[2346757]: created by github.com/fiatjaf/khatru.(*Relay).HandleWebsocket.func2 in goroutine 306
Mar 20 00:07:48 vertex relay[2346757]:         /home/admin/go/pkg/mod/github.com/fiatjaf/khatru@v0.15.0/handlers.go:140 +0x2b4
```

Hints from issue comments:

Solution patch:
diff --git a/event.go b/event.go
index 6d3ebb4..ba8b3e3 100644
--- a/event.go
+++ b/event.go
@@ -8,6 +8,8 @@ import (
 	"github.com/mailru/easyjson"
 )
 
+const hextable = "0123456789abcdef"
+
 // Event represents a Nostr event.
 type Event struct {
 	ID        string
@@ -24,7 +26,7 @@ func (evt Event) String() string {
 	return string(j)
 }
 
-// GetID computes the event ID abd returns it as a hex string.
+// GetID computes the event ID and returns it as a hex string.
 func (evt *Event) GetID() string {
 	h := sha256.Sum256(evt.Serialize())
 	return hex.EncodeToString(h[:])
@@ -32,11 +34,13 @@ func (evt *Event) GetID() string {
 
 // CheckID checks if the implied ID matches the given ID more efficiently.
 func (evt *Event) CheckID() bool {
+	if len(evt.ID) != 64 {
+		return false
+	}
+
 	ser := evt.Serialize()
 	h := sha256.Sum256(ser)
 
-	const hextable = "0123456789abcdef"
-
 	for i := 0; i < 32; i++ {
 		b := hextable[h[i]>>4]
 		if b != evt.ID[i*2] {



Test patch:
diff --git a/event_test.go b/event_test.go
index a9453a1..01b882b 100644
--- a/event_test.go
+++ b/event_test.go
@@ -87,6 +87,9 @@ func TestIDCheck(t *testing.T) {
 			Content:   fmt.Sprintf("hello %d", i),
 			Tags:      Tags{},
 		}
+
+		require.False(t, evt.CheckID())
+
 		evt.Sign(GeneratePrivateKey())
 		require.True(t, evt.CheckID())