diff --git a/internal/sign/rsa.go b/internal/sign/rsa.go index 6dd60e82..58afb9a1 100644 --- a/internal/sign/rsa.go +++ b/internal/sign/rsa.go @@ -20,6 +20,11 @@ var ( errNoRSAKey = errors.New("key is not an RSA key") ) +const ( + PKCS1PrivkeyPreamble = "RSA PRIVATE KEY" + PKCS8PrivkeyPreamble = "PRIVATE KEY" +) + // RSASignSHA1Digest signs the provided SHA1 message digest. The key file // must be in the PEM format and can either be encrypted or not. func RSASignSHA1Digest(sha1Digest []byte, keyFile, passphrase string) ([]byte, error) { @@ -53,9 +58,26 @@ func RSASignSHA1Digest(sha1Digest []byte, keyFile, passphrase string) ([]byte, e blockData = decryptedBlockData } - priv, err := x509.ParsePKCS1PrivateKey(blockData) - if err != nil { - return nil, fmt.Errorf("parse PKCS1 private key: %w", err) + var priv crypto.Signer + + switch block.Type { + case PKCS1PrivkeyPreamble: + priv, err = x509.ParsePKCS1PrivateKey(blockData) + if err != nil { + return nil, fmt.Errorf("parse PKCS#1 private key: %w", err) + } + case PKCS8PrivkeyPreamble: + privAny, err := x509.ParsePKCS8PrivateKey(blockData) + if err != nil { + return nil, fmt.Errorf("parse PKCS#8 private key: %w", err) + } + privTmp, ok := privAny.(crypto.Signer) + if !ok { + return nil, fmt.Errorf("cannot sign with given private key") + } + priv = privTmp + default: + return nil, fmt.Errorf(`key type "%v" is not supported`, block.Type) } signature, err := priv.Sign(rand.Reader, sha1Digest, crypto.SHA1) diff --git a/internal/sign/rsa_test.go b/internal/sign/rsa_test.go index bbe836ef..839a3029 100644 --- a/internal/sign/rsa_test.go +++ b/internal/sign/rsa_test.go @@ -17,8 +17,9 @@ func TestRSASignAndVerify(t *testing.T) { pubKey string passphrase string }{ - {"unprotected", "testdata/rsa_unprotected.priv", "testdata/rsa_unprotected.pub", ""}, - {"protected", "testdata/rsa.priv", "testdata/rsa.pub", pass}, + {"unprotected pkcs1", "testdata/rsa_unprotected.priv", "testdata/rsa_unprotected.pub", ""}, + {"protected pkcs1", "testdata/rsa.priv", "testdata/rsa.pub", pass}, + {"unprotected pkcs8", "testdata/rsa_pkcs8.priv", "testdata/rsa_pkcs8.pub", ""}, } for _, testCase := range testCases { @@ -54,18 +55,39 @@ func TestInvalidHash(t *testing.T) { func TestRSAVerifyWrongKey(t *testing.T) { digest := sha1.New().Sum(nil) // nolint:gosec - sig, err := rsaSign(bytes.NewReader(digest), "testdata/rsa_unprotected.priv", "") - require.NoError(t, err) + testCases := []struct { + name string + privKey string + pubKey string + }{ + {"pkcs1", "testdata/rsa_unprotected.priv", "testdata/rsa_unprotected.pub"}, + {"pkcs8", "testdata/rsa_pkcs8.priv", "testdata/rsa_pkcs8.pub"}, + } + + for _, testCase := range testCases { + sig, err := rsaSign(bytes.NewReader(digest), testCase.privKey, "") + require.NoError(t, err) - err = RSAVerifySHA1Digest(digest, sig, "testdata/rsa.pub") - require.EqualError(t, err, "verify PKCS1v15 signature: crypto/rsa: verification error") + err = RSAVerifySHA1Digest(digest, sig, testCase.pubKey) + require.EqualError(t, err, "verify PKCS1v15 signature: crypto/rsa: verification error") + } } func TestRSAVerifyWrongSignature(t *testing.T) { digest := sha1.New().Sum(nil) // nolint:gosec - err := RSAVerifySHA1Digest(digest, []byte{}, "testdata/rsa.pub") - require.EqualError(t, err, "verify PKCS1v15 signature: crypto/rsa: verification error") + testCases := []struct { + name string + pubKey string + }{ + {"pkcs1", "testdata/rsa.pub"}, + {"pkcs8", "testdata/rsa_pkcs8.pub"}, + } + + for _, testCase := range testCases { + err := RSAVerifySHA1Digest(digest, []byte{}, testCase.pubKey) + require.EqualError(t, err, "verify PKCS1v15 signature: crypto/rsa: verification error") + } } func TestRSAVerifyWrongPublicKeyFormat(t *testing.T) { diff --git a/internal/sign/testdata/rsa_pkcs8.priv b/internal/sign/testdata/rsa_pkcs8.priv new file mode 100644 index 00000000..dce8973a --- /dev/null +++ b/internal/sign/testdata/rsa_pkcs8.priv @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbfacH7+FQJmKF +2gadVTUGceI/Edjo0RDHG9Y9xLlA1VJ+HppgHGDYkek+kqLRSwcqKJ8g58M8hYRK +saOAa2OnMfgQ+B0qg191i7VwNrCm4YxgbP1t0z1QWUYX4G97hV+wS7MUFVz8+2H1 +2I4aKw3iNoBINIKlDJgVgxvR4v85Ly4sEFT7PNl7xEE7sxIOiDMv/EL+M4HXrdx7 +OCE4IcwyCyJFmBcSoc/qbTO87LDE/K4EBR0Lte/IJApid3u1gwfliOEeyCKVh1JH +AMNJ7s5RjpuW6XJMNMba+CyUTDiGmnbbxvEGvb6trJfDUHd2ChsD+3HR2qx4lNQA +epdUrQsdAgMBAAECggEAMvw3qhTTUlJwTWZtZeuukw4uP3dOWxqBWrcBJ70ESWak +MG68bnn5FyWhuCrIznQuuGDSQgsEI5FiPxWPhNutPN/TH2H7KG525K+s2GGj3EgF +WzrGDdZlZj4ulYpJazh6l1GmShKCVLOyODDzJWn94h/F4b/s3xkTVN/tPO6NWcNJ +MHUM8wYXtUP4jqfJvWljJPFrzKZBRVnB9PV+VtZRtX880VnMwQ76CjC8fLbaJQRT +XXDLl12FkULWQzJieQr8XJLhb8hLSytBovbqbO24NbMjGFx1hxHdwyziceDPtu04 +4R11Zi/YK4DOYi7wrQfxuqyquHH0lAPK648b60HBMwKBgQD2mYzqCq11qHKjrKLV +AR3ufemcN40b7PjcxpXccaNzEzkBaWlRlqhdhO/naLXKHM97hNotji002/whANx5 +0MYcjdo+VnYT/OYmxexVbsLjFsV0B9LOY1zrSyBAxxyjlSTdjBslOXMDtDnPKpZQ +ydjqFqlrpAZNXuOjBtaRVcC7pwKBgQDj24740wfDnuzbOKxcaTzBLf+Ak7aNI3xz +E8e9A2yOUBWhnpmi0fwiws5IE0ghqJBWrjdrwjna+B9Gs6HKMyTNatCYh8SdjxgQ +JivJ3jrKVrP8ixojz/cuNDXC6KJEHvklaLARMO6BPSaB88oR425Y0BZcw2XBNuU/ +JS1YGCLLmwKBgCFWiPJrFyA88aKnCCx7xiwj4Z049V69HrfaMRBoXIyGIMLMGWzq +TUC3ZCeIxGrakkJEp6pY+kuXIfLkRupBC0d49fRPhA8XtZWwVE8Idlh1D6SsGhfE +3x8APRAE2x5SX3WEJ3dU2PO7PcWAIGozn5umDKl8t01mcqfrmL51NWUpAoGAVDtf +EAbbMOq4PpYlyYexyOwbLsnsSyKaJ+RhCzOP1tAuHvAFdZZQsfz3ytct7BtnOFPw +8un6/0KINVfEcH4VlcZt1GUkPuaeC6JAv8BiVVhV8v7tK93+T1tHoITlL2+PxM99 +fu1qzeXwLUwVICXGLhjGm4Y0QIftmTlCGPXbLw8CgYBDiihffbawacxp79CZJUyd +DFvVvCLgwu1K9JRyykxyVPOZAcS/7x5IzRhpQdy51A5xG4WjBkNghGNosbnSaiFr +cCzEtKiNHefbSNUd5T3w8NO97y26BmtylyUrx+qIGr5XWHYFUFmgAmErqFVRLheT +4E9lCp7uSkx2AlbSgs+ugQ== +-----END PRIVATE KEY----- diff --git a/internal/sign/testdata/rsa_pkcs8.pub b/internal/sign/testdata/rsa_pkcs8.pub new file mode 100644 index 00000000..50e644e9 --- /dev/null +++ b/internal/sign/testdata/rsa_pkcs8.pub @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA232nB+/hUCZihdoGnVU1 +BnHiPxHY6NEQxxvWPcS5QNVSfh6aYBxg2JHpPpKi0UsHKiifIOfDPIWESrGjgGtj +pzH4EPgdKoNfdYu1cDawpuGMYGz9bdM9UFlGF+Bve4VfsEuzFBVc/Pth9diOGisN +4jaASDSCpQyYFYMb0eL/OS8uLBBU+zzZe8RBO7MSDogzL/xC/jOB163cezghOCHM +MgsiRZgXEqHP6m0zvOywxPyuBAUdC7XvyCQKYnd7tYMH5YjhHsgilYdSRwDDSe7O +UY6blulyTDTG2vgslEw4hpp228bxBr2+rayXw1B3dgobA/tx0dqseJTUAHqXVK0L +HQIDAQAB +-----END PUBLIC KEY-----