diff --git a/pkg/pki/minisign/minisign.go b/pkg/pki/minisign/minisign.go index 995a18c7a..13a587c82 100644 --- a/pkg/pki/minisign/minisign.go +++ b/pkg/pki/minisign/minisign.go @@ -121,17 +121,30 @@ func NewPublicKey(r io.Reader) (*PublicKey, error) { inputString := inputBuffer.String() + // There are three ways a minisign key can be stored. + // 1. The entire text key + // 2. A base64 encoded string + // 3. A legacy format we stored of just the key material (no key ID or Algorithm) key, err := minisign.DecodePublicKey(inputString) - if err != nil { - // try as a standalone base64 string - key, err = minisign.NewPublicKey(inputString) - if err != nil { - return nil, fmt.Errorf("unable to read minisign public key: %w", err) - } + if err == nil { + k.key = &key + return &k, nil + } + key, err = minisign.NewPublicKey(inputString) + if err == nil { + k.key = &key + return &k, nil } - k.key = &key - return &k, nil + if len(inputString) == 32 { + k.key = &minisign.PublicKey{ + SignatureAlgorithm: [2]byte{'E', 'd'}, + KeyId: [8]byte{}, + } + copy(k.key.PublicKey[:], inputBuffer.Bytes()) + return &k, nil + } + return nil, fmt.Errorf("unable to read minisign public key: %w", err) } // CanonicalValue implements the pki.PublicKey interface diff --git a/pkg/pki/minisign/minisign_test.go b/pkg/pki/minisign/minisign_test.go index 15706158b..3dd4ff080 100644 --- a/pkg/pki/minisign/minisign_test.go +++ b/pkg/pki/minisign/minisign_test.go @@ -38,20 +38,59 @@ func TestReadPublicKey(t *testing.T) { } tests := []test{ - {caseDesc: "Not a valid public key file", inputFile: "testdata/hello_world.txt.minisig", errorFound: true}, {caseDesc: "Valid public key (minisign)", inputFile: "testdata/minisign.pub", errorFound: false}, {caseDesc: "Valid public key (signify)", inputFile: "testdata/signify.pub", errorFound: false}, } for _, tc := range tests { - file, err := os.Open(tc.inputFile) - if err != nil { - t.Errorf("%v: cannot open %v", tc.caseDesc, tc.inputFile) - } + t.Run(tc.caseDesc, func(t *testing.T) { + file, err := os.Open(tc.inputFile) + if err != nil { + t.Fatalf("%v: cannot open %v", tc.caseDesc, tc.inputFile) + } - if got, err := NewPublicKey(file); ((got != nil) == tc.errorFound) || ((err != nil) != tc.errorFound) { - t.Errorf("%v: unexpected result testing %v: %v", tc.caseDesc, tc.inputFile, err) - } + got, err := NewPublicKey(file) + if err != nil { + t.Fatalf("unexpected error %v", err) + } + + // Try to send just the raw public key bytes too + rawBytes := got.key.PublicKey[:] + + rawGot, err := NewPublicKey(bytes.NewReader(rawBytes)) + if err != nil { + t.Fatalf("unexpected error re-parsing public key: %v", err) + } + if !bytes.Equal(rawGot.key.PublicKey[:], rawBytes) { + t.Errorf("expected parsed keys to be equal, %v != %v", rawGot.key.PublicKey, rawBytes) + } + }) + } +} + +func TestReadPublicKeyErr(t *testing.T) { + type test struct { + caseDesc string + inputFile string + } + + tests := []test{ + {caseDesc: "Not a valid public key file", inputFile: "testdata/hello_world.txt.minisig"}, + {caseDesc: "Wrong length", inputFile: "testdata/hello_world.txt"}, + } + + for _, tc := range tests { + t.Run(tc.caseDesc, func(t *testing.T) { + file, err := os.Open(tc.inputFile) + if err != nil { + t.Fatalf("%v: cannot open %v", tc.caseDesc, tc.inputFile) + } + + got, err := NewPublicKey(file) + if err == nil { + t.Errorf("error expected, got nil error and %v", got) + } + }) } }