1
1
Fork 0
mirror of https://github.com/goreleaser/nfpm synced 2024-05-06 00:26:11 +02:00

feat: support PKCS8 keys for APK signing (#804)

* support PKCS8 keys for APK signing

Call correct parsing function for given RSA key depending on its PEM
header. So we can use both PKCS1 and PKCS8 keys to sign APK files.

Fixes https://github.com/goreleaser/nfpm/issues/799

* fix golangci-lint warnings
This commit is contained in:
Yaroslav 2024-03-27 18:28:44 +05:00 committed by GitHub
parent 04298aca7a
commit 1667ef9585
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 92 additions and 11 deletions

View File

@ -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)

View File

@ -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"},
}
err = RSAVerifySHA1Digest(digest, sig, "testdata/rsa.pub")
require.EqualError(t, err, "verify PKCS1v15 signature: crypto/rsa: verification error")
for _, testCase := range testCases {
sig, err := rsaSign(bytes.NewReader(digest), testCase.privKey, "")
require.NoError(t, err)
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) {

28
internal/sign/testdata/rsa_pkcs8.priv vendored Normal file
View File

@ -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-----

9
internal/sign/testdata/rsa_pkcs8.pub vendored Normal file
View File

@ -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-----