| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- package cert
- import (
- "bufio"
- "strings"
- "testing"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- )
- func scanAll(t *testing.T, input string) ([]string, error) {
- t.Helper()
- scanner := bufio.NewScanner(strings.NewReader(input))
- scanner.Split(SplitPEM)
- var blocks []string
- for scanner.Scan() {
- blocks = append(blocks, scanner.Text())
- }
- return blocks, scanner.Err()
- }
- func TestSplitPEM_Single(t *testing.T) {
- input := "-----BEGIN TEST-----\ndata\n-----END TEST-----\n"
- blocks, err := scanAll(t, input)
- require.NoError(t, err)
- require.Len(t, blocks, 1)
- require.Equal(t, input, blocks[0])
- }
- func TestSplitPEM_Multiple(t *testing.T) {
- block1 := "-----BEGIN TEST-----\naaa\n-----END TEST-----\n"
- block2 := "-----BEGIN TEST-----\nbbb\n-----END TEST-----\n"
- blocks, err := scanAll(t, block1+block2)
- require.NoError(t, err)
- require.Len(t, blocks, 2)
- require.Equal(t, block1, blocks[0])
- require.Equal(t, block2, blocks[1])
- }
- func TestSplitPEM_CommentsAndWhitespaceBetweenBlocks(t *testing.T) {
- input := "# comment\n\n-----BEGIN TEST-----\naaa\n-----END TEST-----\n\n# another comment\n\n-----BEGIN TEST-----\nbbb\n-----END TEST-----\n"
- blocks, err := scanAll(t, input)
- require.NoError(t, err)
- require.Len(t, blocks, 2)
- }
- func TestSplitPEM_Empty(t *testing.T) {
- blocks, err := scanAll(t, "")
- require.NoError(t, err)
- require.Empty(t, blocks)
- }
- func TestSplitPEM_WhitespaceOnly(t *testing.T) {
- blocks, err := scanAll(t, " \n\t\n ")
- require.NoError(t, err)
- require.Empty(t, blocks)
- }
- func TestSplitPEM_TrailingGarbage(t *testing.T) {
- input := "-----BEGIN TEST-----\ndata\n-----END TEST-----\ngarbage"
- blocks, err := scanAll(t, input)
- require.ErrorIs(t, err, ErrTruncatedPEMBlock)
- require.Len(t, blocks, 1)
- }
- func TestSplitPEM_TruncatedBlock(t *testing.T) {
- input := "-----BEGIN TEST-----\npartial data with no end"
- _, err := scanAll(t, input)
- require.ErrorIs(t, err, ErrTruncatedPEMBlock)
- }
- func TestSplitPEM_NoEndNewline(t *testing.T) {
- input := "-----BEGIN TEST-----\ndata\n-----END TEST-----"
- blocks, err := scanAll(t, input)
- require.NoError(t, err)
- require.Len(t, blocks, 1)
- require.Equal(t, input, blocks[0])
- }
- func TestSplitPEM_GarbageOnly(t *testing.T) {
- _, err := scanAll(t, "this is not PEM data")
- require.ErrorIs(t, err, ErrTruncatedPEMBlock)
- }
- func TestUnmarshalCertificateFromPEM(t *testing.T) {
- goodCert := []byte(`
- # A good cert
- -----BEGIN NEBULA CERTIFICATE-----
- CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
- vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
- bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
- -----END NEBULA CERTIFICATE-----
- `)
- badBanner := []byte(`# A bad banner
- -----BEGIN NOT A NEBULA CERTIFICATE-----
- CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
- vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
- bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
- -----END NOT A NEBULA CERTIFICATE-----
- `)
- invalidPem := []byte(`# Not a valid PEM format
- -BEGIN NEBULA CERTIFICATE-----
- CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
- vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
- bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
- -END NEBULA CERTIFICATE----`)
- certBundle := appendByteSlices(goodCert, badBanner, invalidPem)
- // Success test case
- cert, rest, err := UnmarshalCertificateFromPEM(certBundle)
- assert.NotNil(t, cert)
- assert.Equal(t, rest, append(badBanner, invalidPem...))
- require.NoError(t, err)
- // Fail due to invalid banner.
- cert, rest, err = UnmarshalCertificateFromPEM(rest)
- assert.Nil(t, cert)
- assert.Equal(t, rest, invalidPem)
- require.EqualError(t, err, "bytes did not contain a proper certificate banner")
- // Fail due to invalid PEM format, because
- // it's missing the requisite pre-encapsulation boundary.
- cert, rest, err = UnmarshalCertificateFromPEM(rest)
- assert.Nil(t, cert)
- assert.Equal(t, rest, invalidPem)
- require.EqualError(t, err, "input did not contain a valid PEM encoded block")
- }
- func TestUnmarshalSigningPrivateKeyFromPEM(t *testing.T) {
- privKey := []byte(`# A good key
- -----BEGIN NEBULA ED25519 PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
- -----END NEBULA ED25519 PRIVATE KEY-----
- `)
- privP256Key := []byte(`# A good key
- -----BEGIN NEBULA ECDSA P256 PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -----END NEBULA ECDSA P256 PRIVATE KEY-----
- `)
- shortKey := []byte(`# A short key
- -----BEGIN NEBULA ED25519 PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- -----END NEBULA ED25519 PRIVATE KEY-----
- `)
- invalidBanner := []byte(`# Invalid banner
- -----BEGIN NOT A NEBULA PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
- -----END NOT A NEBULA PRIVATE KEY-----
- `)
- invalidPem := []byte(`# Not a valid PEM format
- -BEGIN NEBULA ED25519 PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
- -END NEBULA ED25519 PRIVATE KEY-----`)
- keyBundle := appendByteSlices(privKey, privP256Key, shortKey, invalidBanner, invalidPem)
- // Success test case
- k, rest, curve, err := UnmarshalSigningPrivateKeyFromPEM(keyBundle)
- assert.Len(t, k, 64)
- assert.Equal(t, rest, appendByteSlices(privP256Key, shortKey, invalidBanner, invalidPem))
- assert.Equal(t, Curve_CURVE25519, curve)
- require.NoError(t, err)
- // Success test case
- k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
- assert.Len(t, k, 32)
- assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
- assert.Equal(t, Curve_P256, curve)
- require.NoError(t, err)
- // Fail due to short key
- k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
- require.EqualError(t, err, "key was not 64 bytes, is invalid Ed25519 private key")
- // Fail due to invalid banner
- k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, rest, invalidPem)
- require.EqualError(t, err, "bytes did not contain a proper Ed25519/ECDSA private key banner")
- // Fail due to invalid PEM format, because
- // it's missing the requisite pre-encapsulation boundary.
- k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, rest, invalidPem)
- require.EqualError(t, err, "input did not contain a valid PEM encoded block")
- }
- func TestUnmarshalPrivateKeyFromPEM(t *testing.T) {
- privKey := []byte(`# A good key
- -----BEGIN NEBULA X25519 PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -----END NEBULA X25519 PRIVATE KEY-----
- `)
- privP256Key := []byte(`# A good key
- -----BEGIN NEBULA P256 PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -----END NEBULA P256 PRIVATE KEY-----
- `)
- shortKey := []byte(`# A short key
- -----BEGIN NEBULA X25519 PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
- -----END NEBULA X25519 PRIVATE KEY-----
- `)
- invalidBanner := []byte(`# Invalid banner
- -----BEGIN NOT A NEBULA PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -----END NOT A NEBULA PRIVATE KEY-----
- `)
- invalidPem := []byte(`# Not a valid PEM format
- -BEGIN NEBULA X25519 PRIVATE KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -END NEBULA X25519 PRIVATE KEY-----`)
- keyBundle := appendByteSlices(privKey, privP256Key, shortKey, invalidBanner, invalidPem)
- // Success test case
- k, rest, curve, err := UnmarshalPrivateKeyFromPEM(keyBundle)
- assert.Len(t, k, 32)
- assert.Equal(t, rest, appendByteSlices(privP256Key, shortKey, invalidBanner, invalidPem))
- assert.Equal(t, Curve_CURVE25519, curve)
- require.NoError(t, err)
- // Success test case
- k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
- assert.Len(t, k, 32)
- assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
- assert.Equal(t, Curve_P256, curve)
- require.NoError(t, err)
- // Fail due to short key
- k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
- require.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 private key")
- // Fail due to invalid banner
- k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, rest, invalidPem)
- require.EqualError(t, err, "bytes did not contain a proper private key banner")
- // Fail due to invalid PEM format, because
- // it's missing the requisite pre-encapsulation boundary.
- k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, rest, invalidPem)
- require.EqualError(t, err, "input did not contain a valid PEM encoded block")
- }
- func TestUnmarshalPublicKeyFromPEM(t *testing.T) {
- t.Parallel()
- pubKey := []byte(`# A good key
- -----BEGIN NEBULA ED25519 PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -----END NEBULA ED25519 PUBLIC KEY-----
- `)
- shortKey := []byte(`# A short key
- -----BEGIN NEBULA ED25519 PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
- -----END NEBULA ED25519 PUBLIC KEY-----
- `)
- invalidBanner := []byte(`# Invalid banner
- -----BEGIN NOT A NEBULA PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -----END NOT A NEBULA PUBLIC KEY-----
- `)
- invalidPem := []byte(`# Not a valid PEM format
- -BEGIN NEBULA ED25519 PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -END NEBULA ED25519 PUBLIC KEY-----`)
- keyBundle := appendByteSlices(pubKey, shortKey, invalidBanner, invalidPem)
- // Success test case
- k, rest, curve, err := UnmarshalPublicKeyFromPEM(keyBundle)
- assert.Len(t, k, 32)
- assert.Equal(t, Curve_CURVE25519, curve)
- require.NoError(t, err)
- assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
- // Fail due to short key
- k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, Curve_CURVE25519, curve)
- assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
- require.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 public key")
- // Fail due to invalid banner
- k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, Curve_CURVE25519, curve)
- require.EqualError(t, err, "bytes did not contain a proper public key banner")
- assert.Equal(t, rest, invalidPem)
- // Fail due to invalid PEM format, because
- // it's missing the requisite pre-encapsulation boundary.
- k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, Curve_CURVE25519, curve)
- assert.Equal(t, rest, invalidPem)
- require.EqualError(t, err, "input did not contain a valid PEM encoded block")
- }
- func TestUnmarshalX25519PublicKey(t *testing.T) {
- t.Parallel()
- pubKey := []byte(`# A good key
- -----BEGIN NEBULA X25519 PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -----END NEBULA X25519 PUBLIC KEY-----
- `)
- pubP256Key := []byte(`# A good key
- -----BEGIN NEBULA P256 PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAA=
- -----END NEBULA P256 PUBLIC KEY-----
- `)
- oldPubP256Key := []byte(`# A good key
- -----BEGIN NEBULA ECDSA P256 PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAA=
- -----END NEBULA ECDSA P256 PUBLIC KEY-----
- `)
- shortKey := []byte(`# A short key
- -----BEGIN NEBULA X25519 PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
- -----END NEBULA X25519 PUBLIC KEY-----
- `)
- invalidBanner := []byte(`# Invalid banner
- -----BEGIN NOT A NEBULA PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -----END NOT A NEBULA PUBLIC KEY-----
- `)
- invalidPem := []byte(`# Not a valid PEM format
- -BEGIN NEBULA X25519 PUBLIC KEY-----
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- -END NEBULA X25519 PUBLIC KEY-----`)
- keyBundle := appendByteSlices(pubKey, pubP256Key, oldPubP256Key, shortKey, invalidBanner, invalidPem)
- // Success test case
- k, rest, curve, err := UnmarshalPublicKeyFromPEM(keyBundle)
- assert.Len(t, k, 32)
- require.NoError(t, err)
- assert.Equal(t, rest, appendByteSlices(pubP256Key, oldPubP256Key, shortKey, invalidBanner, invalidPem))
- assert.Equal(t, Curve_CURVE25519, curve)
- // Success test case
- k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
- assert.Len(t, k, 65)
- require.NoError(t, err)
- assert.Equal(t, rest, appendByteSlices(oldPubP256Key, shortKey, invalidBanner, invalidPem))
- assert.Equal(t, Curve_P256, curve)
- // Success test case
- k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
- assert.Len(t, k, 65)
- require.NoError(t, err)
- assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
- assert.Equal(t, Curve_P256, curve)
- // Fail due to short key
- k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
- require.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 public key")
- // Fail due to invalid banner
- k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
- assert.Nil(t, k)
- require.EqualError(t, err, "bytes did not contain a proper public key banner")
- assert.Equal(t, rest, invalidPem)
- // Fail due to invalid PEM format, because
- // it's missing the requisite pre-encapsulation boundary.
- k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
- assert.Nil(t, k)
- assert.Equal(t, rest, invalidPem)
- require.EqualError(t, err, "input did not contain a valid PEM encoded block")
- }
|