avoid escaping special characters when serializing events leading to invalid IDs and Sigs

This commit is contained in:
0ceanSlim 2024-09-05 11:58:18 -04:00
parent ca43645ef1
commit 462fa0a4b1

View File

@ -3,70 +3,100 @@ package utils
import ( import (
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"encoding/json" "fmt"
"log" "log"
"strings"
relay "grain/server/types" relay "grain/server/types"
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcec/v2/schnorr"
) )
func SerializeEvent(evt relay.Event) []byte {
eventData := []interface{}{ // SerializeEvent manually constructs the JSON string for event serialization
0, func SerializeEvent(evt relay.Event) string {
// Manually construct the event data as a JSON array string
// Avoid escaping special characters like "&"
return fmt.Sprintf(
`[0,"%s",%d,%d,%s,"%s"]`,
evt.PubKey, evt.PubKey,
evt.CreatedAt, evt.CreatedAt,
evt.Kind, evt.Kind,
evt.Tags, serializeTags(evt.Tags),
evt.Content, evt.Content, // Special characters like "&" are not escaped here
} )
serializedEvent, _ := json.Marshal(eventData)
return serializedEvent
} }
// Helper function to serialize the tags array
func serializeTags(tags [][]string) string {
var tagStrings []string
for _, tag := range tags {
tagStrings = append(tagStrings, fmt.Sprintf(`["%s"]`, strings.Join(tag, `","`)))
}
return "[" + strings.Join(tagStrings, ",") + "]"
}
// CheckSignature verifies the event's signature and ID
func CheckSignature(evt relay.Event) bool { func CheckSignature(evt relay.Event) bool {
// Manually serialize the event
serializedEvent := SerializeEvent(evt) serializedEvent := SerializeEvent(evt)
hash := sha256.Sum256(serializedEvent)
// Compute the SHA-256 hash of the serialized event
hash := sha256.Sum256([]byte(serializedEvent))
eventID := hex.EncodeToString(hash[:]) eventID := hex.EncodeToString(hash[:])
// Log the generated and provided IDs
log.Printf("Generated event ID: %s, Provided event ID: %s", eventID, evt.ID)
// Compare the computed event ID with the one provided by the client
if eventID != evt.ID { if eventID != evt.ID {
log.Printf("Invalid ID: expected %s, got %s\n", eventID, evt.ID) log.Printf("Invalid ID: expected %s, got %s", eventID, evt.ID)
return false return false
} }
// Decode the signature from hex
sigBytes, err := hex.DecodeString(evt.Sig) sigBytes, err := hex.DecodeString(evt.Sig)
if err != nil { if err != nil {
log.Printf("Error decoding signature: %v\n", err) log.Printf("Error decoding signature: %v", err)
return false return false
} }
// Parse the Schnorr signature
sig, err := schnorr.ParseSignature(sigBytes) sig, err := schnorr.ParseSignature(sigBytes)
if err != nil { if err != nil {
log.Printf("Error parsing signature: %v\n", err) log.Printf("Error parsing signature: %v", err)
return false return false
} }
// Decode the public key from hex
pubKeyBytes, err := hex.DecodeString(evt.PubKey) pubKeyBytes, err := hex.DecodeString(evt.PubKey)
if err != nil { if err != nil {
log.Printf("Error decoding public key: %v\n", err) log.Printf("Error decoding public key: %v", err)
return false return false
} }
// Parse the public key based on its length
var pubKey *btcec.PublicKey var pubKey *btcec.PublicKey
if len(pubKeyBytes) == 32 { if len(pubKeyBytes) == 32 {
// Handle 32-byte public key (x-coordinate only) // Handle 32-byte compressed public key (x-coordinate only)
pubKey, err = btcec.ParsePubKey(append([]byte{0x02}, pubKeyBytes...)) pubKey, err = btcec.ParsePubKey(append([]byte{0x02}, pubKeyBytes...))
} else { } else if len(pubKeyBytes) == 33 || len(pubKeyBytes) == 65 {
// Handle standard compressed or uncompressed public key // Handle standard compressed (33-byte) or uncompressed (65-byte) public key
pubKey, err = btcec.ParsePubKey(pubKeyBytes) pubKey, err = btcec.ParsePubKey(pubKeyBytes)
} } else {
if err != nil { log.Printf("Malformed public key: invalid length: %d", len(pubKeyBytes))
log.Printf("Error parsing public key: %v\n", err)
return false return false
} }
if err != nil {
log.Printf("Error parsing public key: %v", err)
return false
}
// Verify the signature using the event's hash and public key
verified := sig.Verify(hash[:], pubKey) verified := sig.Verify(hash[:], pubKey)
if !verified { if !verified {
log.Printf("Signature verification failed for event ID: %s\n", evt.ID) log.Printf("Signature verification failed for event ID: %s", evt.ID)
} }
return verified return verified