diff --git a/internal/scti/ctlog_test.go b/internal/scti/ctlog_test.go index 05cac5a2..aaae7f5c 100644 --- a/internal/scti/ctlog_test.go +++ b/internal/scti/ctlog_test.go @@ -3,10 +3,18 @@ package scti import ( "context" "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "os" "strings" "testing" - "github.com/google/trillian/crypto/keys/pem" + trillianpem "github.com/google/trillian/crypto/keys/pem" "github.com/transparency-dev/static-ct/internal/x509util" "github.com/transparency-dev/static-ct/storage" "golang.org/x/mod/sumdb/note" @@ -14,10 +22,14 @@ import ( func TestNewLog(t *testing.T) { ctx := context.Background() - signer, err := pem.ReadPrivateKeyFile("../testdata/ct-http-server.privkey.pem", "dirk") + ecdsaSigner, err := trillianpem.ReadPrivateKeyFile("../testdata/ct-http-server.privkey.pem", "dirk") if err != nil { t.Fatalf("Can't open key: %v", err) } + rsaSigner, err := loadPEMPrivateKey("../testdata/test_rsa_private_key.pem") + if err != nil { + t.Fatalf("Failed to generate RSA key: %v", err) + } roots := x509util.NewPEMCertPool() if err := roots.AppendCertsFromPEMFile("../testdata/fake-ca.cert"); err != nil { t.Fatalf("Can't open roots: %v", err) @@ -34,14 +46,30 @@ func TestNewLog(t *testing.T) { desc: "empty-origin", wantErr: "empty origin", }, - // TODO(phboneff): add a test for a signer of the wrong type + { + desc: "empty-signer", + origin: "testlog", + cvOpts: ChainValidationOpts{ + trustedRoots: roots, + }, + wantErr: "empty signer", + }, { desc: "ok", origin: "testlog", cvOpts: ChainValidationOpts{ trustedRoots: roots, }, - signer: signer, + signer: ecdsaSigner, + }, + { + desc: "incorrect-signer-type", + origin: "testlog", + cvOpts: ChainValidationOpts{ + trustedRoots: roots, + }, + signer: rsaSigner, + wantErr: "unsupported key type", }, } { t.Run(tc.desc, func(t *testing.T) { @@ -61,3 +89,44 @@ func TestNewLog(t *testing.T) { }) } } + +func loadPEMPrivateKey(path string) (crypto.Signer, error) { + keyBytes, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("failed to read key file: %w", err) + } + + block, _ := pem.Decode(keyBytes) + if block == nil { + return nil, errors.New("failed to decode PEM private key") + } + + // Fix block type for testing keys. + block.Type = strings.ReplaceAll(block.Type, "TEST PRIVATE KEY", "PRIVATE KEY") + + var privateKey any + switch block.Type { + case "RSA PRIVATE KEY": + privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) + case "EC PRIVATE KEY": + privateKey, err = x509.ParseECPrivateKey(block.Bytes) + case "PRIVATE KEY": + privateKey, err = x509.ParsePKCS8PrivateKey(block.Bytes) + default: + return nil, fmt.Errorf("unsupported PEM block type: %s", block.Type) + } + if err != nil { + return nil, fmt.Errorf("failed to parse private key: %v", err) + } + + switch key := privateKey.(type) { + case *rsa.PrivateKey: + return key, nil + case *ecdsa.PrivateKey: + return key, nil + case ed25519.PrivateKey: + return key, nil + default: + return nil, errors.New("unsupported private key type") + } +} diff --git a/internal/testdata/test_rsa_private_key.pem b/internal/testdata/test_rsa_private_key.pem new file mode 100644 index 00000000..93d6034f --- /dev/null +++ b/internal/testdata/test_rsa_private_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA TEST PRIVATE KEY----- +MIIEogIBAAKCAQEAlMb0vXCf+XJwvOR8AAeql1NraRVBJYapR3EmeDGALfghvZfn +m65cRS4uVTNnqTRd16bdgzeScpIROErXu8JD+Rg4xMk9uDXphks7DGllcAksaEOu +4Je73H1joJdgP7w3TIAiKhJ9Xx8t2tXh+L+2OcSW/ZSCK87XD20f+mNjZUrYpVbX +PdDr1DrDAvlFblkfDed+xtVIbwPjtTp4eYDYvwJeilvLc/dAw63zg8Qs6NXgAE9x +PQ/O3omhdy8dTEHPRPWg4f3R298alyfCW/GPBON7EPiA242YVavTC572UmGd7ty1 +6CHkxBjaP63qKkp73A/7AvpaAXbKqVFln1ZDGQIDAQABAoIBADCABWPGVdhXRspF +P+kwlpubTa4liCXIFuIb0FspY+xYcgNhBFdbiWfiDKeoyNe/owH8u0Sd9qdT17o+ +p8JlK4yGKWd5ZR3qsVSerMK4jyFtVCUvP1CnFk5kL/i3sGBGps5RDRIjEezS+LtY +s0BImwqM/F3xLlhCpxg3zk9tXAc2VjfMmuEAlpaj1kkHAUkd+rISEiAqXK1sTC2n +Sy+c70vFhg3MZ1VHtj6U2XwkAUJmCKc+yyfNo4KlzwcgiUgodprmJ83hPJuc0H6f +U6TOHEOBgmqimf2BMCCG/1lf+aw2chUtVA43a7p6vTjxxWhCM4NH7n8efJW8VJgW +hbhSbusCgYEAzCdlyn7Eqa2ZY5LXRh1M/spH2pMhuemEl8GCps5zDdghJ1vDJdgE +h1sD82NqTCy7laz9+xJpZg0xnW+Bwp8wzIPDz3Nk4m90OCvcIofmNrkzZwRiFzGa +bdt4mv9hk2L+Ho/u9XlXpEtgkgoPcf8esLNBczwn7xWsOjh9LhVCHc8CgYEAuo9d +w8uqdMlDfzF5DWmbufsh3uzij1hIF5VHQeQvWcRFPdQUvfYdqclA+qgPFx/djOoy +SMmpAwp/GbyvF77YdMsw3PDXM9JGkHEPphTicRwpdj/+AwtlNrcCflzUhWaHeLBp +Jo8c9KdNXB9FkSt1FM3UkPRitVqI1I5jbZOH8pcCgYApTyuEruQCZXMtN9BBirpC +sBGcA7uGT98Zifly4UFcosgKm8HADZbVALCq9gnTQhXu8mMuA4q6MJ9CeQarp+SK +7XqYpoPaYa0FlLJldlQ57H2fMb7bbJkP86HS0yweU6CR9JPordXzE6GFy21WpsXC +AXOT6q817I+99CI4Sern9wKBgBC6zIjDWczRQ5lDYXyfbNSXvajVC1gZbZWX0GUL +RmfBXwg1XYrPaEeSgZ44tem39NEvK0U1uE9KgK1ZK0Zw2c5XblFR06qU/7jyOpoF +I21LPjiZcnjpa7ElZjbYskIoOJvNDhDkIo+Z9Sj+sOlcwUoVTyuUjsl+jeipwCbS +ZQ2PAoGAL8IzB2wc9Lu2SF4Vvs+Jncz3GccU31LLN9l4+IilUbHkqwMse/v1Aer3 +rXwdbIB+W4fvQbYNQMpLHpiuM5iLlhEyEacqYhVN1lngDx+ldcevDosEUXXIeXhd +uVWufi3TCDLGoME6Qb9WxBvVXI3Rb1O0X5pMTXILOpKYfUOJFDg= +-----END RSA TEST PRIVATE KEY-----