40a80467ce
- util/license_key.go: LicensePayload struct, GenerateEd25519KeyPair, IssueLicenseToken (sign), VerifyLicenseToken (verify offline) - cmd/genkey: one-shot keypair generator with demo sign+verify - config: add Ed25519PublicKey field (LICENSE_ED25519_PUBLIC_KEY env) Token format: base64url(header).base64url(payload).base64url(ed25519-sig) Private key stored in Bitwarden; public key embedded in config/client. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
// genkey generates an Ed25519 keypair for license signing.
|
|
// Run once; store the private key in Bitwarden and set the public key in config.
|
|
//
|
|
// Usage: go run ./cmd/genkey
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/wangjia/jiu/backend/internal/util"
|
|
)
|
|
|
|
func main() {
|
|
priv, pub, err := util.GenerateEd25519KeyPair()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "failed to generate keypair: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Println("=== Ed25519 License Keypair ===")
|
|
fmt.Println()
|
|
fmt.Println("[Bitwarden] Private key (keep secret, never commit):")
|
|
fmt.Println(priv)
|
|
fmt.Println()
|
|
fmt.Println("[Config / LICENSE_ED25519_PUBLIC_KEY] Public key:")
|
|
fmt.Println(pub)
|
|
fmt.Println()
|
|
|
|
// Demo: issue and verify a sample token to confirm the keypair works
|
|
now := time.Now()
|
|
exp := now.Add(30 * 24 * time.Hour).Unix()
|
|
sample := util.LicensePayload{
|
|
ShopID: 1,
|
|
LicenseID: 1,
|
|
Type: "trial",
|
|
IssuedAt: now.Unix(),
|
|
ExpiresAt: &exp,
|
|
MaxDevices: 3,
|
|
}
|
|
token, err := util.IssueLicenseToken(sample, priv)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "demo sign failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
verified, err := util.VerifyLicenseToken(token, pub)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "demo verify failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
out, _ := json.MarshalIndent(verified, "", " ")
|
|
fmt.Println("[Demo] Sample token (30-day trial, shop_id=1):")
|
|
fmt.Println(token)
|
|
fmt.Println()
|
|
fmt.Println("[Demo] Verified payload:")
|
|
fmt.Println(string(out))
|
|
}
|