func importVerified(ks *store.KeyStore, cfg *config) error { keyData, err := util.ReadFile(cfg.Args[0]) if err != nil { return err } if cfg.Label == "self" { cfg.Label, err = util.ReadLine("Label: ") if err != nil { return err } } if !ks.ImportVerifiedKey(cfg.Label, keyData) { return errors.New("verified import failed") } vkey, err := store.ParseVerifiedKey(keyData) if err != nil { return err } label, ok := ks.FindPublic(vkey.Signer) if !ok { return errors.New("invalid signer on key") } fmt.Printf("Imported public key signed by '%s'.\n", label) return nil }
func keyList(ks *store.KeyStore, cfg *config) error { updated := time.Unix(ks.Timestamp, 0).Format(timeFormat) fmt.Println("Key store was last updated", updated) fmt.Printf("%d keys stored\n", len(ks.Keys)) fmt.Println("Owner public key:") h := sha256.New() h.Write(ks.PublicKey) fmt.Printf("\tFingerprint: %x\n", h.Sum(nil)) if len(ks.Keys) > 0 { fmt.Println("Key store:") for k, v := range ks.Keys { fmt.Printf("\t%s\n", k) ut := time.Unix(v.Timestamp, 0) st := time.Unix(v.SignatureTime, 0) signer, ok := ks.FindPublic(v.KeySigner) if !ok { signer = "<unknown>" } h = sha256.New() h.Write(v.Keys) fmt.Printf("\t\tLast update: %s\n", ut.Format(timeFormat)) fmt.Printf("\t\t Signed at: %s\n", st.Format(timeFormat)) fmt.Printf("\t\t Signed by: %s\n", signer) fmt.Printf("\t\tFingerprint: %x\n", h.Sum(nil)) } } return nil }
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 decryptSignedFile(ks *store.KeyStore, cfg *config) error { message, err := util.ReadFile(cfg.Args[0]) if err != nil { return err } if len(message) > 10 { if bytes.Equal(message[:10], []byte("-----BEGIN")) { p, _ := pem.Decode(message) if p == nil { return errors.New("failed to decode PEM file") } switch p.Type { case public.EncryptedType: message = p.Bytes default: return errors.New("invalid message") } } } out, ok := ks.DecryptAndVerify(cfg.Label, message) if !ok { return errors.New("decrypt failed") } err = util.WriteFile(out, cfg.Args[1]) if err != nil { return err } return nil }
func encryptFile(ks *store.KeyStore, cfg *config) error { message, err := util.ReadFile(cfg.Args[0]) if err != nil { return err } out, ok := ks.EncryptTo(cfg.Label, message) if !ok { return errors.New("encryption failed") } if cfg.Armour { block := pem.Block{ Type: public.EncryptedType, Bytes: out, } out = pem.EncodeToMemory(&block) } err = util.WriteFile(out, cfg.Args[1]) if err != nil { return err } return nil }
func verifyFile(ks *store.KeyStore, cfg *config) error { message, err := util.ReadFile(cfg.Args[0]) if err != nil { return err } sig, err := util.ReadFile(cfg.Args[1]) if err != nil { return err } if len(sig) > 10 { if bytes.Equal(sig[:10], []byte("-----BEGIN")) { p, _ := pem.Decode(sig) if p == nil { return errors.New("failed to decode PEM file") } switch p.Type { case public.SignatureType: sig = p.Bytes default: return errors.New("invalid message") } } } if ks.Verify(cfg.Label, message, sig) { fmt.Println("Signature: OK") } else { fmt.Println("Signature: INVALID") } return nil }
func keystoreDispatch(ks *store.KeyStore, keystoreFile string) { for { t := time.After(10 * time.Minute) select { case cmd, ok := <-dispatch: if !ok { return } log.Println("received command for", cmd.op) res := process(ks, cmd) cmd.cb <- res case <-t: log.Printf("dumping keystore") t = time.After(10 * time.Minute) out, err := ks.Dump() if err != nil { log.Printf("WARNING: failed to dump keystore: %v", err) break } err = ioutil.WriteFile(keystoreFile, out, 0644) if err != nil { log.Printf("WARNING: failed to write keystore: %v", err) } } } }
func exportVerified(ks *store.KeyStore, cfg *config) error { out, ok := ks.ExportVerified(cfg.Label) if !ok { return errors.New("failed to export verified public key") } return util.WriteFile(out, cfg.Args[0]) }
func importUntrusted(ks *store.KeyStore, cfg *config) error { fmt.Println("*****************************************") fmt.Println("*** WARNING: IMPORTING UNTRUSTED KEYS ***") fmt.Println("*****************************************") keyData, err := util.ReadFile(cfg.Args[0]) if err != nil { return err } vkey, err := store.ParseVerifiedKey(keyData) if err != nil { return err } if vkey.IsSelfSigned() { fmt.Println("Key is self-signed.") } else { fmt.Println("Unrecognised signature.") } h := sha256.New() h.Write(vkey.Public) fmt.Printf("Fingerprint: %x\n", h.Sum(nil)) for { line, err := util.ReadLine("\nAre you sure you want to import this key? (yes or no) ") if err != nil { return nil } if line == "yes" { fmt.Println("As you wish.") break } else if line == "no" { return errors.New("canceled by user") } else { fmt.Println("Please enter either 'yes' or 'no'.") } } if cfg.Label == "self" { cfg.Label, err = util.ReadLine("Label: ") if err != nil { return err } } if !ks.AddKey(cfg.Label, vkey.Public, nil) { return errors.New("failed to add new key") } return nil }
func removeKey(ks *store.KeyStore, cfg *config) error { cfg.Label = cfg.Args[0] if cfg.Label == "self" { return errors.New("cannot remove own key") } else if !ks.Has(cfg.Label) { return fmt.Errorf("no key was found under label %s", cfg.Label) } fmt.Println("Removing key ", cfg.Label) delete(ks.Keys, cfg.Label) return nil }
func decryptFile(ks *store.KeyStore, cfg *config) error { message, err := util.ReadFile(cfg.Args[0]) if err != nil { return err } var needVerify bool if len(message) > 10 { if bytes.Equal(message[:10], []byte("-----BEGIN")) { p, _ := pem.Decode(message) if p == nil { return errors.New("failed to decode PEM file") } switch p.Type { case public.EncryptedType: message = p.Bytes case public.SignedAndEncryptedType: needVerify = true message = p.Bytes default: return errors.New("invalid message") } } } var out []byte var ok bool if !needVerify { out, ok = ks.Decrypt(message) if !ok { return errors.New("decrypt failed") } } else { out, ok = ks.DecryptAndVerify(cfg.Label, message) if !ok { return errors.New("decrypt and verify failed") } fmt.Println("Valid signature.") } err = util.WriteFile(out, cfg.Args[1]) if err != nil { return err } return nil }
func checkUpload(ks *store.KeyStore, cmd command) response { label := cmd.data["label"] pub := []byte(cmd.data["public"]) var resp response if label == "self" || label == "" { resp.err = errors.New("invalid label") return resp } ok := ks.ImportVerifiedKey(label, pub) if !ok { resp.err = errors.New("failed to add public key") } else { resp.out = []byte("public key added successfully") } return resp }
func signFile(ks *store.KeyStore, cfg *config) error { message, err := util.ReadFile(cfg.Args[0]) if err != nil { return err } sig, ok := ks.Sign(message) if !ok { return errors.New("signing failed") } if cfg.Armour { block := pem.Block{ Type: public.SignatureType, Bytes: sig, } sig = pem.EncodeToMemory(&block) } return util.WriteFile(sig, cfg.Args[1]) }
func checkStore(ks *store.KeyStore, cfg *config) error { if ks.Locked() { return errors.New("keystore is locked") } if !ks.Valid(false) { return errors.New("keystore is invalid") } if !ks.KeyAudit() { return errors.New("audit failed") } fmt.Println("Keystore is valid.") 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 process(ks *store.KeyStore, cmd command) *response { var resp response switch cmd.op { case "public": log.Printf("public key lookup") if cmd.data["label"] == "" { log.Printf("public key request with no label") resp.err = errors.New("missing label") } ok := ks.Has(cmd.data["label"]) if !ok { log.Printf("keystore doesn't have key with label %s", cmd.data["label"]) resp.err = errors.New("export failed") } if cmd.data["label"] == "self" { resp.out = ks.ExportKey[:] } else { rec := ks.Keys[cmd.data["label"]] if rec == nil { log.Printf("keystore lookup failed") resp.err = errors.New("export failed") break } vkey := &store.VerifiedKey{ Public: rec.Keys, Signer: rec.KeySigner, Timestamp: rec.SignatureTime, Signature: rec.KeySignature, } resp.out, resp.err = vkey.Serialise() } case "fingerprint": log.Printf("fingerprint lookup") if cmd.data["label"] == "" { log.Printf("fingerprint request with no label") resp.err = errors.New("missing label") } ok := ks.Has(cmd.data["label"]) if !ok { log.Printf("keystore doesn't have key with label %s", cmd.data["label"]) resp.err = errors.New("export failed") } var pub []byte if cmd.data["label"] == "self" { pub = ks.PublicKey[:] } else { rec := ks.Keys[cmd.data["label"]] if rec == nil { log.Printf("keystore lookup failed") resp.err = errors.New("fingerprint failed") break } pub = rec.Keys[:] } h := sha256.New() h.Write(pub) resp.out = []byte(fmt.Sprintf("%x", h.Sum(nil))) case "upload": log.Printf("upload request") resp = checkUpload(ks, cmd) case "audit": log.Printf("audit request") ok := ks.KeyAudit() if !ok { resp.err = errors.New("audit failure") } default: resp.err = errors.New("invalid command") } return &resp }