func pickSSHKey(candidateKeys map[string]string, w io.Writer) (ssh.PublicKey, error) { i := 0 keyLst := make([]ssh.PublicKey, len(candidateKeys)) for key, comment := range candidateKeys { pubKey, _, ok := ssh.ParsePublicKey([]byte(key)) if !ok { continue } keyLst[i] = pubKey k := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(pubKey))) l := fmt.Sprintf("[ %d ] %s...%s %s\n", i+1, k[0:24], k[len(k)-24:], comment) w.Write([]byte(l)) i += 1 } if i == 0 { return nil, errors.New("No ssh keys found.") } choice, err := pick("key", i) if err != nil { return nil, err } return keyLst[choice], nil }
// Find SSH keys on the local file system func getSSHKeys(existingKeyFingerprints map[string]bool) map[string]string { candidateKeys := make(map[string]string) // get key from id_rsa.pub rsaKey, rsaComment, rsaErr := sshReadPubKey(idRsaPubPath) if rsaErr == nil { candidateKeys[string(ssh.MarshalPublicKey(rsaKey))] = rsaComment } // get key from id_dsa.pub dsaKey, dsaComment, dsaErr := sshReadPubKey(idDsaPubPath) if dsaErr == nil { candidateKeys[string(ssh.MarshalPublicKey(dsaKey))] = dsaComment } // get keys from ssh-add out, err := exec.Command("ssh-add", "-L").Output() sshAddKeys := strings.TrimSpace(string(out)) if err == nil && sshAddKeys != "" { for _, k := range strings.Split(sshAddKeys, "\n") { key, comment, _, _, ok := ssh.ParseAuthorizedKey([]byte(k)) if ok { candidateKeys[string(ssh.MarshalPublicKey(key))] = comment } } } for k, _ := range candidateKeys { pubKey, _, _ := ssh.ParsePublicKey([]byte(k)) fp := fingerprint(pubKey) if _, ok := existingKeyFingerprints[fp]; ok { delete(candidateKeys, k) } } return candidateKeys }