github.com/goreleaser/nfpm/v2@v2.44.0/internal/sign/pgp_test.go (about)

     1  package sign
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"os"
     7  	"testing"
     8  
     9  	"github.com/AlekSi/pointer"
    10  	"github.com/ProtonMail/gopenpgp/v2/crypto"
    11  	"github.com/goreleaser/nfpm/v2"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  const pass = "hunter2"
    16  
    17  var testCases = []struct {
    18  	name        string
    19  	privKeyFile string
    20  	pubKeyFile  string
    21  	pass        string
    22  	keyID       *string
    23  }{
    24  	{"protected", "testdata/privkey.gpg", "testdata/pubkey", pass, nil},
    25  	{"unprotected", "testdata/privkey_unprotected.gpg", "testdata/pubkey", "", nil},
    26  	{"armored protected", "testdata/privkey.asc", "testdata/pubkey", pass, nil},
    27  	{"armored unprotected", "testdata/privkey_unprotected.asc", "testdata/pubkey", "", nil},
    28  	{"gpg subkey unprotected", "testdata/privkey_unprotected_subkey_only.asc", "testdata/pubkey", "", nil},
    29  	{"protected-with-key-id", "testdata/privkey.gpg", "testdata/pubkey", pass, pointer.ToString("bc8acdd415bd80b3")},
    30  	{"unprotected-with-key-id", "testdata/privkey_unprotected.gpg", "testdata/pubkey", "", pointer.ToString("bc8acdd415bd80b3")},
    31  	{"armored protected-with-key-id", "testdata/privkey.asc", "testdata/pubkey", pass, pointer.ToString("bc8acdd415bd80b3")},
    32  	{"armored unprotected-with-key-id", "testdata/privkey_unprotected.asc", "testdata/pubkey", "", pointer.ToString("bc8acdd415bd80b3")},
    33  	{"gpg subkey unprotected-with-key-id", "testdata/privkey_unprotected_subkey_only.asc", "testdata/pubkey", "", pointer.ToString("9890904dfb2ec88a")},
    34  }
    35  
    36  func TestPGPSignerAndVerify(t *testing.T) {
    37  	data := []byte("testdata")
    38  	for _, testCase := range testCases {
    39  		testCase := testCase
    40  		t.Run(testCase.name, func(t *testing.T) {
    41  			armoredPublicKey := fmt.Sprintf("%s.asc", testCase.pubKeyFile)
    42  			gpgPublicKey := fmt.Sprintf("%s.gpg", testCase.pubKeyFile)
    43  			sig, err := PGPSignerWithKeyID(testCase.privKeyFile, testCase.pass, testCase.keyID)(data)
    44  			require.NoError(t, err)
    45  
    46  			err = PGPVerify(bytes.NewReader(data), sig, armoredPublicKey)
    47  			require.NoError(t, err)
    48  
    49  			err = PGPVerify(bytes.NewReader(data), sig, gpgPublicKey)
    50  			require.NoError(t, err)
    51  			if testCase.keyID != nil {
    52  				var pgpSignature *crypto.PGPSignature
    53  				if isASCII(sig) {
    54  					pgpSignature, err = crypto.NewPGPSignatureFromArmored(string(sig))
    55  					require.NoError(t, err)
    56  				} else {
    57  					pgpSignature = crypto.NewPGPSignature(sig)
    58  				}
    59  				sigID, _ := pgpSignature.GetSignatureKeyIDs()
    60  				require.Len(t, sigID, 1)
    61  				require.Equal(t, *testCase.keyID, fmt.Sprintf("%x", sigID[0]))
    62  			}
    63  		})
    64  	}
    65  }
    66  
    67  func TestArmoredDetachSignAndVerify(t *testing.T) {
    68  	data := []byte("testdata")
    69  	for _, testCase := range testCases {
    70  		testCase := testCase
    71  		t.Run(testCase.name, func(t *testing.T) {
    72  			armoredPublicKey := fmt.Sprintf("%s.asc", testCase.pubKeyFile)
    73  			gpgPublicKey := fmt.Sprintf("%s.gpg", testCase.pubKeyFile)
    74  			sig, err := PGPArmoredDetachSignWithKeyID(
    75  				bytes.NewReader(data),
    76  				testCase.privKeyFile,
    77  				testCase.pass,
    78  				testCase.keyID,
    79  			)
    80  			require.NoError(t, err)
    81  
    82  			err = PGPVerify(bytes.NewReader(data), sig, armoredPublicKey)
    83  			require.NoError(t, err)
    84  
    85  			err = PGPVerify(bytes.NewReader(data), sig, gpgPublicKey)
    86  			require.NoError(t, err)
    87  			if testCase.keyID != nil {
    88  				var pgpSignature *crypto.PGPSignature
    89  				if isASCII(sig) {
    90  					pgpSignature, err = crypto.NewPGPSignatureFromArmored(string(sig))
    91  					require.NoError(t, err)
    92  				} else {
    93  					pgpSignature = crypto.NewPGPSignature(sig)
    94  				}
    95  				sigID, _ := pgpSignature.GetSignatureKeyIDs()
    96  				require.Len(t, sigID, 1)
    97  				require.Equal(t, *testCase.keyID, fmt.Sprintf("%x", sigID[0]))
    98  			}
    99  		})
   100  	}
   101  }
   102  
   103  func TestPGPSignerError(t *testing.T) {
   104  	_, err := PGPSignerWithKeyID("/does/not/exist", "", nil)([]byte("data"))
   105  	require.Error(t, err)
   106  
   107  	var expectedError *nfpm.ErrSigningFailure
   108  	require.ErrorAs(t, err, &expectedError)
   109  }
   110  
   111  func TestNoSigningKey(t *testing.T) {
   112  	_, err := readSigningKey("testdata/pubkey.asc", pass)
   113  	require.EqualError(t, err, "no signing key in keyring")
   114  }
   115  
   116  func TestMultipleKeys(t *testing.T) {
   117  	_, err := readSigningKey("testdata/multiple_privkeys.asc", pass)
   118  	require.EqualError(t, err, "more than one signing key in keyring")
   119  }
   120  
   121  func TestWrongPass(t *testing.T) {
   122  	_, err := readSigningKey("testdata/privkey.asc", "password123")
   123  	require.Contains(t, err.Error(), "private key checksum failure")
   124  }
   125  
   126  func TestEmptyPass(t *testing.T) {
   127  	_, err := readSigningKey("testdata/privkey.asc", "")
   128  	require.EqualError(t, err, "key is encrypted but no passphrase was provided")
   129  }
   130  
   131  func TestReadArmoredKey(t *testing.T) {
   132  	_, err := readSigningKey("testdata/privkey.asc", pass)
   133  	require.NoError(t, err)
   134  }
   135  
   136  func TestReadKey(t *testing.T) {
   137  	_, err := readSigningKey("testdata/privkey.gpg", pass)
   138  	require.NoError(t, err)
   139  }
   140  
   141  func TestIsASCII(t *testing.T) {
   142  	data, err := os.ReadFile("testdata/privkey.asc")
   143  	require.NoError(t, err)
   144  	require.True(t, isASCII(data))
   145  
   146  	data, err = os.ReadFile("testdata/privkey.gpg")
   147  	require.NoError(t, err)
   148  	require.False(t, isASCII(data))
   149  }