diff --git a/crtutil/crt.go b/crtutil/crt.go index 95315e6..4204edb 100644 --- a/crtutil/crt.go +++ b/crtutil/crt.go @@ -9,87 +9,25 @@ import ( ) var ( - ErrNoPEMData = errors.New("no pem data is found") ErrUnknownKeyType = errors.New("unknown private key type in PKCS#8 wrapping") ) -// ParseCertFile parses x509.Certificate from the given file. -// The data is expected to be PEM Encoded and contain one certificate +// ReadAsX509FromFile read x509.Certificate from the given file. +// The data is expected to be PEM Encoded and contain one or more certificates // with PEM type "CERTIFICATE". -// Deprecated: use ReadFileAsX509 instead. -func ParseCertFile(fpath string) (*x509.Certificate, error) { - return ReadFileAsX509(fpath) -} - -// ReadFileAsX509 read x509.Certificate from the given file. -// The data is expected to be PEM Encoded and contain one certificate -// with PEM type "CERTIFICATE". -func ReadFileAsX509(fpath string) (*x509.Certificate, error) { - bs, err := ioutil.ReadFile(fpath) - if err != nil { - return nil, err - } - - return ReadBytesAsX509(bs) -} - -// ParseCertBytes parses a single x509.Certificate from the given data. -// The data is expected to be PEM Encoded and contain one certificate -// with PEM type "CERTIFICATE". -// Deprecated: use ReadBytesAsX509 instead. -func ParseCertBytes(data []byte) (*x509.Certificate, error) { - return ReadBytesAsX509(data) -} - -// ReadBytesAsX509 read x509.Certificate from the given data. -// The data is expected to be PEM Encoded and contain one certificate -// with PEM type "CERTIFICATE". -func ReadBytesAsX509(data []byte) (*x509.Certificate, error) { - if len(data) == 0 { - return nil, nil - } - bl, _ := pem.Decode(data) - if bl == nil { - return nil, ErrNoPEMData - } - cert, err := x509.ParseCertificate(bl.Bytes) - if err != nil { - return nil, err - } - return cert, nil -} - -// ParseCertChainFile parses the x509.Certificate chain from the given file. -// The data is expected to be PEM Encoded and contain one of more certificates -// with PEM type "CERTIFICATE". -// Deprecated: use ReadChainFileAsX509 instead. -func ParseCertChainFile(fpath string) ([]*x509.Certificate, error) { - return ReadChainFileAsX509(fpath) -} - -// ReadChainFileAsX509 read the x509.Certificate chain from the given file. -// The data is expected to be PEM Encoded and contain one of more certificates -// with PEM type "CERTIFICATE". -func ReadChainFileAsX509(fpath string) ([]*x509.Certificate, error) { +func ReadAsX509FromFile(fpath string) ([]*x509.Certificate, error) { bs, err := ioutil.ReadFile(fpath) if err != nil { return nil, err } - return ReadChainBytesAsX509(bs) -} -// ParseCertChainBytes parses x509.Certificate chain from the given data. -// The data is expected to be PEM Encoded and contain one of more certificates -// with PEM type "CERTIFICATE". -// Deprecated: use ReadChainBytesAsX509 instead. -func ParseCertChainBytes(data []byte) ([]*x509.Certificate, error) { - return ReadChainBytesAsX509(data) + return ReadAsX509(bs) } -// ReadChainBytesAsX509 read x509.Certificate chain from the given data. +// ReadAsX509 read x509.Certificate chain from the given data. // The data is expected to be PEM Encoded and contain one of more certificates // with PEM type "CERTIFICATE". -func ReadChainBytesAsX509(data []byte) ([]*x509.Certificate, error) { +func ReadAsX509(data []byte) ([]*x509.Certificate, error) { var ( certs []*x509.Certificate cert *x509.Certificate @@ -111,19 +49,9 @@ func ReadChainBytesAsX509(data []byte) ([]*x509.Certificate, error) { certs = append(certs, cert) } - if len(certs) == 0 { - return nil, ErrNoPEMData - } - return certs, nil } -// CertToPEM converts a x509.Certificate into a PEM block. -// Deprecated: use EncodeX509ToPEM instead. -func CertToPEM(cert *x509.Certificate) []byte { - return EncodeX509ToPEM(cert, nil) -} - // EncodeX509ToPEM converts a x509.Certificate into a PEM block. func EncodeX509ToPEM(cert *x509.Certificate, headers map[string]string) []byte { return pem.EncodeToMemory(&pem.Block{ @@ -133,12 +61,6 @@ func EncodeX509ToPEM(cert *x509.Certificate, headers map[string]string) []byte { }) } -// CertChainToPEM converts a slice of x509.Certificate into PEM block, in the order they are passed. -// Deprecated: use EncodeX509ChainToPEM instead. -func CertChainToPEM(chain []*x509.Certificate) ([]byte, error) { - return EncodeX509ChainToPEM(chain, nil) -} - // EncodeX509ChainToPEM converts a slice of x509.Certificate into PEM block, in the order they are passed. func EncodeX509ChainToPEM(chain []*x509.Certificate, headers map[string]string) ([]byte, error) { var buf bytes.Buffer diff --git a/crtutil/crt_test.go b/crtutil/crt_test.go index 076b5b8..7e66bd6 100644 --- a/crtutil/crt_test.go +++ b/crtutil/crt_test.go @@ -1,65 +1,91 @@ package crtutil import ( - "bytes" - "crypto/x509" - "fmt" - "strings" "testing" "github.com/stretchr/testify/assert" ) -func TestParseCrtFile(t *testing.T) { - _, err := ReadFileAsX509("testdata/server.crt") - assert.NoError(t, err) - // printCrt(t, crt, "server") +func TestReadAsX509FromFile(t *testing.T) { + tests := []struct { + title string + input string + expected int + shoulderr bool + }{ + { + "read server certificate", + "testdata/server.crt", + 1, + false, + }, + { + "returns error while reading a non-existent file", + "testdata/server-non-existent.crt", + 0, + true, + }, + { + "returns 2 CA certificates", + "testdata/server-ca.crt", + 2, + false, + }, + { + "returns 3 certificates", + "testdata/server-3layers.crt", + 3, + false, + }, + { + "returns 3 certificates and ignore redundant characters", + "testdata/server-3layers-withcharacters.crt", + 3, + false, + }, + } + for _, v := range tests { + t.Run(v.title, func(t *testing.T) { + certs, err := ReadAsX509FromFile(v.input) + if v.shoulderr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, v.expected, len(certs)) + } + }) + } - t.Run("parse error with empty data", func(t *testing.T) { - _, err = ReadFileAsX509("testdata/server-fail.crt") - assert.Error(t, err) - }) } func TestParseCertBytes(t *testing.T) { - t.Run("empty data", func(t *testing.T) { - _, err := ReadBytesAsX509([]byte{}) - assert.NoError(t, err) - }) - t.Run("ErrNoPEMData", func(t *testing.T) { - _, err := ReadBytesAsX509([]byte("sdfklhjasdfkjhasdfkjlhas")) - assert.ErrorIs(t, err, ErrNoPEMData) - }) -} - -func TestParseCrtSetFile(t *testing.T) { - crts, err := ReadChainFileAsX509("testdata/server-ca.crt") - assert.NoError(t, err) - assert.Equal(t, 2, len(crts)) - - crts, err = ReadChainFileAsX509("testdata/server-3layers.crt") - assert.NoError(t, err) - assert.Equal(t, 3, len(crts)) - - crts, err = ReadChainFileAsX509("testdata/server-3layers-withcharacters.crt") - assert.NoError(t, err) - assert.Equal(t, 3, len(crts)) - - t.Run("parse error with empty data", func(t *testing.T) { - _, err = ReadChainFileAsX509("testdata/server-fail.crt") - assert.Error(t, err) - }) -} - -func TestParseCertChainBytes(t *testing.T) { - t.Run("ErrNoPEMData", func(t *testing.T) { - _, err := ReadChainBytesAsX509([]byte("sdfklhjasdfkjhasdfkjlhas")) - assert.ErrorIs(t, err, ErrNoPEMData) - }) + tests := []struct { + title string + input []byte + expected int + }{ + { + "empty data, should got 0 certificates", + []byte{}, + 0, + }, + { + "string data, should got 0 certificates", + []byte("sdfklhjasdfkjhasdfkjlhas"), + 0, + }, + } + for _, v := range tests { + t.Run(v.title, func(t *testing.T) { + certs, err := ReadAsX509(v.input) + assert.NoError(t, err) + assert.Equal(t, v.expected, len(certs)) + }) + } } -func TestCertChainToPEM(t *testing.T) { - crts, err := ReadChainFileAsX509("testdata/server-3layers-withcharacters.crt") +func TestEncodeX509ChainToPEM(t *testing.T) { + crts, err := ReadAsX509FromFile("testdata/server-3layers-withcharacters.crt") assert.NoError(t, err) assert.Equal(t, 3, len(crts)) got, err := EncodeX509ChainToPEM(crts, nil) @@ -67,34 +93,9 @@ func TestCertChainToPEM(t *testing.T) { assert.NotEmpty(t, got) } -func TestCertToPEM(t *testing.T) { - crt, err := ReadFileAsX509("testdata/server.crt") +func TestEncodeX509ToPEM(t *testing.T) { + crt, err := ReadAsX509FromFile("testdata/server.crt") assert.NoError(t, err) - got := EncodeX509ToPEM(crt, nil) + got := EncodeX509ToPEM(crt[0], nil) assert.NotEmpty(t, got) } - -func printCrt(t *testing.T, cert *x509.Certificate, name string) { - t.Log("") - t.Logf("%s Certificate Information:", name) - t.Logf(" Issuer: %s", cert.Issuer) - t.Logf(" NotBefore: %s", cert.NotBefore.String()) - t.Logf(" NotAfter: %s", cert.NotAfter.String()) - t.Logf(" Subject: %s", cert.Subject) - - dnsStr := strings.Join(cert.DNSNames, ",") - ipBuf := new(bytes.Buffer) - - for k := range cert.IPAddresses { - if k == 0 { - _, _ = fmt.Fprintf(ipBuf, "%s", cert.IPAddresses[k].String()) - } else { - _, _ = fmt.Fprintf(ipBuf, ", %s", cert.IPAddresses[k].String()) - } - } - t.Logf(" DNSNames: %s", dnsStr) - t.Logf(" IPAddresses: %s", ipBuf.String()) - t.Logf(" KeyUsage: %v", cert.KeyUsage) - t.Logf(" ExtKeyUsage: %v", cert.ExtKeyUsage) - t.Logf(" IsCA: %v", cert.IsCA) -} diff --git a/crtutil/key.go b/crtutil/key.go index 9425d52..d671151 100644 --- a/crtutil/key.go +++ b/crtutil/key.go @@ -10,48 +10,30 @@ import ( "io/ioutil" ) -// ParseKeyFile parses an unencrypted crypto.PrivateKey from the given file. -// Deprecated: use ReadFileAsSigner instead. -func ParseKeyFile(fpath string) (crypto.PrivateKey, error) { - return ReadFileAsSigner(fpath) -} - -// ReadFileAsSigner read a crypto.PrivateKey from the given file. -func ReadFileAsSigner(fpath string) (crypto.PrivateKey, error) { +// ReadAsSignerFromFile read a crypto.PrivateKey from the given file. +func ReadAsSignerFromFile(fpath string) (crypto.PrivateKey, error) { f, err := ioutil.ReadFile(fpath) if err != nil { return nil, err } - return ReadBytesAsSigner(f, false) -} - -// ParseKeyFileWithPass read a crypto.PrivateKey from the given file. -// Deprecated: use ReadFileAsSignerWithPass instead. -func ParseKeyFileWithPass(keyPath, keyPass string) (crypto.PrivateKey, error) { - return ReadFileAsSignerWithPass(keyPath, keyPass) + return ReadAsSigner(f, false) } -// ReadFileAsSignerWithPass read a crypto.PrivateKey from the given file. -func ReadFileAsSignerWithPass(keyPath, keyPass string) (crypto.PrivateKey, error) { +// ReadAsSignerWithPassFromFile read a crypto.PrivateKey from the given file. +func ReadAsSignerWithPassFromFile(keyPath, keyPass string) (crypto.PrivateKey, error) { f, err := ioutil.ReadFile(keyPath) if err != nil { return nil, err } - return readBytesAsSigner(f, []byte(keyPass), false) -} - -// ParseKeyBytes read a crypto.PrivateKey from the given data. -// Deprecated: use ReadBytesAsSigner instead. -func ParseKeyBytes(data []byte, isBase64 bool) (crypto.PrivateKey, error) { - return readBytesAsSigner(data, nil, isBase64) + return readAsSigner(f, []byte(keyPass), false) } -// ReadBytesAsSigner read a crypto.PrivateKey from the given data. -func ReadBytesAsSigner(data []byte, isBase64 bool) (crypto.PrivateKey, error) { - return readBytesAsSigner(data, nil, isBase64) +// ReadAsSigner read a crypto.PrivateKey from the given data. +func ReadAsSigner(data []byte, isBase64 bool) (crypto.PrivateKey, error) { + return readAsSigner(data, nil, isBase64) } -func readBytesAsSigner(key, keypass []byte, isBase64 bool) (crypto.PrivateKey, error) { +func readAsSigner(key, keypass []byte, isBase64 bool) (crypto.PrivateKey, error) { var err error dkeystr := key diff --git a/crtutil/key_test.go b/crtutil/key_test.go index 24788f6..f98dcf8 100644 --- a/crtutil/key_test.go +++ b/crtutil/key_test.go @@ -9,7 +9,7 @@ import ( ) func TestParseKeyFile(t *testing.T) { - prik, err := ReadFileAsSigner("testdata/server-rsa.key") + prik, err := ReadAsSignerFromFile("testdata/server-rsa.key") assert.NoError(t, err) _, ok := prik.(*rsa.PrivateKey) @@ -17,7 +17,7 @@ func TestParseKeyFile(t *testing.T) { } func TestParseKeyFileWithPass(t *testing.T) { - prik, err := ReadFileAsSignerWithPass("testdata/server-rsa.key", "") + prik, err := ReadAsSignerWithPassFromFile("testdata/server-rsa.key", "") assert.NoError(t, err) _, ok := prik.(*rsa.PrivateKey) @@ -28,7 +28,7 @@ func TestParseKeyBytes(t *testing.T) { f, err := ioutil.ReadFile("testdata/server-rsa-base64.key") assert.NoError(t, err) - prik, err := ReadBytesAsSigner(f, true) + prik, err := ReadAsSigner(f, true) assert.NoError(t, err) _, ok := prik.(*rsa.PrivateKey)