package credentials import ( "crypto/tls" "encoding/pem" "errors" "fmt" "os" "os/exec" "strings" "google.golang.org/grpc/credentials" ) func CredentialsFromKeyWithPasswd(certFile, certKey, passwd string) (credentials.TransportCredentials, error) { if certFile == "" { return nil, errors.New("certFile cannot be empty") } if certKey == "" { return nil, errors.New("certKey cannot be empty") } bts, err := os.ReadFile(certKey) if err != nil { return nil, fmt.Errorf("os.ReadFile certKey: %s", err) } keyBlock, rest := pem.Decode(bts) if keyBlock == nil { return nil, errors.New("not valid pem file") } if len(rest) > 0 { return nil, errors.New("rest is not empty") } if !strings.Contains(keyBlock.Type, "ENCRYPTED") { return nil, fmt.Errorf("certificate should has been encrypted with password") } decriptedKeyPem, err := decryptRSA(certKey, passwd) if err != nil { return nil, fmt.Errorf("decryptRSA: %s", err) } bts, err = os.ReadFile(certFile) if err != nil { return nil, fmt.Errorf("os.ReadFile certFile: %s", err) } cert, err := tls.X509KeyPair(bts, []byte(decriptedKeyPem)) if err != nil { return nil, fmt.Errorf("tls.X509KeyPair: %s", err) } return credentials.NewServerTLSFromCert(&cert), nil } func decryptRSA(keyFile, password string) (string, error) { cmd := exec.Command("openssl", "rsa", "-in", keyFile, "-passin", formatPass(password), "-text") output_bts, err := cmd.Output() if err != nil { return "", fmt.Errorf("cmd.Output: %s", err) } idx := strings.Index(string(output_bts), "-----BEGIN") return string(output_bts)[idx:], nil } func formatPass(password string) string { if password == "" { return "" } return "pass:" + password }