master
  1package generate
  2
  3import (
  4	"crypto"
  5	"crypto/ed25519"
  6	"encoding/base64"
  7	"encoding/pem"
  8	"fmt"
  9	"os"
 10	"path/filepath"
 11
 12	"golang.org/x/crypto/ssh"
 13)
 14
 15// helpers
 16func writeStringToFile(filePath string, data string, permission os.FileMode) error {
 17	file, err := os.Create(filePath)
 18	if err != nil {
 19		return fmt.Errorf("failed to create file %s: %w", filePath, err)
 20	}
 21
 22	if _, err = file.WriteString(data); err != nil {
 23		return fmt.Errorf("failed to write to file %s: %w", filePath, err)
 24	}
 25
 26	if err = file.Chmod(permission); err != nil {
 27		return fmt.Errorf("failed to change file permissions: %w", err)
 28	}
 29
 30	return nil
 31}
 32
 33func returnKeyPath(fileName string) (string, error) {
 34	currentDir, err := os.Getwd()
 35	if err != nil {
 36		return "", fmt.Errorf("failed to get current directory: %w", err)
 37	}
 38
 39	keyPath := filepath.Join(currentDir, fileName)
 40
 41	return keyPath, nil
 42}
 43
 44// main
 45func generateSSHKeyEDSA() (string, string, error) {
 46	// Generate a new Ed25519 private key
 47	//// If rand is nil, crypto/rand.Reader will be used
 48	public, private, err := ed25519.GenerateKey(nil)
 49	if err != nil {
 50		return "", "", fmt.Errorf("failed to generate ed25519 key: %w", err)
 51	}
 52
 53	// public key
 54	publicKey, err := ssh.NewPublicKey(public)
 55	if err != nil {
 56		return "", "", fmt.Errorf("failed to create public key: %w", err)
 57	}
 58	publicKeyString := fmt.Sprintf("ssh-ed25519 %s", base64.StdEncoding.EncodeToString(publicKey.Marshal()))
 59
 60	// private key
 61	//// p stands for pem
 62	p, err := ssh.MarshalPrivateKey(crypto.PrivateKey(private), "")
 63	if err != nil {
 64		return "", "", fmt.Errorf("failed to marshal private key: %w", err)
 65	}
 66	privateKeyPem := pem.EncodeToMemory(p)
 67	privateKeyString := string(privateKeyPem)
 68
 69	return publicKeyString, privateKeyString, nil
 70}
 71
 72func SSHKey(args []string) error {
 73	//init
 74	if len(args) == 0 {
 75		return fmt.Errorf("please specify key name")
 76	}
 77
 78	// main
 79	publicKeyString, privateKeyString, err := generateSSHKeyEDSA()
 80	if err != nil {
 81		return err
 82	}
 83
 84	// write key to file
 85	publicKeyFilename := fmt.Sprintf("%s.pub", args[0])
 86	if err = writeStringToFile(publicKeyFilename, publicKeyString, 0644); err != nil {
 87		return err
 88	}
 89
 90	privateKeyFilename := args[0]
 91	if err = writeStringToFile(privateKeyFilename, privateKeyString, 0600); err != nil {
 92		return err
 93	}
 94
 95	keyPath, err := returnKeyPath(args[0])
 96	if err != nil {
 97		return err
 98	}
 99
100	fmt.Printf("SSH key created at: %s\n", keyPath)
101	return nil
102}