go-grpc-certificate/credentials.go

74 lines
1.7 KiB
Go

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
}