func cryptSignFile(ks *store.KeyStore, cfg *config) error { message, err := util.ReadFile(cfg.Args[0]) if err != nil { util.Errorf("%v", err) return err } out, ok := ks.EncryptAndSignTo(cfg.Label, message) if !ok { util.Errorf("Failed to encrypt message.") return errors.New("signcryption failed") } if cfg.Armour { block := pem.Block{ Type: public.SignedAndEncryptedType, Bytes: out, } out = pem.EncodeToMemory(&block) } err = util.WriteFile(out, cfg.Args[1]) if err != nil { util.Errorf("%v", err) return nil } return nil }
func loadStore(path string, m secret.ScryptMode) *store.SecretStore { passphrase, err := util.PassPrompt("Secrets passphrase> ") if err != nil { util.Errorf("Failed to read passphrase: %v", err) return nil } var passwords *store.SecretStore if ok, _ := util.Exists(path); ok { defer util.Zero(passphrase) fileData, err := util.ReadFile(path) if err != nil { util.Errorf("%v", err) return nil } var ok bool passwords, ok = store.UnmarshalSecretStore(fileData, passphrase, m) if !ok { return nil } return passwords } util.Errorf("could not find %s", path) return nil }
// LoadKeyStore attempts to load a keystore from the given path. If // the keystore doesn't exist, a new one is created with a // freshly-generated keys if the orNew argument is true. func LoadKeyStore(path string, orNew bool) (*KeyStore, bool) { data, err := ioutil.ReadFile(path) if err != nil && os.IsNotExist(err) && orNew { var priv *public.PrivateKey priv, err = public.GenerateKey() if err != nil { util.Errorf("Failed to generate key.") return nil, false } return NewPrivateKeyStore(priv) } else if err != nil { util.Errorf("%v", err) return nil, false } store := new(KeyStore) err = json.Unmarshal(data, store) if err != nil { util.Errorf("%v", err) return nil, false } if store.Keys == nil { store.Keys = map[string]*PublicKeyRecord{} } if store.PrivateKey != nil { store.locked = true } if !store.Valid(true) { util.Errorf("invalid keystore %v", store) return nil, false } return store, true }
// UnmarshalSecretStore decrypts and parses the secret store contained // in the input byte slice. func UnmarshalSecretStore(in, passphrase []byte, m secret.ScryptMode) (*SecretStore, bool) { if len(in) < saltSize { return nil, false } salt := in[:saltSize] enc := in[saltSize:] key := secret.DeriveKeyStrength(passphrase, salt, m) if key == nil { return nil, false } defer util.Zero(key[:]) data, ok := secret.Decrypt(key, enc) if !ok { util.Errorf("decrypt fails") return nil, false } defer util.Zero(data) var store SecretStore err := json.Unmarshal(data, &store) if err != nil { util.Errorf("encrypt fails") return nil, false } store.passphrase = make([]byte, len(passphrase)) copy(store.passphrase, passphrase) return &store, true }
func loadStore(path string) *store.KeyStore { // If keystore is newly created, we'll want to write it to // disk before leaving this function. var flush bool if exists, _ := util.Exists(path); !exists { flush = true } passphrase, err := util.PassPrompt("keystore passphrase> ") if err != nil { util.Errorf("%v", err) return nil } defer util.Zero(passphrase) keystore, ok := store.LoadKeyStore(path, true) if !ok { fmt.Printf("error in LoadKeyStore") return nil } if !keystore.Valid(false) { fmt.Println("keystore not valid") return nil } if !flush { if !keystore.Unlock(passphrase) { return nil } return keystore } if !keystore.LockWith(passphrase) { util.Errorf("Failed to set initial passphrase.") return nil } else if !keystore.Unlock(passphrase) { util.Errorf("Flushing keystore failed.") return nil } out, err := keystore.Dump() if err != nil { log.Printf("WARNING: failed to dump keystore: %v", err) return nil } err = ioutil.WriteFile(path, out, 0644) if err != nil { log.Printf("WARNING: failed to write keystore: %v", err) } return keystore }
func writeStore(ks *store.KeyStore, path string) bool { storeData := store.DumpKeyStore(ks) if storeData == nil { util.Errorf("Failed to dump keystore.") return false } err := ioutil.WriteFile(path, storeData, 0644) if err != nil { util.Errorf("%v", err) return false } return true }
func addSecret(ps *store.SecretStore, cfg *config, m secret.ScryptMode) error { if cfg.WithMeta { return addMeta(ps, cfg, m) } label := cfg.Args[0] var rec *store.SecretRecord if ps.Has(label) { if !cfg.Overwrite { return errors.New("entry exists, not forcing overwrite") } util.Errorf("*** WARNING: overwriting password") rec = ps.Store[label] } else { rec = &store.SecretRecord{Label: label} } password, err := readpass.PasswordPromptBytes("New password: "******"no password entered") } rec.Secret = password rec.Timestamp = time.Now().Unix() ps.Store[label] = rec return nil }
func removeMeta(ps *store.SecretStore, cfg *config) error { label := cfg.Args[0] if !ps.Has(label) { return errors.New("entry not found") } rec := ps.Store[label] for { var keys = make([]string, 0, len(rec.Metadata)) for k := range rec.Metadata { keys = append(keys, k) } sort.Strings(keys) fmt.Println("Keys:") for i := range keys { fmt.Printf("\t%s\n", keys[i]) } key, err := util.ReadLine("Remove key: ") if err != nil { util.Errorf("Failed to read key: %v", err) continue } else if key == "" { break } delete(rec.Metadata, key) fmt.Println("Deleted key", key) } rec.Timestamp = time.Now().Unix() ps.Store[label] = rec return nil }
func initStore(path string, m secret.ScryptMode) error { passphrase, err := util.PassPrompt("Secrets passphrase> ") if err != nil { util.Errorf("Failed to read passphrase: %v", err) return err } if len(passphrase) == 0 { return fmt.Errorf("No passphrase provided.") } defer util.Zero(passphrase) passwords := store.NewSecretStore(passphrase) if passwords == nil { return fmt.Errorf("failed to create store") } fmt.Println("creating store...") fileData, ok := store.MarshalSecretStore(passwords, m) if !ok { return fmt.Errorf("failed to marshal store") } err = util.WriteFile(fileData, path) if err != nil { return err } passwords, ok = store.UnmarshalSecretStore(fileData, passphrase, m) if !ok { err = fmt.Errorf("failed to unmarshal store") } return err }
// migrateStore decrypts a file using the legacy settings for scrypt, // and re-encrypts with the current settings. func migrateStore(path string) { prompt := fmt.Sprintf("Password for %s: ", path) pass, err := readpass.PasswordPromptBytes(prompt) if err != nil { util.Errorf("%v", err) os.Exit(1) } blob, err := legacy.DecryptFile(path, pass) if err != nil { util.Errorf("%v", err) os.Exit(1) } fmt.Printf("[+] Decrypted %s.\n", path) err = secret.EncryptFile(path, pass, blob) if err != nil { util.Errorf("%v", err) os.Exit(1) } fmt.Printf("[+] Migrated %s.\n", path) }
// KeyAudit verifies the signature chain on all keys in the // keystore. This operation may be slow, and it is recommended that it // be run at most once per hour. For large keystores, once per day // might be more suitable. func (s *KeyStore) KeyAudit() bool { if !s.Valid(true) { return false } for lbl := range s.Keys { if !s.VerifyChain(lbl) { util.Errorf("Key %s is not trusted.", lbl) return false } } return true }
func writeStore(ps *store.SecretStore, path string, m secret.ScryptMode) bool { fileData, ok := store.MarshalSecretStore(ps, m) if !ok { return false } err := util.WriteFile(fileData, path) if err != nil { util.Errorf("Write failed: %v", err) return false } return true }
func multi(ps *store.SecretStore, cfg *config, m secret.ScryptMode) error { fmt.Println("Use an empty name to indicate that you are done.") for { name, err := util.ReadLine("Name: ") if err != nil { return err } else if name == "" { break } var rec *store.SecretRecord if ps.Has(name) { if !cfg.Overwrite { util.Errorf("Entry exists, not forcing overwrite.") continue } else { util.Errorf("*** WARNING: overwriting password") } rec = ps.Store[name] } else { rec = &store.SecretRecord{ Label: name, } } password, err := util.PassPrompt("Password: "******"No password entered.") continue } rec.Secret = password rec.Timestamp = time.Now().Unix() ps.Store[name] = rec } return nil }
func unlockStore(ks *store.KeyStore) bool { if !ks.Locked() { return true } passphrase, err := util.PassPrompt("keystore passphrase> ") if err != nil { util.Errorf("%v", err) return false } defer util.Zero(passphrase) if !ks.Locked() && ks.PrivateKey == nil { if !ks.LockWith(passphrase) { util.Errorf("Failed to set initial passphrase.") return false } } if !ks.Unlock(passphrase) { util.Errorf("Unlock failed (bad passphrase?)") return false } return true }
func writeMeta(args []string) error { if len(args) == 0 { return errors.New("no label specified") } else if len(args) > 1 { return errors.New("only one label may be specified") } label := args[0] r, ok := session.Store.Store[label] if !ok { return errors.New("no such record") } if r.Metadata == nil { r.Metadata = map[string][]byte{} } fmt.Println("Enter metadata; use an empty line to indicate that you are done.") for { line, err := util.ReadLine("key = value: ") if err != nil { return err } else if line == "" { break } meta := strings.SplitN(line, "=", 2) if len(meta) < 2 { util.Errorf("Metadata should be in the form 'key=value'") continue } key := strings.TrimSpace(meta[0]) val := strings.TrimSpace(meta[1]) if prev, ok := r.Metadata[key]; ok { fmt.Printf("Note: replacing previous value of '%s'\n", string(prev)) } r.Metadata[key] = []byte(val) } r.Timestamp = time.Now().Unix() session.Store.Timestamp = r.Timestamp session.Store.Store[label] = r session.Dirty = true return nil }
func addMeta(ps *store.SecretStore, cfg *config, m secret.ScryptMode) error { label := cfg.Args[0] if !ps.Has(label) { tempConfig := *cfg tempConfig.WithMeta = false err := addSecret(ps, &tempConfig, m) if err != nil { return err } } rec := ps.Store[label] if rec.Metadata == nil { rec.Metadata = map[string][]byte{} } fmt.Println("Enter metadata; use an empty line to indicate that you are done.") for { line, err := util.ReadLine("key = value: ") if err != nil { return err } else if line == "" { break } meta := strings.SplitN(line, "=", 2) if len(meta) < 2 { util.Errorf("Metadata should be in the form 'key=value'") continue } key := strings.TrimSpace(meta[0]) val := strings.TrimSpace(meta[1]) rec.Metadata[key] = []byte(val) } rec.Timestamp = time.Now().Unix() ps.Store[label] = rec return nil }
func main() { baseFile := filepath.Join(os.Getenv("HOME"), ".secrets.db") doInit := flag.Bool("init", false, "initialize a new store") doMerge := flag.Bool("merge", false, "merge another store into this store") doExport := flag.Bool("export", false, "export store to PEM") doImport := flag.Bool("import", false, "import store from PEM") doMulti := flag.Bool("multi", false, "enter multiple passwords") doChPass := flag.Bool("c", false, "change the store's password") storePath := flag.String("f", baseFile, "path to password store") doList := flag.Bool("l", false, "list accounts") withMeta := flag.Bool("m", false, "include metadata") doRemove := flag.Bool("r", false, "remove entries") doStore := flag.Bool("s", false, "store password") clipExport := flag.Bool("x", false, "dump secrets for clipboard") overWrite := flag.Bool("w", false, "overwrite existing secrets") doVersion := flag.Bool("V", false, "display version and exit") scryptInteractive := flag.Bool("i", false, "use scrypt interactive") flag.Parse() if *doVersion { fmt.Println("secrets version", util.VersionString()) os.Exit(0) } scryptMode := secret.ScryptStandard if *scryptInteractive { scryptMode = secret.ScryptInteractive } var cfg = &config{ Args: flag.Args(), Clip: *clipExport, WithMeta: *withMeta, Overwrite: *overWrite, } var cmd command switch { case *doInit: cmd = commandSet["init"] err := initStore(*storePath, scryptMode) if err != nil { util.Errorf("Failed: %v", err) os.Exit(1) } return case *doChPass: cmd = commandSet["passwd"] case *doStore: cmd = commandSet["store"] case *doRemove: cmd = commandSet["remove"] case *doList: cmd = commandSet["list"] case *doMulti: cmd = commandSet["multi"] case *doMerge: cmd = commandSet["merge"] case *doExport: if flag.NArg() != 1 { util.Errorf("No output file specified.") } err := exportStore(*storePath, flag.Arg(0)) if err != nil { util.Errorf("Failed: %v", err) os.Exit(1) } return case *doImport: if flag.NArg() != 1 { util.Errorf("No input file specified.") } err := importStore(*storePath, flag.Arg(0)) if err != nil { util.Errorf("Failed: %v", err) os.Exit(1) } return default: cmd = commandSet["show"] } if flag.NArg() < cmd.RequiredArgc { util.Errorf("Not enough arguments: want %d, have %d.", cmd.RequiredArgc, flag.NArg()) util.Errorf("Want: %v", strings.Join(cmd.Args, ", ")) os.Exit(1) } passwords := loadStore(*storePath, scryptMode) if passwords == nil { util.Errorf("Failed to open password store") os.Exit(1) } defer passwords.Zero() err := cmd.Run(passwords, cfg, scryptMode) if err != nil { util.Errorf("Failed: %v", err) os.Exit(1) } if cmd.ShouldWrite { passwords.Timestamp = time.Now().Unix() if !writeStore(passwords, *storePath, scryptMode) { util.Errorf("Failed to write store!") os.Exit(1) } } }
func addSecret(ps *store.SecretStore, cfg *config) error { label := cfg.Args[0] if ps.Has(label) { if cfg.Overwrite { util.Errorf("WARNING: a token already exists under this label!") } else { return errors.New("token already exists under label") } } // Default prompt is echoing, which we want here. secret, err := util.PassPrompt("Secret: ") if err != nil { return err } var rec *store.SecretRecord secret = sanitiseSecret(secret) switch cfg.OTPType { case HOTP: in, err := util.ReadLine("Initial counter (0): ") if err != nil { return err } if in == "" { in = "0" } d, err := strconv.Atoi(in) if err != nil { return err } in, err = util.ReadLine("Digits (6 or 8): ") if err != nil { return err } else if in == "" { in = "6" } digits, err := strconv.Atoi(in) if err != nil { return err } key, err := base32.StdEncoding.DecodeString(string(secret)) if err != nil { fmt.Printf("%s", secret) return err } var hotp *twofactor.HOTP hotp = twofactor.NewHOTP(key, uint64(d), digits) confirmation := hotp.OTP() fmt.Printf("Confirmation: %s\n", confirmation) rec = &store.SecretRecord{ Label: label, Secret: []byte(hotp.URL(label)), Timestamp: time.Now().Unix(), Metadata: map[string][]byte{ "key": secret, "type": []byte("HOTP"), "confirmation": []byte(confirmation), }, } case TOTP: in, err := util.ReadLine("Time step (30s): ") if err != nil { return err } if in == "" { in = "30s" } d, err := time.ParseDuration(in) if err != nil { return err } in, err = util.ReadLine("Digits (6 or 8): ") if err != nil { return err } else if in == "" { in = "6" } digits, err := strconv.Atoi(in) if err != nil { return err } key, err := base32.StdEncoding.DecodeString(string(secret)) if err != nil { return err } var totp *twofactor.TOTP totp = twofactor.NewTOTPSHA1(key, 0, uint64(d.Seconds()), digits) confirmation := totp.OTP() fmt.Printf("Confirmation: %s\n", confirmation) rec = &store.SecretRecord{ Label: label, Secret: []byte(totp.URL(label)), Timestamp: time.Now().Unix(), Metadata: map[string][]byte{ "key": secret, "type": []byte("TOTP-SHA1"), "step": []byte(d.String()), "confirmation": []byte(confirmation), }, } case GoogleTOTP: var totp *twofactor.TOTP totp, err = twofactor.NewGoogleTOTP(string(secret)) if err != nil { return err } confirmation := totp.OTP() fmt.Printf("Confirmation: %s\n", confirmation) rec = &store.SecretRecord{ Label: label, Secret: []byte(totp.URL(label)), Timestamp: time.Now().Unix(), Metadata: map[string][]byte{ "key": secret, "type": []byte("TOTP-GOOGLE"), "step": []byte("30s"), "confirmation": []byte(confirmation), }, } default: return errors.New("unrecognised OTP type") } ps.Store[label] = rec return nil }
func main() { baseFile := filepath.Join(os.Getenv("HOME"), ".otpc.db") doInit := flag.Bool("init", false, "initialize a new store") doStore := flag.Bool("s", false, "store a new two-factor token") storePath := flag.String("f", baseFile, "path to password store") otpKind := flag.String("t", "", "OTP type (TOTP, HOTP, GOOGLE)") doQR := flag.Bool("qr", false, "dump QR code for secret") doVersion := flag.Bool("V", false, "display version and exit") scryptInteractive := flag.Bool("i", false, "use scrypt interactive") flag.Parse() if *doVersion { fmt.Println("otpc version", util.VersionString()) os.Exit(0) } scryptMode := secret.ScryptStandard if *scryptInteractive { scryptMode = secret.ScryptInteractive } var cfg = &config{ Args: flag.Args(), OTPType: parseOTPKind(*otpKind), } var cmd command switch { case *doInit: cmd = commandSet["init"] err := initStore(*storePath, scryptMode) if err != nil { util.Errorf("Failed: %v", err) os.Exit(1) } return case *doStore: cmd = commandSet["store"] case *doQR: cmd = commandSet["qr"] default: cmd = commandSet["show"] } if flag.NArg() < cmd.RequiredArgc { util.Errorf("Not enough arguments: want %d, have %d.", cmd.RequiredArgc, flag.NArg()) util.Errorf("Want: %v", strings.Join(cmd.Args, ", ")) os.Exit(1) } ps := loadStore(*storePath, scryptMode) if ps == nil { util.Errorf("Failed to open two-factor store.") os.Exit(1) } defer ps.Zero() err := cmd.Run(ps, cfg) if err != nil { util.Errorf("Failed: %v", err) os.Exit(1) } if cmd.ShouldWrite || cfg.Updated { ps.Timestamp = time.Now().Unix() if !writeStore(ps, *storePath, scryptMode) { util.Errorf("Failed to write store!") os.Exit(1) } } }
func main() { baseFile := filepath.Join(os.Getenv("HOME"), ".secrets.db") count := flag.Int("n", 5, "how many delegations are going out?") caFile := flag.String("ca", "", "CA file for Red October") storePath := flag.String("f", baseFile, "path to password store") scryptInteractive := flag.Bool("i", false, "use scrypt interactive") forTime := flag.String("for", "1h", "how long should the delegation be active for?") labels := flag.String("labels", "", "red october labels to use for decryption") server := flag.String("server", "127.0.0.1:8080", "host:port of red october server") owners := flag.String("to", "", "users to whitelist for decryption") userName := flag.String("u", "", "username for red october") flag.Parse() if flag.NArg() != 2 { usage() os.Exit(1) } scryptMode := secret.ScryptStandard if *scryptInteractive { scryptMode = secret.ScryptInteractive } passwords := loadStore(*storePath, scryptMode) if passwords == nil { util.Errorf("Failed to open password store") os.Exit(1) } defer passwords.Zero() rec, ok := passwords.Store[flag.Arg(0)] if !ok { util.Errorf("%s is not a valid label.", flag.Arg(0)) os.Exit(1) } var ro roData ro.User, ok = getMetadata(rec, "ro-user", *userName) if !ok { util.Errorf("Unable to get a valid user.") os.Exit(1) } ro.Password = string(rec.Secret) ro.Server, ok = getMetadata(rec, "ro-server", *server) if !ok { util.Errorf("Unable to get a valid user.") os.Exit(1) } ro.CAFile, ok = getMetadata(rec, "ro-ca", *caFile) if !ok { util.Errorf("Unable to get a valid user.") os.Exit(1) } ro.Labels = split(*labels) ro.Owners = split(*owners) ro.Count = *count ro.Dur = *forTime var err error cmd := flag.Arg(1) switch cmd { case "delegate": err = delegate(&ro) case "summary": err = summary(&ro) default: err = errors.New("rocli: invalid command " + cmd) } if err != nil { util.Errorf("%v", err) os.Exit(1) } }
func main() { flArmour := flag.Bool("a", false, "armour output") flOutDir := flag.String("o", ".", "output directory") flOutfile := flag.String("f", "passcrypt.enc", "pack file") flShowManifest := flag.Bool("l", false, "list the files in the archive") flUnpack := flag.Bool("u", false, "unpack the archive") flag.BoolVar(&verbose, "v", false, "verbose mode") flVersion := flag.Bool("V", false, "display version and exit") flag.Parse() if *flVersion { fmt.Println("passcrypt version", util.VersionString()) os.Exit(0) } if *flUnpack || *flShowManifest { if flag.NArg() != 1 { util.Errorf("Only one file may be unpacked at a time.\n") os.Exit(1) } in, err := ioutil.ReadFile(flag.Arg(0)) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } if p, _ := pem.Decode(in); p != nil { if p.Type != header { util.Errorf("Wrong header for archive.\n") os.Exit(1) } in = p.Bytes } if len(in) <= saltLength { util.Errorf("Invalid archive.\n") os.Exit(1) } salt := in[:saltLength] in = in[saltLength:] passphrase, err := readpass.PasswordPromptBytes("Password: "******"%v\n", err) os.Exit(1) } key := secret.DeriveKey(passphrase, salt) if key == nil { util.Errorf("Failed to derive key.n\n") os.Exit(1) } in, ok := secret.Decrypt(key, in) if !ok { util.Errorf("Decryption failed.\n") os.Exit(1) } defer util.Zero(in) if *flUnpack { err = unpackFiles(in, *flOutDir) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } } else if *flShowManifest { var files []File _, err := asn1.Unmarshal(in, &files) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } fmt.Println("Manifest for", flag.Arg(0)) fmt.Printf("\n") for _, file := range files { fmt.Printf("\t%s", file.Path) if os.FileMode(file.Mode).IsDir() { fmt.Printf("/") } fmt.Printf("\n") } } return } if flag.NArg() == 0 { return } passphrase, err := readpass.PasswordPromptBytes("Password: "******"%v\n", err) os.Exit(1) } salt := util.RandBytes(saltLength) if salt == nil { util.Errorf("Failed to generate a random salt.\n") os.Exit(1) } key := secret.DeriveKey(passphrase, salt) if key == nil { util.Errorf("Failed to derive key.n\n") os.Exit(1) } out, err := packFiles(flag.Args()) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } var ok bool out, ok = secret.Encrypt(key, out) if !ok { util.Errorf("Encryption failed.\n") os.Exit(1) } out = append(salt, out...) if *flArmour { p := &pem.Block{ Type: header, Bytes: out, } out = pem.EncodeToMemory(p) } err = ioutil.WriteFile(*flOutfile, out, 0644) if err != nil { util.Errorf("%v\n", err) os.Exit(1) } }
func main() { baseFile := filepath.Join(os.Getenv("HOME"), ".cukeystore.db") doCheck := flag.Bool("check", false, "check keystore's integrity'") doExport := flag.Bool("export", false, "export a verified key") doImport := flag.Bool("import", false, "import a key") doArmour := flag.Bool("a", false, "armour output") doDecrypt := flag.Bool("d", false, "decrypt file") doEncrypt := flag.Bool("e", false, "encrypt file") keystorePath := flag.String("f", baseFile, "path to keystore") doList := flag.Bool("k", false, "list keys") label := flag.String("l", "self", "label selecting a key") doRemove := flag.Bool("r", false, "remove named key") doSign := flag.Bool("s", false, "sign file") untrustedOK := flag.Bool("u", false, "accept untrusted keys when importing") doVerify := flag.Bool("v", false, "verify signature") flag.Parse() cfg := &config{ Args: flag.Args(), Label: *label, Armour: *doArmour, } var cmd command switch { case *doCheck: cmd = commandSet["check"] case *doSign && *doEncrypt: cfg.Armour = true cmd = commandSet["cryptsign"] case *doSign: cmd = commandSet["sign"] case *doVerify: cmd = commandSet["verify"] case *doEncrypt: cmd = commandSet["encrypt"] case *doDecrypt: cmd = commandSet["decrypt"] case *doRemove: cmd = commandSet["remove"] case *doList: cmd = commandSet["list"] case *doExport && *label == "self": cmd = commandSet["exportself"] case *doExport: cmd = commandSet["export"] case *doImport: if *untrustedOK { cmd = commandSet["uimport"] } else { cmd = commandSet["import"] } default: util.Errorf("Nothing to do.") return } if flag.NArg() < cmd.RequiredArgc { util.Errorf("Not enough arguments: want %d, have %d.", cmd.RequiredArgc, flag.NArg()) util.Errorf("Want: %v", strings.Join(cmd.Args, ", ")) os.Exit(1) } ks := loadStore(*keystorePath) if ks == nil { util.Errorf("Failed to load keystore.") os.Exit(1) } if *doCheck && ks.ExportKey == nil { cmd.ShouldWrite = true } if cmd.NeedsUnlock { if !unlockStore(ks) { os.Exit(1) } defer ks.Lock() } err := cmd.Run(ks, cfg) if err != nil { util.Errorf("Failed: %v", err) os.Exit(1) } shouldWrite := cmd.ShouldWrite exists, ok := util.Exists(*keystorePath) if !ok { util.Errorf("Error checking %s", *keystorePath) os.Exit(1) } shouldWrite = shouldWrite || !exists if shouldWrite { ks.Timestamp = time.Now().Unix() fmt.Println("Writing keystore.") if !writeStore(ks, *keystorePath) { os.Exit(1) } } }
func main() { baseFile := filepath.Join(os.Getenv("HOME"), ".cu_journal") doInit := flag.Bool("init", false, "initialize a new store") currentEditor := os.Getenv("EDITOR") editor := flag.String("editor", currentEditor, "editor for writing entries") doEdit := flag.Bool("e", false, "edit entry") storePath := flag.String("f", baseFile, "path to journal") doList := flag.Bool("l", false, "list entries") doWrite := flag.Bool("w", false, "write new entry") doVersion := flag.Bool("V", false, "display version and exit") scryptInteractive := flag.Bool("i", false, "use scrypt interactive") flag.Parse() if *doVersion { fmt.Println("journal version", util.VersionString()) os.Exit(0) } scryptMode := secret.ScryptStandard if *scryptInteractive { scryptMode = secret.ScryptInteractive } var cfg = &config{ Args: flag.Args(), Editor: *editor, } var cmd command switch { case *doInit: cmd = commandSet["init"] err := initStore(*storePath, scryptMode) if err != nil { util.Errorf("Failed: %v", err) os.Exit(1) } return case *doEdit: cmd = commandSet["edit"] case *doList: cmd = commandSet["list"] case *doWrite: cmd = commandSet["write"] default: cmd = commandSet["show"] } if flag.NArg() < cmd.RequiredArgc { util.Errorf("Not enough arguments: want %d, have %d.", cmd.RequiredArgc, flag.NArg()) util.Errorf("Want: %v", strings.Join(cmd.Args, ", ")) os.Exit(1) } passwords := loadStore(*storePath, scryptMode) if passwords == nil { util.Errorf("Failed to open password store") os.Exit(1) } defer passwords.Zero() err := cmd.Run(passwords, cfg) if err != nil { util.Errorf("Failed: %v", err) os.Exit(1) } if cmd.ShouldWrite { passwords.Timestamp = time.Now().Unix() if !writeStore(passwords, *storePath, scryptMode) { util.Errorf("Failed to write store!") os.Exit(1) } } }