1package main
2
3import (
4 "crypto/ecdsa"
5 "crypto/elliptic"
6 "crypto/rand"
7 "encoding/json"
8 "fmt"
9 "os"
10 "time"
11
12 "github.com/bluesky-social/indigo/atproto/crypto"
13 "github.com/lestrrat-go/jwx/v2/jwk"
14 "github.com/urfave/cli/v2"
15)
16
17func main() {
18 app := cli.App{
19 Name: "admin",
20 Commands: cli.Commands{
21 runCreateRotationKey,
22 runCreatePrivateJwk,
23 },
24 ErrWriter: os.Stdout,
25 }
26
27 app.Run(os.Args)
28}
29
30var runCreateRotationKey = &cli.Command{
31 Name: "create-rotation-key",
32 Usage: "creates a rotation key for your pds",
33 Flags: []cli.Flag{
34 &cli.StringFlag{
35 Name: "out",
36 Required: true,
37 Usage: "output file for your rotation key",
38 },
39 },
40 Action: func(cmd *cli.Context) error {
41 key, err := crypto.GeneratePrivateKeyK256()
42 if err != nil {
43 return err
44 }
45
46 bytes := key.Bytes()
47
48 if err := os.WriteFile(cmd.String("out"), bytes, 0644); err != nil {
49 return err
50 }
51
52 return nil
53 },
54}
55
56var runCreatePrivateJwk = &cli.Command{
57 Name: "create-private-jwk",
58 Usage: "creates a private jwk for your pds",
59 Flags: []cli.Flag{
60 &cli.StringFlag{
61 Name: "out",
62 Required: true,
63 Usage: "output file for your jwk",
64 },
65 },
66 Action: func(cmd *cli.Context) error {
67 privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
68 if err != nil {
69 return err
70 }
71
72 key, err := jwk.FromRaw(privKey)
73 if err != nil {
74 return err
75 }
76
77 kid := fmt.Sprintf("%d", time.Now().Unix())
78
79 if err := key.Set(jwk.KeyIDKey, kid); err != nil {
80 return err
81 }
82
83 b, err := json.Marshal(key)
84 if err != nil {
85 return err
86 }
87
88 if err := os.WriteFile(cmd.String("out"), b, 0644); err != nil {
89 return err
90 }
91
92 return nil
93 },
94}