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 }