implement messages and operations for FIND
This commit is contained in:
283
cmd/find/main.go
Normal file
283
cmd/find/main.go
Normal file
@@ -0,0 +1,283 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"next.orly.dev/pkg/crypto/keys"
|
||||
"next.orly.dev/pkg/encoders/hex"
|
||||
"next.orly.dev/pkg/find"
|
||||
"next.orly.dev/pkg/interfaces/signer"
|
||||
"next.orly.dev/pkg/interfaces/signer/p8k"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
printUsage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
command := os.Args[1]
|
||||
|
||||
switch command {
|
||||
case "register":
|
||||
handleRegister()
|
||||
case "transfer":
|
||||
handleTransfer()
|
||||
case "verify-name":
|
||||
handleVerifyName()
|
||||
case "generate-key":
|
||||
handleGenerateKey()
|
||||
case "issue-cert":
|
||||
handleIssueCert()
|
||||
case "help":
|
||||
printUsage()
|
||||
default:
|
||||
fmt.Printf("Unknown command: %s\n\n", command)
|
||||
printUsage()
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func printUsage() {
|
||||
fmt.Println("FIND - Free Internet Name Daemon")
|
||||
fmt.Println("Usage: find <command> [options]")
|
||||
fmt.Println()
|
||||
fmt.Println("Commands:")
|
||||
fmt.Println(" register <name> Create a registration proposal for a name")
|
||||
fmt.Println(" transfer <name> <new-owner> Transfer a name to a new owner")
|
||||
fmt.Println(" verify-name <name> Validate a name format")
|
||||
fmt.Println(" generate-key Generate a new key pair")
|
||||
fmt.Println(" issue-cert <name> Issue a certificate for a name")
|
||||
fmt.Println(" help Show this help message")
|
||||
fmt.Println()
|
||||
fmt.Println("Examples:")
|
||||
fmt.Println(" find verify-name example.com")
|
||||
fmt.Println(" find register myname.nostr")
|
||||
fmt.Println(" find generate-key")
|
||||
}
|
||||
|
||||
func handleRegister() {
|
||||
if len(os.Args) < 3 {
|
||||
fmt.Println("Usage: find register <name>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
name := os.Args[2]
|
||||
|
||||
// Validate the name
|
||||
if err := find.ValidateName(name); err != nil {
|
||||
fmt.Printf("Invalid name: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Generate a key pair for this example
|
||||
// In production, this would load from a secure keystore
|
||||
signer, err := p8k.New()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to create signer: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := signer.Generate(); err != nil {
|
||||
fmt.Printf("Failed to generate key: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Create registration proposal
|
||||
proposal, err := find.NewRegistrationProposal(name, find.ActionRegister, signer)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to create proposal: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Registration Proposal Created\n")
|
||||
fmt.Printf("==============================\n")
|
||||
fmt.Printf("Name: %s\n", name)
|
||||
fmt.Printf("Pubkey: %s\n", hex.Enc(signer.Pub()))
|
||||
fmt.Printf("Event ID: %s\n", hex.Enc(proposal.GetIDBytes()))
|
||||
fmt.Printf("Kind: %d\n", proposal.Kind)
|
||||
fmt.Printf("Created At: %s\n", time.Unix(proposal.CreatedAt, 0))
|
||||
fmt.Printf("\nEvent JSON:\n")
|
||||
json := proposal.Marshal(nil)
|
||||
fmt.Println(string(json))
|
||||
}
|
||||
|
||||
func handleTransfer() {
|
||||
if len(os.Args) < 4 {
|
||||
fmt.Println("Usage: find transfer <name> <new-owner-pubkey>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
name := os.Args[2]
|
||||
newOwnerPubkey := os.Args[3]
|
||||
|
||||
// Validate the name
|
||||
if err := find.ValidateName(name); err != nil {
|
||||
fmt.Printf("Invalid name: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Generate current owner key (in production, load from keystore)
|
||||
currentOwner, err := p8k.New()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to create current owner signer: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := currentOwner.Generate(); err != nil {
|
||||
fmt.Printf("Failed to generate current owner key: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Authorize the transfer
|
||||
prevSig, timestamp, err := find.AuthorizeTransfer(name, newOwnerPubkey, currentOwner)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to authorize transfer: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Transfer Authorization Created\n")
|
||||
fmt.Printf("===============================\n")
|
||||
fmt.Printf("Name: %s\n", name)
|
||||
fmt.Printf("Current Owner: %s\n", hex.Enc(currentOwner.Pub()))
|
||||
fmt.Printf("New Owner: %s\n", newOwnerPubkey)
|
||||
fmt.Printf("Timestamp: %s\n", timestamp)
|
||||
fmt.Printf("Signature: %s\n", prevSig)
|
||||
fmt.Printf("\nTo complete the transfer, the new owner must create a proposal with:")
|
||||
fmt.Printf(" prev_owner: %s\n", hex.Enc(currentOwner.Pub()))
|
||||
fmt.Printf(" prev_sig: %s\n", prevSig)
|
||||
}
|
||||
|
||||
func handleVerifyName() {
|
||||
if len(os.Args) < 3 {
|
||||
fmt.Println("Usage: find verify-name <name>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
name := os.Args[2]
|
||||
|
||||
// Validate the name
|
||||
if err := find.ValidateName(name); err != nil {
|
||||
fmt.Printf("❌ Invalid name: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
normalized := find.NormalizeName(name)
|
||||
isTLD := find.IsTLD(normalized)
|
||||
parent := find.GetParentDomain(normalized)
|
||||
|
||||
fmt.Printf("✓ Valid name\n")
|
||||
fmt.Printf("==============\n")
|
||||
fmt.Printf("Original: %s\n", name)
|
||||
fmt.Printf("Normalized: %s\n", normalized)
|
||||
fmt.Printf("Is TLD: %v\n", isTLD)
|
||||
if parent != "" {
|
||||
fmt.Printf("Parent: %s\n", parent)
|
||||
}
|
||||
}
|
||||
|
||||
func handleGenerateKey() {
|
||||
// Generate a new key pair
|
||||
secKey, err := keys.GenerateSecretKey()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to generate secret key: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
secKeyHex := hex.Enc(secKey)
|
||||
pubKeyHex, err := keys.GetPublicKeyHex(secKeyHex)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to derive public key: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("New Key Pair Generated")
|
||||
fmt.Println("======================")
|
||||
fmt.Printf("Secret Key (keep safe!): %s\n", secKeyHex)
|
||||
fmt.Printf("Public Key: %s\n", pubKeyHex)
|
||||
fmt.Println()
|
||||
fmt.Println("⚠️ IMPORTANT: Store the secret key securely. Anyone with access to it can control your names.")
|
||||
}
|
||||
|
||||
func handleIssueCert() {
|
||||
if len(os.Args) < 3 {
|
||||
fmt.Println("Usage: find issue-cert <name>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
name := os.Args[2]
|
||||
|
||||
// Validate the name
|
||||
if err := find.ValidateName(name); err != nil {
|
||||
fmt.Printf("Invalid name: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Generate name owner key
|
||||
owner, err := p8k.New()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to create owner signer: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := owner.Generate(); err != nil {
|
||||
fmt.Printf("Failed to generate owner key: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Generate certificate key (different from name owner)
|
||||
certSigner, err := p8k.New()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to create cert signer: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := certSigner.Generate(); err != nil {
|
||||
fmt.Printf("Failed to generate cert key: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
certPubkey := hex.Enc(certSigner.Pub())
|
||||
|
||||
// Generate 3 witness signers (in production, these would be separate services)
|
||||
var witnesses []signer.I
|
||||
for i := 0; i < 3; i++ {
|
||||
witness, err := p8k.New()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to create witness %d: %v\n", i, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := witness.Generate(); err != nil {
|
||||
fmt.Printf("Failed to generate witness %d key: %v\n", i, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
witnesses = append(witnesses, witness)
|
||||
}
|
||||
|
||||
// Issue certificate (90 day validity)
|
||||
cert, err := find.IssueCertificate(name, certPubkey, find.CertificateValidity, owner, witnesses)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to issue certificate: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Certificate Issued\n")
|
||||
fmt.Printf("==================\n")
|
||||
fmt.Printf("Name: %s\n", cert.Name)
|
||||
fmt.Printf("Cert Pubkey: %s\n", cert.CertPubkey)
|
||||
fmt.Printf("Valid From: %s\n", cert.ValidFrom)
|
||||
fmt.Printf("Valid Until: %s\n", cert.ValidUntil)
|
||||
fmt.Printf("Challenge: %s\n", cert.Challenge)
|
||||
fmt.Printf("Witnesses: %d\n", len(cert.Witnesses))
|
||||
fmt.Printf("Algorithm: %s\n", cert.Algorithm)
|
||||
fmt.Printf("Usage: %s\n", cert.Usage)
|
||||
|
||||
fmt.Printf("\nWitness Pubkeys:\n")
|
||||
for i, w := range cert.Witnesses {
|
||||
fmt.Printf(" %d: %s\n", i+1, w.Pubkey)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user