74 lines
1.7 KiB
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
|
||
|
}
|