Add a Go HTTP API with Ed25519 auth and invitation onboarding, user-scoped GeoJSON Point management, a Bun-tested @noble/ed25519 TypeScript client, static Vue/Vuetify frontend integration, and a Gitea CI workflow running both Go and Bun test suites. Made-with: Cursor
45 lines
1.1 KiB
Go
45 lines
1.1 KiB
Go
package auth
|
|
|
|
import (
|
|
"crypto/ed25519"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
func NewRandomToken(byteLen int) (string, error) {
|
|
if byteLen <= 0 {
|
|
return "", errors.New("byteLen must be greater than zero")
|
|
}
|
|
|
|
b := make([]byte, byteLen)
|
|
if _, err := rand.Read(b); err != nil {
|
|
return "", fmt.Errorf("read random bytes: %w", err)
|
|
}
|
|
return base64.RawURLEncoding.EncodeToString(b), nil
|
|
}
|
|
|
|
func VerifySignature(publicKeyBase64, message, signatureBase64 string) error {
|
|
pubBytes, err := base64.RawURLEncoding.DecodeString(publicKeyBase64)
|
|
if err != nil {
|
|
return fmt.Errorf("decode public key: %w", err)
|
|
}
|
|
if len(pubBytes) != ed25519.PublicKeySize {
|
|
return errors.New("invalid public key length")
|
|
}
|
|
|
|
sigBytes, err := base64.RawURLEncoding.DecodeString(signatureBase64)
|
|
if err != nil {
|
|
return fmt.Errorf("decode signature: %w", err)
|
|
}
|
|
if len(sigBytes) != ed25519.SignatureSize {
|
|
return errors.New("invalid signature length")
|
|
}
|
|
|
|
if !ed25519.Verify(ed25519.PublicKey(pubBytes), []byte(message), sigBytes) {
|
|
return errors.New("signature verification failed")
|
|
}
|
|
return nil
|
|
}
|