Add HandleDelete and GetSerialsFromFilter methods, integrate admin keys handling, and enhance constraints API. Include a new CLI convert tool for key translation.
This commit is contained in:
143
cmd/convert/convert.go
Normal file
143
cmd/convert/convert.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"crypto.orly/ec/schnorr"
|
||||
"crypto.orly/ec/secp256k1"
|
||||
b32 "encoders.orly/bech32encoding"
|
||||
"encoders.orly/hex"
|
||||
)
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "Usage: convert [--secret] <key>\n")
|
||||
fmt.Fprintf(
|
||||
os.Stderr, " <key> can be hex (64 chars) or bech32 (npub/nsec).\n",
|
||||
)
|
||||
fmt.Fprintf(
|
||||
os.Stderr,
|
||||
" --secret: interpret input key as a secret key; print both nsec and npub in hex and bech32.\n"+
|
||||
" --secret is implied if <key> starts with nsec.\n",
|
||||
)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var isSecret bool
|
||||
flag.BoolVar(
|
||||
&isSecret, "secret", false, "interpret the input as a secret key",
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() < 1 {
|
||||
usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
input := strings.TrimSpace(flag.Arg(0))
|
||||
|
||||
// Auto-detect secret if input starts with nsec
|
||||
if strings.HasPrefix(input, string(b32.SecHRP)) {
|
||||
isSecret = true
|
||||
}
|
||||
|
||||
if isSecret {
|
||||
if err := handleSecret(input); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := handlePublic(input); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func handleSecret(input string) error {
|
||||
// Accept nsec bech32 or 64-char hex as secret key
|
||||
var sk *secp256k1.SecretKey
|
||||
var err error
|
||||
|
||||
if strings.HasPrefix(input, string(b32.SecHRP)) { // nsec...
|
||||
if sk, err = b32.NsecToSecretKey([]byte(input)); err != nil {
|
||||
return fmt.Errorf("failed to decode nsec: %w", err)
|
||||
}
|
||||
} else {
|
||||
// Expect hex
|
||||
if len(input) != b32.HexKeyLen {
|
||||
return fmt.Errorf("secret key hex must be %d chars", b32.HexKeyLen)
|
||||
}
|
||||
var b []byte
|
||||
if b, err = hex.Dec(input); err != nil {
|
||||
return fmt.Errorf("invalid secret hex: %w", err)
|
||||
}
|
||||
sk = secp256k1.SecKeyFromBytes(b)
|
||||
}
|
||||
|
||||
// Prepare outputs for secret
|
||||
nsec, err := b32.SecretKeyToNsec(sk)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode nsec: %w", err)
|
||||
}
|
||||
secHex := hex.EncAppend(nil, sk.Serialize())
|
||||
|
||||
// Derive public key
|
||||
pk := sk.PubKey()
|
||||
npub, err := b32.PublicKeyToNpub(pk)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode npub: %w", err)
|
||||
}
|
||||
pkBytes := schnorr.SerializePubKey(pk)
|
||||
pkHex := hex.EncAppend(nil, pkBytes)
|
||||
|
||||
// Print results
|
||||
fmt.Printf("nsec (hex): %s\n", string(secHex))
|
||||
fmt.Printf("nsec (bech32): %s\n", string(nsec))
|
||||
fmt.Printf("npub (hex): %s\n", string(pkHex))
|
||||
fmt.Printf("npub (bech32): %s\n", string(npub))
|
||||
return nil
|
||||
}
|
||||
|
||||
func handlePublic(input string) error {
|
||||
// Accept npub bech32, nsec bech32 (derive pub), or 64-char hex pubkey
|
||||
var pubBytes []byte
|
||||
var err error
|
||||
|
||||
if strings.HasPrefix(input, string(b32.PubHRP)) { // npub...
|
||||
if pubBytes, err = b32.NpubToBytes([]byte(input)); err != nil {
|
||||
return fmt.Errorf("failed to decode npub: %w", err)
|
||||
}
|
||||
} else if strings.HasPrefix(
|
||||
input, string(b32.SecHRP),
|
||||
) { // nsec without --secret: show pub only
|
||||
var sk *secp256k1.SecretKey
|
||||
if sk, err = b32.NsecToSecretKey([]byte(input)); err != nil {
|
||||
return fmt.Errorf("failed to decode nsec: %w", err)
|
||||
}
|
||||
pubBytes = schnorr.SerializePubKey(sk.PubKey())
|
||||
} else {
|
||||
// Expect hex pubkey
|
||||
if len(input) != b32.HexKeyLen {
|
||||
return fmt.Errorf("public key hex must be %d chars", b32.HexKeyLen)
|
||||
}
|
||||
if pubBytes, err = hex.Dec(input); err != nil {
|
||||
return fmt.Errorf("invalid public hex: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Compute encodings
|
||||
npub, err := b32.BinToNpub(pubBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode npub: %w", err)
|
||||
}
|
||||
pubHex := hex.EncAppend(nil, pubBytes)
|
||||
|
||||
// Print only pubkey representations
|
||||
fmt.Printf("npub (hex): %s\n", string(pubHex))
|
||||
fmt.Printf("npub (bech32): %s\n", string(npub))
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user