()
| 171 | } |
| 172 | |
| 173 | func cmdExport() { |
| 174 | fs := flag.NewFlagSet("export", flag.ExitOnError) |
| 175 | alias := fs.String("alias", "", "alias name") |
| 176 | out := fs.String("out", "", "output path") |
| 177 | pass := fs.String("passphrase", "", "DEPRECATED: passphrase in CLI may leak; prefer --ask-passphrase or --passphrase-file or --passphrase-stdin") |
| 178 | ask := fs.Bool("ask-passphrase", false, "read passphrase securely from TTY") |
| 179 | passFile := fs.String("passphrase-file", "", "read passphrase from file path") |
| 180 | passStdin := fs.Bool("passphrase-stdin", false, "read passphrase from stdin") |
| 181 | force := fs.Bool("force", false, "overwrite output if exists") |
| 182 | fs.Parse(os.Args[2:]) |
| 183 | if *alias == "" || *out == "" { |
| 184 | fatal(errors.New("alias and out are required")) |
| 185 | } |
| 186 | if !*force { |
| 187 | if _, err := os.Stat(*out); err == nil { |
| 188 | fatal(fmt.Errorf("output exists: %s", *out)) |
| 189 | } |
| 190 | } |
| 191 | mk, err := keychain.LoadMasterKey() |
| 192 | if err != nil { |
| 193 | fatal(err) |
| 194 | } |
| 195 | rec, err := store.LoadDecryptedRecord(*alias, mk) |
| 196 | if err != nil { |
| 197 | fatal(err) |
| 198 | } |
| 199 | p, err := resolvePassphrase(*pass, *ask, *passFile, *passStdin, "Export PEM passphrase (optional, press Enter for none): ") |
| 200 | if err != nil { fatal(err) } |
| 201 | pemBytes, err := store.ExportPKCS8PEM(rec, p) |
| 202 | if err != nil { |
| 203 | fatal(err) |
| 204 | } |
| 205 | if err := os.WriteFile(*out, pemBytes, 0600); err != nil { |
| 206 | fatal(err) |
| 207 | } |
| 208 | fmt.Printf("exported %s to %s (PKCS#8 PEM)%s\n", rec.Alias, *out, func() string { if p != "" { return " with passphrase" } ; return "" }()) |
| 209 | } |
| 210 | |
| 211 | func cmdStatus() { |
| 212 | exists, err := keychain.MasterKeyExists() |
no test coverage detected