From 0ade6c177a02c81850a9dcb72f1a503b6fbeb6be Mon Sep 17 00:00:00 2001 From: wangtiga Date: Sat, 11 Nov 2023 21:27:59 +0800 Subject: [PATCH] add unit test for cert PKCS12 DER PEM --- cmd/grpcurl/grpcurl.go | 62 ++--- internal/certigo/lib/cert_key_format.go | 45 ++++ internal/certigo/lib/certs.go | 328 ++++++++++------------- internal/certigo/lib/certs_test.go | 64 +++++ internal/certigo/lib/tls/ca.crl | 16 ++ internal/certigo/lib/tls/ca.crt | 28 ++ internal/certigo/lib/tls/ca.der | Bin 0 -> 1246 bytes internal/certigo/lib/tls/ca.key | 51 ++++ internal/certigo/lib/tls/client.cer | 101 +++++++ internal/certigo/lib/tls/client.crt | 25 ++ internal/certigo/lib/tls/client.csr | 16 ++ internal/certigo/lib/tls/client.der | Bin 0 -> 1078 bytes internal/certigo/lib/tls/client.guess | 101 +++++++ internal/certigo/lib/tls/client.key | 27 ++ internal/certigo/lib/tls/client.pfx | Bin 0 -> 3973 bytes internal/certigo/lib/tls/client_pass.pfx | Bin 0 -> 3973 bytes internal/certigo/lib/tls/gen.sh | 18 ++ 17 files changed, 655 insertions(+), 227 deletions(-) create mode 100644 internal/certigo/lib/cert_key_format.go create mode 100644 internal/certigo/lib/certs_test.go create mode 100644 internal/certigo/lib/tls/ca.crl create mode 100644 internal/certigo/lib/tls/ca.crt create mode 100644 internal/certigo/lib/tls/ca.der create mode 100644 internal/certigo/lib/tls/ca.key create mode 100644 internal/certigo/lib/tls/client.cer create mode 100644 internal/certigo/lib/tls/client.crt create mode 100644 internal/certigo/lib/tls/client.csr create mode 100644 internal/certigo/lib/tls/client.der create mode 100644 internal/certigo/lib/tls/client.guess create mode 100644 internal/certigo/lib/tls/client.key create mode 100644 internal/certigo/lib/tls/client.pfx create mode 100644 internal/certigo/lib/tls/client_pass.pfx create mode 100755 internal/certigo/lib/tls/gen.sh diff --git a/cmd/grpcurl/grpcurl.go b/cmd/grpcurl/grpcurl.go index 6b0fbcf..ca7bbc4 100644 --- a/cmd/grpcurl/grpcurl.go +++ b/cmd/grpcurl/grpcurl.go @@ -73,13 +73,11 @@ var ( when use PEM/DER certificate file.`)) pCertFormat = flags.String("cert-format", string(lib.CertKeyFormatPEM), prettify(` cert Format of given input (PEM, DER, PKCS12; heuristic if missing).`)) - pass = flags.String("pass", "", prettify(` - Pass phrase for the key`)) + certPass = flags.String("pass", "", prettify(` + Pass phrase for the PKCS12 cert`)) key = flags.String("key", "", prettify(` File containing client private key, to present to the server. Not valid with -plaintext option. Must also provide -cert option.`)) - pKeyFormat = flags.String("key-format", string(lib.CertKeyFormatPEM), prettify(` - key Format of given input (PEM, DER; heuristic if missing).`)) // ALTS Options usealts = flags.Bool("alts", false, prettify(` @@ -300,7 +298,7 @@ func main() { usetls := !*plaintext && !*usealts cacertFormat := lib.NewCertificateKeyFormat(*pCACertFormat) certFormat := lib.NewCertificateKeyFormat(*pCertFormat) - keyFormat := lib.NewCertificateKeyFormat(*pKeyFormat) + keyFormat := lib.CertKeyFormatPEM // Do extra validation on arguments and figure out what user asked us to do. if *connectTimeout < 0 { @@ -330,55 +328,45 @@ func main() { if usetls { if *cacert != "" { - if cacertFormat.IsNone() { - guessFormat, err := lib.GuessFormatForFile(*cacert, "") - if err != nil { - fail(nil, "Fail to guess file format of -key err: %s", err) - } - cacertFormat.Set(guessFormat) + guessFormat, err := lib.GuessFormatForFile(*cacert, cacertFormat) + if err != nil { + fail(nil, "Fail to guess file format of -key err: %s", err) } - switch cacertFormat { + switch guessFormat { case lib.CertKeyFormatPEM, lib.CertKeyFormatDER: - // do nothing + cacertFormat = guessFormat default: - fail(nil, "The -cacert-format %s not support.", keyFormat) + fail(nil, "The -cacert-format %s not support.", cacertFormat) } } if *cert != "" { - if certFormat.IsNone() { - guessFormat, err := lib.GuessFormatForFile(*cert, "") - if err != nil { - fail(nil, "Fail to guess file format of -cert err: %s", err) - } - certFormat.Set(guessFormat) + guessFormat, err := lib.GuessFormatForFile(*cert, certFormat) + if err != nil { + fail(nil, "Fail to guess file format of -cert err: %s", err) } - switch certFormat { + switch guessFormat { case lib.CertKeyFormatPEM, lib.CertKeyFormatDER: if *cert == "" || *key == "" { fail(nil, "The -cert and -key arguments must be used together and both be present.") } + certFormat = guessFormat case lib.CertKeyFormatPKCS12: - // do nothing + certFormat = guessFormat default: fail(nil, "The -cert-format %s not support.", certFormat) } } - if *key != "" { - if keyFormat.IsNone() { - guessFormat, err := lib.GuessFormatForFile(*key, "") - if err != nil { - fail(nil, "Fail to guess file format of -key err: %s", err) - } - keyFormat.Set(guessFormat) - } - switch keyFormat { - case lib.CertKeyFormatPEM, lib.CertKeyFormatDER: - if *cert == "" || *key == "" { - fail(nil, "The -cert and -key arguments must be used together and both be present.") - } + if *certPass != "" { + switch certFormat { + case lib.CertKeyFormatPKCS12: default: - fail(nil, "The -key-format %s not support.", keyFormat) + fail(nil, "The -pass argument is only supported when -cert-type is PKCS12.") + } + } + if *key != "" { + if *cert == "" || *key == "" { + fail(nil, "The -cert and -key arguments must be used together and both be present.") } } @@ -518,7 +506,7 @@ func main() { } creds = alts.NewClientCreds(clientOptions) } else if usetls { - tlsConf, err := lib.ClientTLSConfigV2(*insecure, *cacert, cacertFormat, *cert, certFormat, *key, keyFormat, *pass) + tlsConf, err := lib.ClientTLSConfigV2(*insecure, *cacert, cacertFormat, *cert, certFormat, *key, keyFormat, *certPass) if err != nil { fail(err, "Failed to create TLS config") } diff --git a/internal/certigo/lib/cert_key_format.go b/internal/certigo/lib/cert_key_format.go new file mode 100644 index 0000000..b6f038e --- /dev/null +++ b/internal/certigo/lib/cert_key_format.go @@ -0,0 +1,45 @@ +package lib + +import ( + "strings" +) + +func NewCertificateKeyFormat(fileFormat string) CertificateKeyFormat { + fileFormat = strings.ToUpper(fileFormat) + switch fileFormat { + case "": + return CertKeyFormatNONE + case "PEM": + return CertKeyFormatPEM + case "DER": + return CertKeyFormatDER + case "JCEKS": + return CertKeyFormatJCEKS + case "PKCS12", "P12": + return CertKeyFormatPKCS12 + default: + return CertKeyFormatNONE + } +} + +type CertificateKeyFormat string + +const ( + CertKeyFormatNONE CertificateKeyFormat = "" + // The file contains plain-text PEM data + CertKeyFormatPEM CertificateKeyFormat = "PEM" + // The file contains X.509 DER encoded data + CertKeyFormatDER CertificateKeyFormat = "DER" + // The file contains JCEKS keystores + CertKeyFormatJCEKS CertificateKeyFormat = "JCEKS" + // The file contains PFX data describing PKCS#12 + CertKeyFormatPKCS12 CertificateKeyFormat = "PKCS12" +) + +func (f *CertificateKeyFormat) Set(fileFormat string) { + *f = NewCertificateKeyFormat(fileFormat) +} + +func (f CertificateKeyFormat) IsNone() bool { + return f == CertKeyFormatNONE +} diff --git a/internal/certigo/lib/certs.go b/internal/certigo/lib/certs.go index e7284af..81d47ac 100644 --- a/internal/certigo/lib/certs.go +++ b/internal/certigo/lib/certs.go @@ -48,97 +48,42 @@ const ( fileHeader = "originFile" ) -var fileExtToFormat = map[string]string{ - ".pem": "PEM", - ".crt": "PEM", - ".cer": "PEM", - ".p7b": "PEM", - ".p7c": "PEM", - ".p12": "PKCS12", - ".pfx": "PKCS12", - ".jceks": "JCEKS", - ".jks": "JCEKS", // Only partially supported - ".der": "DER", +var fileExtToFormat = map[string]CertificateKeyFormat{ + ".pem": CertKeyFormatPEM, + ".crt": CertKeyFormatPEM, + ".p7b": CertKeyFormatPEM, + ".p7c": CertKeyFormatPEM, + ".p12": CertKeyFormatPKCS12, + ".pfx": CertKeyFormatPKCS12, + ".jceks": CertKeyFormatJCEKS, + ".jks": CertKeyFormatJCEKS, // Only partially supported + ".der": CertKeyFormatDER, } -var badSignatureAlgorithms = [...]x509.SignatureAlgorithm{ - x509.MD2WithRSA, - x509.MD5WithRSA, - x509.SHA1WithRSA, - x509.DSAWithSHA1, - x509.ECDSAWithSHA1, -} +//var badSignatureAlgorithms = [...]x509.SignatureAlgorithm{ +// x509.MD2WithRSA, +// x509.MD5WithRSA, +// x509.SHA1WithRSA, +// x509.DSAWithSHA1, +// x509.ECDSAWithSHA1, +//} -func errorFromErrors(errs []error) error { - if len(errs) == 0 { - return nil - } - if len(errs) == 1 { - return errs[0] - } - buffer := new(bytes.Buffer) - buffer.WriteString("encountered multiple errors:\n") - for _, err := range errs { - buffer.WriteString("* ") - buffer.WriteString(strings.TrimSuffix(err.Error(), "\n")) - buffer.WriteString("\n") - } - return errors.New(buffer.String()) -} - -func NewCertificateKeyFormat(fileFormat string) CertificateKeyFormat { - fileFormat = strings.ToUpper(fileFormat) - switch fileFormat { - case "": - return CertKeyFormatNONE - case "PEM": - return CertKeyFormatPEM - case "DER": - return CertKeyFormatDER - case "PKCS12", "P12": - return CertKeyFormatPKCS12 - default: - return CertKeyFormatNONE - } -} - -type CertificateKeyFormat string - -const ( - CertKeyFormatNONE CertificateKeyFormat = "" - // The file contains plain-text PEM data - CertKeyFormatPEM CertificateKeyFormat = "PEM" - // The file contains X.509 DER encoded data - CertKeyFormatDER CertificateKeyFormat = "DER" - // The file contains JCEKS keystores - CertKeyFormatJCEKS CertificateKeyFormat = "JCEKS" - // The file contains PFX data describing PKCS#12 - CertKeyFormatPKCS12 CertificateKeyFormat = "PKCS12" -) - -func (f *CertificateKeyFormat) Set(fileFormat string) { - *f = NewCertificateKeyFormat(fileFormat) -} - -func (f CertificateKeyFormat) IsNone() bool { - return f == CertKeyFormatNONE -} - -func (f *CertificateKeyFormat) SetPEM() { - *f = CertKeyFormatPEM -} - -func (f CertificateKeyFormat) IsPEM() bool { - return f == CertKeyFormatPEM -} - -func (f CertificateKeyFormat) IsDER() bool { - return f == CertKeyFormatDER -} - -func (f CertificateKeyFormat) IsPKCS12() bool { - return f == CertKeyFormatPKCS12 -} +//func errorFromErrors(errs []error) error { +// if len(errs) == 0 { +// return nil +// } +// if len(errs) == 1 { +// return errs[0] +// } +// buffer := new(bytes.Buffer) +// buffer.WriteString("encountered multiple errors:\n") +// for _, err := range errs { +// buffer.WriteString("* ") +// buffer.WriteString(strings.TrimSuffix(err.Error(), "\n")) +// buffer.WriteString("\n") +// } +// return errors.New(buffer.String()) +//} // ClientTLSConfigV2 builds transport-layer config for a gRPC client using the // given properties. Support certificate file both PEM and P12. @@ -147,7 +92,7 @@ func ClientTLSConfigV2(insecureSkipVerify bool, cacertFile string, cacertFormat if clientCertFile != "" { // Load the client certificates - pemCertBytes, err := readAsPEMEx2(clientCertFile, string(certFormat), clientPass) + pemCertBytes, err := readAsPEMEx(clientCertFile, certFormat, clientPass) if err != nil { return nil, fmt.Errorf("could not load client cert: %v", err) } @@ -155,7 +100,7 @@ func ClientTLSConfigV2(insecureSkipVerify bool, cacertFile string, cacertFormat // Load the client key if clientKeyFile != "" { - pemBytes, err := readAsPEMEx2(clientKeyFile, string(keyFormat), clientPass) + pemBytes, err := readAsPEMEx(clientKeyFile, keyFormat, clientPass) if err != nil { return nil, fmt.Errorf("could not load client key: %v", err) } @@ -174,13 +119,12 @@ func ClientTLSConfigV2(insecureSkipVerify bool, cacertFile string, cacertFormat tlsConf.InsecureSkipVerify = true } else if cacertFile != "" { // Create a certificate pool from the certificate authority - certPool := x509.NewCertPool() - pemCACertBytes, err := readAsPEMEx2(cacertFile, string(cacertFormat), "") + pemCACertBytes, err := readAsPEMEx(cacertFile, cacertFormat, "") if err != nil { return nil, fmt.Errorf("could not load cacert : %v", err) } - // Append the certificates from the CA + certPool := x509.NewCertPool() if ok := certPool.AppendCertsFromPEM(pemCACertBytes); !ok { return nil, errors.New("failed to append ca certs") } @@ -191,7 +135,12 @@ func ClientTLSConfigV2(insecureSkipVerify bool, cacertFile string, cacertFormat return &tlsConf, nil } -func GuessFormatForFile(filename, format string) (string, error) { +func GuessFormatForFile(filename string, format CertificateKeyFormat) (CertificateKeyFormat, error) { + // First, honor --format flag we got from user + if !format.IsNone() { + return format, nil + } + // Second, attempt to guess based on extension guess, ok := fileExtToFormat[strings.ToLower(filepath.Ext(filename))] if ok { @@ -200,7 +149,7 @@ func GuessFormatForFile(filename, format string) (string, error) { file, err := os.Open(filename) if err != nil { - return "", fmt.Errorf("unable to open file: %s\n", err) + return CertKeyFormatNONE, fmt.Errorf("unable to open file: %s\n", err) } defer file.Close() reader := bufio.NewReaderSize(file, 4) @@ -208,60 +157,60 @@ func GuessFormatForFile(filename, format string) (string, error) { // Third, attempt to guess based on first 4 bytes of input data, err := reader.Peek(4) if err != nil { - return "", fmt.Errorf("unable to read file: %s\n", err) + return CertKeyFormatNONE, fmt.Errorf("unable to read file: %s\n", err) } // Heuristics for guessing -- best effort. magic := binary.BigEndian.Uint32(data) + fmt.Printf(" magic 0x%0x\n", magic) if magic == 0xCECECECE || magic == 0xFEEDFEED { // JCEKS/JKS files always start with this prefix - return "JCEKS", nil + return CertKeyFormatJCEKS, nil } - if magic == 0x2D2D2D2D || magic == 0x434f4e4e { - // Starts with '----' or 'CONN' (what s_client prints...) - // TODO start with 'Certificate' - return "PEM", nil + if magic == 0x2D2D2D2D { + // Starts with '----' + return CertKeyFormatPEM, nil + } + if magic == 0x434f4e4e { + // Starts with 'CONN' (what s_client prints...) + return CertKeyFormatPEM, nil + } + if magic == 0x43657274 { + // Starts with 'Cert' (what openssl x509 -text -in tls/client.crt prints...) + return CertKeyFormatPEM, nil } if magic&0xFFFF0000 == 0x30820000 { // Looks like the input is DER-encoded, so it's either PKCS12 or X.509. if magic&0x0000FF00 == 0x0300 { // Probably X.509 - return "DER", nil + return CertKeyFormatDER, nil } - return "PKCS12", nil + return CertKeyFormatPKCS12, nil } - return "", nil + return CertKeyFormatNONE, fmt.Errorf("unable to guess format for %v magic 0x%0x", filename, magic) } -func readAsPEMEx2(filename string, format string, password string) ([]byte, error) { +func readAsPEMEx(filename string, format CertificateKeyFormat, password string) ([]byte, error) { var pembuf bytes.Buffer - err := readAsPEMEx(filename, format, "", func(block *pem.Block, format string) error { + pembufFunc := func(block *pem.Block, format CertificateKeyFormat) error { return pem.Encode(&pembuf, block) - }) - if err != nil { - return nil, fmt.Errorf("could not load client cert: %v", err) } - return pembuf.Bytes(), nil -} - -func readAsPEMEx(filename string, format string, password string, callback func(*pem.Block, string) error) error { - rawFile, err := os.Open(filename) - if err != nil { - return fmt.Errorf("unable to open file: %s\n", err) - } - defer rawFile.Close() passwordFunc := func(promet string) string { return password } - reader := bufio.NewReaderSize(rawFile, 4) - format, err = formatForFile(reader, "", format) + rawFile, err := os.Open(filename) if err != nil { - return fmt.Errorf("unable to guess format for input stream") + return nil, fmt.Errorf("unable to open file: %s\n", err) } + defer rawFile.Close() - return readCertsFromStream(reader, "", format, passwordFunc, callback) + err = readCertsFromStream(rawFile, "", format, passwordFunc, pembufFunc) + if err != nil { + return nil, fmt.Errorf("could not read file: %s\n", err) + } + return pembuf.Bytes(), nil } // // ReadAsPEMFromFiles will read PEM blocks from the given set of inputs. Input @@ -287,26 +236,26 @@ func readAsPEMEx(filename string, format string, password string, callback func( // } // -// ReadAsPEM will read PEM blocks from the given set of inputs. Input data may -// be in plain-text PEM files, DER-encoded certificates or PKCS7 envelopes, or -// PKCS12/JCEKS keystores. All inputs will be converted to PEM blocks and -// passed to the callback. -func ReadAsPEM(readers []io.Reader, format string, password func(string) string, callback func(*pem.Block, string) error) error { - errs := []error{} - for _, r := range readers { - reader := bufio.NewReaderSize(r, 4) - format, err := formatForFile(reader, "", format) - if err != nil { - return fmt.Errorf("unable to guess format for input stream") - } - - err = readCertsFromStream(reader, "", format, password, callback) - if err != nil { - errs = append(errs, err) - } - } - return errorFromErrors(errs) -} +//// ReadAsPEM will read PEM blocks from the given set of inputs. Input data may +//// be in plain-text PEM files, DER-encoded certificates or PKCS7 envelopes, or +//// PKCS12/JCEKS keystores. All inputs will be converted to PEM blocks and +//// passed to the callback. +//func ReadAsPEM(readers []io.Reader, format string, password func(string) string, callback func(*pem.Block, string) error) error { +// errs := []error{} +// for _, r := range readers { +// reader := bufio.NewReaderSize(r, 4) +// format, err := formatForFile(reader, "", format) +// if err != nil { +// return fmt.Errorf("unable to guess format for input stream") +// } +// +// err = readCertsFromStream(reader, "", format, password, callback) +// if err != nil { +// errs = append(errs, err) +// } +// } +// return errorFromErrors(errs) +//} //// ReadAsX509FromFiles will read X.509 certificates from the given set of //// inputs. Input data may be in plain-text PEM files, DER-encoded certificates @@ -380,15 +329,14 @@ func ReadAsPEM(readers []io.Reader, format string, password func(string) string, //} // readCertsFromStream takes some input and converts it to PEM blocks. -func readCertsFromStream(reader io.Reader, filename string, format string, password func(string) string, callback func(*pem.Block, string) error) error { +func readCertsFromStream(reader io.Reader, filename string, format CertificateKeyFormat, password func(string) string, callback func(*pem.Block, CertificateKeyFormat) error) error { headers := map[string]string{} if filename != "" && filename != os.Stdin.Name() { headers[fileHeader] = filename } - format = strings.TrimSpace(format) switch format { - case "PEM": + case CertKeyFormatPEM: scanner := pemScanner(reader) for scanner.Scan() { block, _ := pem.Decode(scanner.Bytes()) @@ -399,7 +347,7 @@ func readCertsFromStream(reader io.Reader, filename string, format string, passw } } return nil - case "DER": + case CertKeyFormatDER: data, err := ioutil.ReadAll(reader) if err != nil { return fmt.Errorf("unable to read input: %s\n", err) @@ -407,6 +355,7 @@ func readCertsFromStream(reader io.Reader, filename string, format string, passw x509Certs, err0 := x509.ParseCertificates(data) if err0 == nil { for _, cert := range x509Certs { + fmt.Printf("cert cn: %v\n", cert.Issuer.CommonName) err := callback(encodeX509ToPEM(cert, headers), format) if err != nil { return err @@ -425,7 +374,7 @@ func readCertsFromStream(reader io.Reader, filename string, format string, passw return nil } return fmt.Errorf("unable to parse certificates from DER data\n* X.509 parser gave: %s\n* PKCS7 parser gave: %s\n", err0, err1) - case "PKCS12": + case CertKeyFormatPKCS12: data, err := ioutil.ReadAll(reader) if err != nil { return fmt.Errorf("unable to read input: %s\n", err) @@ -442,7 +391,7 @@ func readCertsFromStream(reader io.Reader, filename string, format string, passw } } return nil - case "JCEKS": + case CertKeyFormatJCEKS: keyStore, err := jceks.LoadFromReader(reader, []byte(password(""))) if err != nil { return fmt.Errorf("unable to parse keystore: %s\n", err) @@ -534,48 +483,47 @@ func keyToPem(key crypto.PrivateKey, headers map[string]string) (*pem.Block, err return nil, fmt.Errorf("unknown key type: %s\n", reflect.TypeOf(key)) } -// formatForFile returns the file format (either from flags or -// based on file extension). -func formatForFile(file *bufio.Reader, filename, format string) (string, error) { - // First, honor --format flag we got from user - if format != "" { - return format, nil - } - - // Second, attempt to guess based on extension - guess, ok := fileExtToFormat[strings.ToLower(filepath.Ext(filename))] - if ok { - return guess, nil - } - - // Third, attempt to guess based on first 4 bytes of input - data, err := file.Peek(4) - if err != nil { - return "", fmt.Errorf("unable to read file: %s\n", err) - } - - // Heuristics for guessing -- best effort. - magic := binary.BigEndian.Uint32(data) - if magic == 0xCECECECE || magic == 0xFEEDFEED { - // JCEKS/JKS files always start with this prefix - return "JCEKS", nil - } - if magic == 0x2D2D2D2D || magic == 0x434f4e4e { - // Starts with '----' or 'CONN' (what s_client prints...) - // TODO start with 'Certificate' - return "PEM", nil - } - if magic&0xFFFF0000 == 0x30820000 { - // Looks like the input is DER-encoded, so it's either PKCS12 or X.509. - if magic&0x0000FF00 == 0x0300 { - // Probably X.509 - return "DER", nil - } - return "PKCS12", nil - } - - return "", fmt.Errorf("unable to guess file format") -} +//// formatForFile returns the file format (either from flags or +//// based on file extension). +//func formatForFile(file *bufio.Reader, filename, format string) (string, error) { +// // First, honor --format flag we got from user +// if format != "" { +// return format, nil +// } +// +// // Second, attempt to guess based on extension +// guess, ok := fileExtToFormat[strings.ToLower(filepath.Ext(filename))] +// if ok { +// return string(guess), nil +// } +// +// // Third, attempt to guess based on first 4 bytes of input +// data, err := file.Peek(4) +// if err != nil { +// return "", fmt.Errorf("unable to read file: %s\n", err) +// } +// +// // Heuristics for guessing -- best effort. +// magic := binary.BigEndian.Uint32(data) +// if magic == 0xCECECECE || magic == 0xFEEDFEED { +// // JCEKS/JKS files always start with this prefix +// return "JCEKS", nil +// } +// if magic == 0x2D2D2D2D || magic == 0x434f4e4e { +// // Starts with '----' or 'CONN' (what s_client prints...) +// return "PEM", nil +// } +// if magic&0xFFFF0000 == 0x30820000 { +// // Looks like the input is DER-encoded, so it's either PKCS12 or X.509. +// if magic&0x0000FF00 == 0x0300 { +// // Probably X.509 +// return "DER", nil +// } +// return "PKCS12", nil +// } +// +// return "", fmt.Errorf("unable to guess file format") +//} // pemScanner will return a bufio.Scanner that splits the input // from the given reader into PEM blocks. diff --git a/internal/certigo/lib/certs_test.go b/internal/certigo/lib/certs_test.go new file mode 100644 index 0000000..1676b9c --- /dev/null +++ b/internal/certigo/lib/certs_test.go @@ -0,0 +1,64 @@ +package lib + +import ( + "testing" +) + +func TestClientTLSConfig(t *testing.T) { + derfmt := CertKeyFormatDER + pemfmt := CertKeyFormatPEM + pfxfmt := CertKeyFormatPKCS12 + testTLSConfig(t, false, "tls/ca.crt", pemfmt, "tls/client.crt", pemfmt, "tls/client.key", pemfmt, "") + testTLSConfig(t, false, "tls/ca.crt", pemfmt, "tls/client.der", derfmt, "tls/client.key", pemfmt, "") + testTLSConfig(t, false, "tls/ca.crt", pemfmt, "tls/client.pfx", pfxfmt, "tls/client.key", pemfmt, "") + testTLSConfig(t, false, "tls/ca.crt", pemfmt, "tls/client_pass.pfx", pfxfmt, "", pemfmt, "pfxpassword") + testTLSConfig(t, false, "tls/ca.der", derfmt, "tls/client.pfx", pfxfmt, "", pemfmt, "") + //testTLSConfig(t, false, "tls/ca.crt", pemfmt, "tls/client.crt", pemfmt, "tls/client.key.pass", pemfmt, "123456") // not support + //testTLSConfig(t, false, "tls/ca.crt", pemfmt, "tls/client_pass.pfx", pfxfmt, "", pemfmt, "invalidpwd") // invalid + //testTLSConfig(t, false, "tls/ca.crt", pemfmt, "tls/client.der", derfmt, "tls/client.key.der", derfmt, "") key can not be der +} + +func testTLSConfig( + t *testing.T, + insecure bool, + cacert string, + cacertFormat CertificateKeyFormat, + cert string, + certFormat CertificateKeyFormat, + key string, + keyFormat CertificateKeyFormat, + pass string, +) { + tlsConf, err := ClientTLSConfigV2(insecure, cacert, cacertFormat, cert, certFormat, key, keyFormat, pass) + if err != nil { + t.Fatalf("Failed to create TLS config err: %v", err) + } + if tlsConf == nil || tlsConf.Certificates == nil || tlsConf.RootCAs == nil { + t.Fatal("Failed to create TLS config tlsConf is nil") + } + +} + +func TestGuessFormat(t *testing.T) { + guessFormat(t, "tls/client.crt", CertKeyFormatPEM) + guessFormat(t, "tls/client.cer", CertKeyFormatPEM) + guessFormat(t, "tls/client.key", CertKeyFormatPEM) + guessFormat(t, "tls/client.pfx", CertKeyFormatPKCS12) + guessFormat(t, "tls/client.der", CertKeyFormatDER) + forceFormat(t, "tls/client.guess", CertKeyFormatPEM, CertKeyFormatPEM) +} + +func guessFormat(t *testing.T, filename string, formatExpected CertificateKeyFormat) { + forceFormat(t, filename, formatExpected, CertKeyFormatNONE) +} + +func forceFormat(t *testing.T, filename string, formatExpected, formatForce CertificateKeyFormat) { + guessFormat, err := GuessFormatForFile(filename, formatForce) + if err != nil { + t.Fatalf("failed to guess file err: %v", err) + } + if guessFormat != formatExpected { + t.Fatalf("failed to guess file %v format: %v expected: %v", filename, guessFormat, formatExpected) + } + t.Logf("format %v filename %v", guessFormat, filename) +} diff --git a/internal/certigo/lib/tls/ca.crl b/internal/certigo/lib/tls/ca.crl new file mode 100644 index 0000000..6f75589 --- /dev/null +++ b/internal/certigo/lib/tls/ca.crl @@ -0,0 +1,16 @@ +-----BEGIN X509 CRL----- +MIICfDBmAgEBMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNVBAMTAmNhFw0yMzEwMjQy +MzM5MThaFw0zNTA0MjQyMzM5MTZaMACgIzAhMB8GA1UdIwQYMBaAFAoT7NARRdDN +KQdlVkLUqtOsbJ54MA0GCSqGSIb3DQEBCwUAA4ICAQAdG+TDH5K5Y8xdB+kw9iIW +6icXq47ilbI/TRJbAq9BrmvPZXUI630fXojNijDgRqoSkgtbI+0wQuMqBFLJ0+VK +La4WTucsoYOQz89EJikB6z3m3BFNrubsxLjvNuW3i+ebi3ydH4VE2P7QgRjrW10K +M69pozzYM7CzNkQFmmXUcjcg/EPu4UiN2VQK6WXTTDBae1nGsAiZnsLyHNuFiK/G +9vVtoCDNc26GGaRb33Rh/1hS7hXqUCBQb1EdTNunZzVhAC9JfPdAKWlW35NWyrMz +/llYq3RMvouALXpOtRudi2G+ULto9iZdPGH9WiiVWpYx+Mdl1ab/yf/OzmsU8c1L +GHuh6Lx2Ed2Bz2y58Xk8di5IbER9GyVIecP3NbnL/Xrf0SKyw5WH/BTU66cwZgb6 +aUPjqm+U3TUrNXGnh2FKy77CVUTnQV75GU1V+aFsmyplQUOjIHpTP+sAad88tIsg +AMDcezxBVydZV6Zfl+52pGR2aByd8FYZi27Y0ggh8CyMlrmYTKYRP10RbIHwcaKN +bH6CpxGvQDGXRvn6D7BY9qEVt1v2oQzIW11Gm6ldlWDYzLUG0YaID4RrJ3KP2wfX +0fbpbA35kBL+coZ8iLsH79qR8p90IYdhM4QNwfWfptwPcxxW4y5AfNgFD7hao6Wg +N1Hgooy5gkyxxwNUBlRXOg== +-----END X509 CRL----- diff --git a/internal/certigo/lib/tls/ca.crt b/internal/certigo/lib/tls/ca.crt new file mode 100644 index 0000000..491dfad --- /dev/null +++ b/internal/certigo/lib/tls/ca.crt @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIE2jCCAsKgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDEwJjYTAe +Fw0yMzEwMjQyMzI5MThaFw0zNTA0MjQyMzM5MTZaMA0xCzAJBgNVBAMTAmNhMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAm+lCc8AxpzKpx65+fJIb/kX+ +2wmRKjwZ107lsJRhKlEGZEyN6ncgIoDhsaZKBqcBtE8C4QqxWsocKLlb0irP1rnP +nfvUxglA0JFnHElq6KqfsW0aXcNe4DUU9iS2p69uvG/1aAEyUH5DMP0EpncJCLKp +1tw7lehQdNNFUtOdiMpfo88iiP+ECHdPEz3ZRmy9rjzXvWwd72AbH0x2/n7BE3SI +Q4njXDzFt1DZo/d2WssV1/Lghop5vQqeuUQS905Oc+VtKZ+OB52bTrqWsjvc+m8b +/bIUDTsKbR2Gm+/cTjLsjN5GgjAt0kVCS+N1iXSuvlJ/PfeQadk3XugPq20IWdF+ +VlcWe45qrrEjmpBaqrHOKW1DzNjW2yRNmXTz7R3IncnzdFc6pGbpTLtHQ+qnWJ4c +5xCw7SOHdVWFgTBTWd/NMIbDQRwNWcJheFQKTGKwaEJ2uP/s7PNJkcyPH1LNzgfv +MH93zbSw1KNyO36Vslc4cd/lrgtY+b/oMsr49dOn52iNKcJQospcgRJR3S2vkdKx +6i+SFyHSTjP35W04eDRLvK6JNcs3S6yrnyc5bAasvk1gOaosru4/ffEWxXNtQxmi +4FiGUpEpzdCySy3rmnrvEuos269jC79ecS80QzEi825BcMtgStjo0sFfddLiZhx+ +C0wMPv4e95M8YI1cc08CAwEAAaNFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB +/wQIMAYBAf8CAQAwHQYDVR0OBBYEFAoT7NARRdDNKQdlVkLUqtOsbJ54MA0GCSqG +SIb3DQEBCwUAA4ICAQBMFWBTyqLqK3ZMOXDupvyMGkjbGP3G4IbVd3e5gjya0qJ9 +w7HhaUT+W/WjfvZ/AjMp3oweSqa1v2hpRQ9nh7odxRuOtOqiE85TCQDBmxyILWN4 +uDWmUFMD5P0rOxwICLLaPy1TCFU/9PlYfO6OT0gj4FNtwK0Z2P7vl920WOpPaKfk +caTH9c1ZovZKCDgrJxWFk+XJdLQX5xTMPZdjPwZxvZnPp1RU2ZyUJKb5uBC6slMU +fPMpmYwd7kt03IyqMepqDRYFI79Va9d6J+E3+yeCbvsgVaZhKX1crHDK2MqkV+TG +E1q+r3VpxCD4efqWaUJDHE9YSbDG8pCT6yM+H4hooSJfTgTKS6Ip/PhEtaM5D02j +vnLwQkf+kB96bJ6ks5RolIsPgH9Y7lZ95sz4xoBT906AjemW+Z76wiMovrOeqa7g +eXy8sSQIxAVhg+oQOS9z2ryt/H/g3AJnMdpcRz+/yd0hFRvFiIY3oUwaaAprcLD/ +a3X5+YKv1LFB9UohigroCofh0RtDXSX83cuP472Ant50qXk7D3WhdLzHLc1hgpPx +5jedrwzBh5VMW/fqhjqz2kCvS50ed+t83/kO9VGwyviiyipmw0VebDp3nCKmD1cx +VqL063NkQC83ijAG+GdeWYydqAqPikxcJnWunfbLFcr73lHjjLA64d+CE+rZOQ== +-----END CERTIFICATE----- diff --git a/internal/certigo/lib/tls/ca.der b/internal/certigo/lib/tls/ca.der new file mode 100644 index 0000000000000000000000000000000000000000..b64fce383c3197018dcffa202dda31ea30d1f4ad GIT binary patch literal 1246 zcmV<41R?t{f&|(yf&#*z0|Eg80s#Rq4F(A+hDe6@4FLfQ1pqJ&F$*vW1_M-@${Z-UThc1e*16A}`_#q>K+utA z97$^Es-LlK8ePL);58KXB(|roZoF^xXaO=%enT+*1g3Wh2(qcx+&h)%P;}EpQq!G? z%3q_;B8dNl2zO5tJ=sQVy{hGycK&|B6Lg3}iQ`;6#kWw|qxW`N%N5u1 z;D(BMy$YVWL=yK-PIKjLDW8r9otsX&ma;qC`fnTkvJ?$F3T+*RoA2CCGVF}rMuIRc z(nUf`<8_I2uD()#J@=4l**9M3536kmSU$eqdabXPj0X6a13M?>nTSe_i`5U}kdhjmqjfiP29-_0R0>RD zuxLVdxc}_z^GT7+j~`Oa&Ij)>e|OEau+*b+JARe2S2%Is<*o}@`M>Bg%J}uur{`#m zDZ)^q%3OgGQQa-Ck!H1Ox*D0R}J<1_Mxq>{J(xQFCvEgY% z{#*5p-Xs6_Hq{sEmS)%qz2skSz z6@`=K$#k?A=M>C6mt#K$alM((r&LtgoRlP{`M40evQrd%^C_8(9qvnX+>EL*>S_%Z z1tY&zYu9=w;Wzsyf^PdDRi&8p8CQgD893vsjlF8e7vzF2*d?pgX$1DFLTusY%2 If)nc5Imvf3kpKVy literal 0 HcmV?d00001 diff --git a/internal/certigo/lib/tls/ca.key b/internal/certigo/lib/tls/ca.key new file mode 100644 index 0000000..0c68f59 --- /dev/null +++ b/internal/certigo/lib/tls/ca.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/internal/certigo/lib/tls/client.cer b/internal/certigo/lib/tls/client.cer new file mode 100644 index 0000000..f240b35 --- /dev/null +++ b/internal/certigo/lib/tls/client.cer @@ -0,0 +1,101 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 1c:c0:06:ac:3b:23:e6:29:6a:a1:79:67:5e:e7:c1:98 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=ca + Validity + Not Before: Oct 24 23:29:18 2023 GMT + Not After : Oct 24 23:39:18 2033 GMT + Subject: CN=client + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d1:ec:d0:8f:11:4f:bb:52:15:ff:81:69:98:4d: + 16:fa:3b:93:3b:cb:65:20:14:cb:92:b9:aa:07:fc: + 0b:92:85:a8:ef:66:ff:e9:70:57:f8:b0:4f:cb:dc: + a4:18:b3:e6:ee:3e:2d:2a:e6:fe:7f:0d:8d:05:47: + b0:2b:b0:1d:6c:77:dd:1a:fb:f0:ac:a2:49:a4:6f: + 77:ec:b6:f1:da:e6:3b:90:08:eb:2d:8a:be:4d:57: + ff:da:fa:c2:5c:a2:67:68:f3:4e:2f:cd:b1:20:09: + fa:7c:7f:62:cb:1b:98:90:1c:58:74:d5:27:68:a9: + 98:20:39:e8:b1:53:55:7f:64:38:e5:68:ef:b3:2e: + 51:e3:2e:2a:56:1e:93:c9:ff:16:9c:a0:46:b4:86: + b9:a5:f4:d8:7f:72:ec:15:7e:8a:98:59:ee:e7:76: + 0f:57:85:3e:80:d2:79:0a:b3:15:4d:5e:38:c8:60: + 3f:10:62:12:6c:a6:97:4a:da:93:44:93:8c:2f:8a: + dd:0a:26:41:fb:2b:80:dc:93:2b:18:99:56:27:21: + cf:24:df:21:0e:a9:a6:21:41:cd:d9:0b:19:62:4a: + 03:b5:ad:a7:be:bd:1e:80:b5:da:e1:0e:e7:28:5d: + 41:cf:f2:30:6e:6f:7f:7f:ac:11:5a:44:1d:87:87: + 6f:cb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Data Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Subject Key Identifier: + 86:F9:9A:9A:8E:0B:23:62:72:65:A0:BB:6A:03:4F:A6:AB:50:78:B3 + X509v3 Authority Key Identifier: + keyid:0A:13:EC:D0:11:45:D0:CD:29:07:65:56:42:D4:AA:D3:AC:6C:9E:78 + + X509v3 Subject Alternative Name: + DNS:client.com + Signature Algorithm: sha256WithRSAEncryption + 32:4b:c5:cb:ed:61:4f:f3:98:cc:4b:5d:3e:5e:73:ea:8d:0f: + 20:3c:42:c9:c2:f0:4c:7b:a4:3a:e2:7c:60:ba:a0:41:66:c4: + 62:4f:88:26:4e:9f:28:08:dc:28:67:2f:39:04:fc:9b:2d:74: + d6:57:2b:0f:05:5f:96:85:77:26:11:bd:39:1b:e1:30:7c:ec: + 40:ea:45:2a:3d:d7:2d:95:c5:25:75:09:59:f9:99:0a:9e:81: + bd:2a:f6:87:e7:d4:c3:0f:cf:eb:19:dc:53:96:81:5b:bc:36: + 94:8f:21:fb:8c:5f:13:b1:5e:28:2e:9b:6a:99:d6:3d:16:f8: + b7:96:77:24:99:af:7e:93:06:84:a1:45:fc:22:50:af:cb:9f: + 34:02:92:4c:f4:98:66:ab:d8:27:e2:68:84:e4:cb:f9:af:90: + f2:b0:1f:ae:cc:70:a5:ff:bf:e9:1e:81:bb:d1:1b:5a:a7:fb: + 50:f7:ab:ae:ff:0d:d9:69:c6:76:d6:15:2e:b9:0b:e5:d7:84: + 5a:ae:95:01:d1:e1:cb:8d:b7:ee:58:34:65:89:7e:b2:2b:3b: + cf:ef:b7:78:93:28:19:6b:a6:58:40:18:8b:c1:4d:cc:f7:ef: + 38:06:9a:52:e3:85:6a:ff:9b:09:09:36:f6:a2:d3:e0:c4:b6: + ca:79:90:49:a1:70:08:13:ca:b8:88:16:ad:c2:eb:5f:be:5b: + 25:be:1b:56:7d:b9:78:63:66:41:9a:db:b9:4e:e2:5a:14:28: + 1b:ee:cf:14:52:ed:ff:56:ff:9b:98:06:93:cb:b6:92:77:52: + 81:eb:31:6d:3e:6d:23:d9:c3:ff:38:24:24:66:96:7b:58:dc: + 70:a7:b2:f6:a3:f1:b7:f2:99:84:2a:28:65:ba:65:5f:dd:be: + 04:09:78:e4:42:8b:54:2e:9c:29:16:7f:7f:b5:e9:f6:53:c5: + 26:a0:f5:d9:17:4e:69:b6:ac:2f:73:36:cc:f0:09:37:af:03: + c3:21:5d:87:75:86:1a:72:a1:a0:07:90:34:1d:01:d8:05:37: + 0a:4c:ac:0d:10:b5:85:71:59:b7:96:94:e4:7c:9f:d8:60:7d: + 1e:28:24:58:c9:21:1d:f1:d6:29:f2:5f:25:c6:a4:10:47:11: + 1a:7f:fb:a4:8e:bd:a9:49:1a:9c:8d:7d:2c:83:b3:0c:89:ca: + 12:0c:ed:69:37:0f:d0:0b:a0:2c:1c:67:d0:63:3a:b6:8e:b8: + 21:af:fb:b3:54:19:6d:3c:b6:e1:e2:a3:d5:4f:f8:56:65:4c: + d4:c2:13:9e:e7:31:91:c9:13:b1:f5:14:c8:70:db:7d:d1:cf: + de:46:bd:63:6c:f9:d6:99 +-----BEGIN CERTIFICATE----- +MIIEMjCCAhqgAwIBAgIQHMAGrDsj5ilqoXlnXufBmDANBgkqhkiG9w0BAQsFADAN +MQswCQYDVQQDEwJjYTAeFw0yMzEwMjQyMzI5MThaFw0zMzEwMjQyMzM5MThaMBEx +DzANBgNVBAMTBmNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANHs0I8RT7tSFf+BaZhNFvo7kzvLZSAUy5K5qgf8C5KFqO9m/+lwV/iwT8vcpBiz +5u4+LSrm/n8NjQVHsCuwHWx33Rr78KyiSaRvd+y28drmO5AI6y2Kvk1X/9r6wlyi +Z2jzTi/NsSAJ+nx/YssbmJAcWHTVJ2ipmCA56LFTVX9kOOVo77MuUeMuKlYek8n/ +FpygRrSGuaX02H9y7BV+iphZ7ud2D1eFPoDSeQqzFU1eOMhgPxBiEmyml0rak0ST +jC+K3QomQfsrgNyTKxiZVichzyTfIQ6ppiFBzdkLGWJKA7Wtp769HoC12uEO5yhd +Qc/yMG5vf3+sEVpEHYeHb8sCAwEAAaOBiTCBhjAOBgNVHQ8BAf8EBAMCA7gwHQYD +VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBSG+ZqajgsjYnJl +oLtqA0+mq1B4szAfBgNVHSMEGDAWgBQKE+zQEUXQzSkHZVZC1KrTrGyeeDAVBgNV +HREEDjAMggpjbGllbnQuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQAyS8XL7WFP85jM +S10+XnPqjQ8gPELJwvBMe6Q64nxguqBBZsRiT4gmTp8oCNwoZy85BPybLXTWVysP +BV+WhXcmEb05G+EwfOxA6kUqPdctlcUldQlZ+ZkKnoG9KvaH59TDD8/rGdxTloFb +vDaUjyH7jF8TsV4oLptqmdY9Fvi3lnckma9+kwaEoUX8IlCvy580ApJM9Jhmq9gn +4miE5Mv5r5DysB+uzHCl/7/pHoG70Rtap/tQ96uu/w3ZacZ21hUuuQvl14RarpUB +0eHLjbfuWDRliX6yKzvP77d4kygZa6ZYQBiLwU3M9+84BppS44Vq/5sJCTb2otPg +xLbKeZBJoXAIE8q4iBatwutfvlslvhtWfbl4Y2ZBmtu5TuJaFCgb7s8UUu3/Vv+b +mAaTy7aSd1KB6zFtPm0j2cP/OCQkZpZ7WNxwp7L2o/G38pmEKihlumVf3b4ECXjk +QotULpwpFn9/ten2U8UmoPXZF05ptqwvczbM8Ak3rwPDIV2HdYYacqGgB5A0HQHY +BTcKTKwNELWFcVm3lpTkfJ/YYH0eKCRYySEd8dYp8l8lxqQQRxEaf/ukjr2pSRqc +jX0sg7MMicoSDO1pNw/QC6AsHGfQYzq2jrghr/uzVBltPLbh4qPVT/hWZUzUwhOe +5zGRyROx9RTIcNt90c/eRr1jbPnWmQ== +-----END CERTIFICATE----- diff --git a/internal/certigo/lib/tls/client.crt b/internal/certigo/lib/tls/client.crt new file mode 100644 index 0000000..79b7a12 --- /dev/null +++ b/internal/certigo/lib/tls/client.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEMjCCAhqgAwIBAgIQHMAGrDsj5ilqoXlnXufBmDANBgkqhkiG9w0BAQsFADAN +MQswCQYDVQQDEwJjYTAeFw0yMzEwMjQyMzI5MThaFw0zMzEwMjQyMzM5MThaMBEx +DzANBgNVBAMTBmNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANHs0I8RT7tSFf+BaZhNFvo7kzvLZSAUy5K5qgf8C5KFqO9m/+lwV/iwT8vcpBiz +5u4+LSrm/n8NjQVHsCuwHWx33Rr78KyiSaRvd+y28drmO5AI6y2Kvk1X/9r6wlyi +Z2jzTi/NsSAJ+nx/YssbmJAcWHTVJ2ipmCA56LFTVX9kOOVo77MuUeMuKlYek8n/ +FpygRrSGuaX02H9y7BV+iphZ7ud2D1eFPoDSeQqzFU1eOMhgPxBiEmyml0rak0ST +jC+K3QomQfsrgNyTKxiZVichzyTfIQ6ppiFBzdkLGWJKA7Wtp769HoC12uEO5yhd +Qc/yMG5vf3+sEVpEHYeHb8sCAwEAAaOBiTCBhjAOBgNVHQ8BAf8EBAMCA7gwHQYD +VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBSG+ZqajgsjYnJl +oLtqA0+mq1B4szAfBgNVHSMEGDAWgBQKE+zQEUXQzSkHZVZC1KrTrGyeeDAVBgNV +HREEDjAMggpjbGllbnQuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQAyS8XL7WFP85jM +S10+XnPqjQ8gPELJwvBMe6Q64nxguqBBZsRiT4gmTp8oCNwoZy85BPybLXTWVysP +BV+WhXcmEb05G+EwfOxA6kUqPdctlcUldQlZ+ZkKnoG9KvaH59TDD8/rGdxTloFb +vDaUjyH7jF8TsV4oLptqmdY9Fvi3lnckma9+kwaEoUX8IlCvy580ApJM9Jhmq9gn +4miE5Mv5r5DysB+uzHCl/7/pHoG70Rtap/tQ96uu/w3ZacZ21hUuuQvl14RarpUB +0eHLjbfuWDRliX6yKzvP77d4kygZa6ZYQBiLwU3M9+84BppS44Vq/5sJCTb2otPg +xLbKeZBJoXAIE8q4iBatwutfvlslvhtWfbl4Y2ZBmtu5TuJaFCgb7s8UUu3/Vv+b +mAaTy7aSd1KB6zFtPm0j2cP/OCQkZpZ7WNxwp7L2o/G38pmEKihlumVf3b4ECXjk +QotULpwpFn9/ten2U8UmoPXZF05ptqwvczbM8Ak3rwPDIV2HdYYacqGgB5A0HQHY +BTcKTKwNELWFcVm3lpTkfJ/YYH0eKCRYySEd8dYp8l8lxqQQRxEaf/ukjr2pSRqc +jX0sg7MMicoSDO1pNw/QC6AsHGfQYzq2jrghr/uzVBltPLbh4qPVT/hWZUzUwhOe +5zGRyROx9RTIcNt90c/eRr1jbPnWmQ== +-----END CERTIFICATE----- diff --git a/internal/certigo/lib/tls/client.csr b/internal/certigo/lib/tls/client.csr new file mode 100644 index 0000000..eddc94e --- /dev/null +++ b/internal/certigo/lib/tls/client.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICfjCCAWYCAQAwETEPMA0GA1UEAxMGY2xpZW50MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA0ezQjxFPu1IV/4FpmE0W+juTO8tlIBTLkrmqB/wLkoWo +72b/6XBX+LBPy9ykGLPm7j4tKub+fw2NBUewK7AdbHfdGvvwrKJJpG937Lbx2uY7 +kAjrLYq+TVf/2vrCXKJnaPNOL82xIAn6fH9iyxuYkBxYdNUnaKmYIDnosVNVf2Q4 +5Wjvsy5R4y4qVh6Tyf8WnKBGtIa5pfTYf3LsFX6KmFnu53YPV4U+gNJ5CrMVTV44 +yGA/EGISbKaXStqTRJOML4rdCiZB+yuA3JMrGJlWJyHPJN8hDqmmIUHN2QsZYkoD +ta2nvr0egLXa4Q7nKF1Bz/Iwbm9/f6wRWkQdh4dvywIDAQABoCgwJgYJKoZIhvcN +AQkOMRkwFzAVBgNVHREEDjAMggpjbGllbnQuY29tMA0GCSqGSIb3DQEBCwUAA4IB +AQCk6+YAX3TIhnqV8cUjt++viZrc/DFBAaDhD0NcmKE1SjPwd32UzDDXaunNwWQ8 +htz0dP0x0qSWFQjrUkYbFmUVt4La5kbsNoNNGFJqtVaDbCRI5ye8pg2TUvLkADM2 +daSKMwabNqSAgbW+w1kMk+v9F6A4TFb7Z8/DoRWtWmJS/uR3PkvGOy7skV26+f+t +FCty+DD/2NUe98chXPi2xu9aQld4ZLyWw5KDQqcyS4Gr1fOQQQWENqSM4T76yhuu +LAzpD7sKoqa7u5LsWVr6iQLIhKLU6BHxjZqV7SmGZranIZ0hqWfuRKs04dq/fTXK +GoVHc0Bd9JlPzp0faSgj55jg +-----END CERTIFICATE REQUEST----- diff --git a/internal/certigo/lib/tls/client.der b/internal/certigo/lib/tls/client.der new file mode 100644 index 0000000000000000000000000000000000000000..89ab33f9b5b463eee3f4320484d00fe1dccdf67c GIT binary patch literal 1078 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 literal 0 HcmV?d00001 diff --git a/internal/certigo/lib/tls/gen.sh b/internal/certigo/lib/tls/gen.sh new file mode 100755 index 0000000..a09c529 --- /dev/null +++ b/internal/certigo/lib/tls/gen.sh @@ -0,0 +1,18 @@ + +set -ex + +# generate der and pkcs12 file +openssl x509 -outform der -in tls/ca.crt -out tls/ca.der +openssl x509 -outform der -in tls/client.crt -out tls/client.der +openssl pkcs12 -export \ + -in tls/client.crt \ + -inkey tls/client.key \ + -certfile tls/ca.crt \ + -out tls/client.pfx \ + -password pass: +openssl pkcs12 -export \ + -in tls/client.crt \ + -inkey tls/client.key \ + -certfile tls/ca.crt \ + -out tls/client_pass.pfx \ + -password pass:pfxpassword