package main import ( "bytes" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "errors" "fmt" "io/ioutil" "os" "syscall" "forge.cadoles.com/wpetit/go-http-peering/crypto" "golang.org/x/crypto/ssh/terminal" ) func getPassphrase() ([]byte, error) { passphrase, exists := os.LookupEnv("KEY_PASSPHRASE") if exists { return []byte(passphrase), nil } return askPassphrase() } func askPassphrase() ([]byte, error) { fmt.Print("Passphrase: ") passphrase, err := terminal.ReadPassword(syscall.Stdin) if err != nil { return nil, err } fmt.Println() fmt.Print("Confirm passphrase: ") passphraseConfirmation, err := terminal.ReadPassword(syscall.Stdin) if err != nil { return nil, err } fmt.Println() if !bytes.Equal(passphrase, passphraseConfirmation) { return nil, errors.New("passphrases does not match") } return passphrase, nil } func privateKeyToEncryptedPEM(key *rsa.PrivateKey, passphrase []byte) ([]byte, error) { if passphrase == nil { return nil, errors.New("passphrase cannot be empty") } // Convert it to pem block := &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key), } block, err := x509.EncryptPEMBlock(rand.Reader, block.Type, block.Bytes, passphrase, x509.PEMCipherAES256) if err != nil { return nil, err } return pem.EncodeToMemory(block), nil } func loadPrivateKey() (*rsa.PrivateKey, error) { if keyFile == "" { return nil, errors.New("you must specify a key file to load") } pem, err := ioutil.ReadFile(keyFile) if err != nil { return nil, err } passphrase, err := getPassphrase() if err != nil { return nil, err } privateKey, err := crypto.DecodePEMEncryptedPrivateKey(pem, passphrase) if err != nil { return nil, err } return privateKey, nil } func handleError(err error) { if !debug { fmt.Println(err) } else { panic(err) } os.Exit(1) }