mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-07-16 12:08:04 +00:00
Merge pull request #755 from aptly-dev/gpg2-gpg1
Unit tests for PGP signing/verification
This commit is contained in:
+1
-13
@@ -174,7 +174,7 @@ type GpgVerifier struct {
|
|||||||
keyRings []string
|
keyRings []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGpgVerifier creates a new gpg signer
|
// NewGpgVerifier creates a new gpg verifier
|
||||||
func NewGpgVerifier() *GpgVerifier {
|
func NewGpgVerifier() *GpgVerifier {
|
||||||
gpg, err := findGPG1()
|
gpg, err := findGPG1()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -191,18 +191,6 @@ func NewGpgVerifier() *GpgVerifier {
|
|||||||
|
|
||||||
// InitKeyring verifies that gpg is installed and some keys are trusted
|
// InitKeyring verifies that gpg is installed and some keys are trusted
|
||||||
func (g *GpgVerifier) InitKeyring() error {
|
func (g *GpgVerifier) InitKeyring() error {
|
||||||
cmd, err := findGPG1()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
g.gpg = cmd
|
|
||||||
|
|
||||||
cmd, err = findGPGV1()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
g.gpgv = cmd
|
|
||||||
|
|
||||||
if len(g.keyRings) == 0 {
|
if len(g.keyRings) == 0 {
|
||||||
// using default keyring
|
// using default keyring
|
||||||
output, err := exec.Command(g.gpg, "--no-default-keyring", "--no-auto-check-trustdb", "--keyring", "trustedkeys.gpg", "--list-keys").Output()
|
output, err := exec.Command(g.gpg, "--no-default-keyring", "--no-auto-check-trustdb", "--keyring", "trustedkeys.gpg", "--list-keys").Output()
|
||||||
|
|||||||
@@ -77,3 +77,35 @@ func (s *GnupgSuite) TestGPGVNothing(c *C) {
|
|||||||
|
|
||||||
c.Assert(func() { NewGpgVerifier() }, PanicMatches, `Couldn't find a suitable gpgv executable.+`)
|
c.Assert(func() { NewGpgVerifier() }, PanicMatches, `Couldn't find a suitable gpgv executable.+`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Gnupg1VerifierSuite struct {
|
||||||
|
VerifierSuite
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Suite(&Gnupg1VerifierSuite{})
|
||||||
|
|
||||||
|
func (s *Gnupg1VerifierSuite) SetUpTest(c *C) {
|
||||||
|
s.verifier = NewGpgVerifier()
|
||||||
|
s.verifier.AddKeyring("./trusted.gpg")
|
||||||
|
|
||||||
|
c.Assert(s.verifier.InitKeyring(), IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Gnupg1SignerSuite struct {
|
||||||
|
SignerSuite
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Suite(&Gnupg1SignerSuite{})
|
||||||
|
|
||||||
|
func (s *Gnupg1SignerSuite) SetUpTest(c *C) {
|
||||||
|
s.signer = NewGpgSigner()
|
||||||
|
s.signer.SetBatch(true)
|
||||||
|
|
||||||
|
s.verifier = &GoVerifier{}
|
||||||
|
s.verifier.AddKeyring("./keyrings/aptly.pub")
|
||||||
|
s.verifier.AddKeyring("./keyrings/aptly_passphrase.pub")
|
||||||
|
|
||||||
|
c.Assert(s.verifier.InitKeyring(), IsNil)
|
||||||
|
|
||||||
|
s.SignerSuite.SetUpTest(c)
|
||||||
|
}
|
||||||
|
|||||||
+14
-73
@@ -1,14 +1,11 @@
|
|||||||
package pgp
|
package pgp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GoVerifierSuite struct {
|
type GoVerifierSuite struct {
|
||||||
verifier Verifier
|
VerifierSuite
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = Suite(&GoVerifierSuite{})
|
var _ = Suite(&GoVerifierSuite{})
|
||||||
@@ -20,77 +17,21 @@ func (s *GoVerifierSuite) SetUpTest(c *C) {
|
|||||||
c.Assert(s.verifier.InitKeyring(), IsNil)
|
c.Assert(s.verifier.InitKeyring(), IsNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GoVerifierSuite) TestVerifyDetached(c *C) {
|
type GoSignerSuite struct {
|
||||||
for _, test := range []struct {
|
SignerSuite
|
||||||
textName, signatureName string
|
|
||||||
}{
|
|
||||||
{"1.text", "1.signature"},
|
|
||||||
{"2.text", "2.signature"},
|
|
||||||
{"3.text", "3.signature"},
|
|
||||||
} {
|
|
||||||
cleartext, err := os.Open(test.textName)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
signature, err := os.Open(test.signatureName)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
err = s.verifier.VerifyDetachedSignature(signature, cleartext, false)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
signature.Close()
|
|
||||||
cleartext.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GoVerifierSuite) TestVerifyClearsigned(c *C) {
|
var _ = Suite(&GoSignerSuite{})
|
||||||
for _, test := range []struct {
|
|
||||||
clearSignedName string
|
|
||||||
}{
|
|
||||||
{"1.clearsigned"},
|
|
||||||
} {
|
|
||||||
clearsigned, err := os.Open(test.clearSignedName)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
keyInfo, err := s.verifier.VerifyClearsigned(clearsigned, false)
|
func (s *GoSignerSuite) SetUpTest(c *C) {
|
||||||
c.Assert(err, IsNil)
|
s.signer = &GoSigner{}
|
||||||
c.Check(keyInfo.GoodKeys, DeepEquals, []Key{"8B48AD6246925553", "7638D0442B90D010"})
|
s.signer.SetBatch(true)
|
||||||
c.Check(keyInfo.MissingKeys, DeepEquals, []Key(nil))
|
|
||||||
|
|
||||||
clearsigned.Close()
|
s.verifier = &GoVerifier{}
|
||||||
}
|
s.verifier.AddKeyring("./keyrings/aptly.pub")
|
||||||
}
|
s.verifier.AddKeyring("./keyrings/aptly_passphrase.pub")
|
||||||
|
|
||||||
func (s *GoVerifierSuite) TestExtractClearsigned(c *C) {
|
c.Assert(s.verifier.InitKeyring(), IsNil)
|
||||||
for _, test := range []struct {
|
|
||||||
clearSignedName, clearTextName string
|
s.SignerSuite.SetUpTest(c)
|
||||||
}{
|
|
||||||
{"1.clearsigned", "1.cleartext"},
|
|
||||||
} {
|
|
||||||
clearsigned, err := os.Open(test.clearSignedName)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
cleartext, err := os.Open(test.clearTextName)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
is, err := s.verifier.IsClearSigned(clearsigned)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Check(is, Equals, true)
|
|
||||||
|
|
||||||
clearsigned.Seek(0, 0)
|
|
||||||
|
|
||||||
extractedF, err := s.verifier.ExtractClearsigned(clearsigned)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
expected, err := ioutil.ReadAll(cleartext)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
extracted, err := ioutil.ReadAll(extractedF)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
c.Check(expected, DeepEquals, extracted)
|
|
||||||
|
|
||||||
extractedF.Close()
|
|
||||||
clearsigned.Close()
|
|
||||||
cleartext.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,134 @@
|
|||||||
|
package pgp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
. "gopkg.in/check.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Common set of tests shared by internal & external GnuPG implementations
|
||||||
|
type SignerSuite struct {
|
||||||
|
signer Signer
|
||||||
|
verifier Verifier
|
||||||
|
|
||||||
|
clearF *os.File
|
||||||
|
signedF *os.File
|
||||||
|
cleartext []byte
|
||||||
|
|
||||||
|
passwordFile string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) SetUpTest(c *C) {
|
||||||
|
tempDir := c.MkDir()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
s.clearF, err = os.Create(path.Join(tempDir, "cleartext"))
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
s.cleartext = make([]byte, 0, 1024)
|
||||||
|
_, err = rand.Read(s.cleartext)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
_, err = s.clearF.Write(s.cleartext)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
_, err = s.clearF.Seek(0, io.SeekStart)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
s.signedF, err = os.Create(path.Join(tempDir, "signed"))
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
s.passwordFile = path.Join(tempDir, "password")
|
||||||
|
f, err := os.OpenFile(s.passwordFile, os.O_CREATE|os.O_WRONLY, 0600)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
_, err = f.Write([]byte("verysecret"))
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
s.signer.SetBatch(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) TearDownTest(c *C) {
|
||||||
|
s.clearF.Close()
|
||||||
|
s.signedF.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) testSignDetached(c *C) {
|
||||||
|
c.Assert(s.signer.Init(), IsNil)
|
||||||
|
|
||||||
|
err := s.signer.DetachedSign(s.clearF.Name(), s.signedF.Name())
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
err = s.verifier.VerifyDetachedSignature(s.signedF, s.clearF, false)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) TestSignDetachedNoPassphrase(c *C) {
|
||||||
|
s.signer.SetKeyRing("keyrings/aptly.pub", "keyrings/aptly.sec")
|
||||||
|
|
||||||
|
s.testSignDetached(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) TestSignDetachedPassphrase(c *C) {
|
||||||
|
s.signer.SetKeyRing("keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec")
|
||||||
|
s.signer.SetPassphrase("verysecret", "")
|
||||||
|
|
||||||
|
s.testSignDetached(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) TestSignDetachedPassphraseFile(c *C) {
|
||||||
|
s.signer.SetKeyRing("keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec")
|
||||||
|
s.signer.SetPassphrase("", s.passwordFile)
|
||||||
|
|
||||||
|
s.testSignDetached(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) testClearSign(c *C, expectedKey Key) {
|
||||||
|
c.Assert(s.signer.Init(), IsNil)
|
||||||
|
|
||||||
|
err := s.signer.ClearSign(s.clearF.Name(), s.signedF.Name())
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
keyInfo, err := s.verifier.VerifyClearsigned(s.signedF, false)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
c.Assert(keyInfo.GoodKeys, DeepEquals, []Key{expectedKey})
|
||||||
|
c.Assert(keyInfo.MissingKeys, DeepEquals, []Key(nil))
|
||||||
|
|
||||||
|
_, err = s.signedF.Seek(0, io.SeekStart)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
extractedF, err := s.verifier.ExtractClearsigned(s.signedF)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
defer extractedF.Close()
|
||||||
|
|
||||||
|
extracted, err := ioutil.ReadAll(extractedF)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
c.Assert(extracted, DeepEquals, s.cleartext)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) TestClearSignNoPassphrase(c *C) {
|
||||||
|
s.signer.SetKeyRing("keyrings/aptly.pub", "keyrings/aptly.sec")
|
||||||
|
|
||||||
|
s.testClearSign(c, "21DBB89C16DB3E6D")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) TestClearSignPassphrase(c *C) {
|
||||||
|
s.signer.SetKeyRing("keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec")
|
||||||
|
s.signer.SetPassphrase("verysecret", "")
|
||||||
|
|
||||||
|
s.testClearSign(c, "F30E8CB9CDDE2AF8")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SignerSuite) TestClearSignPassphraseFile(c *C) {
|
||||||
|
s.signer.SetKeyRing("keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec")
|
||||||
|
s.signer.SetPassphrase("", s.passwordFile)
|
||||||
|
|
||||||
|
s.testClearSign(c, "F30E8CB9CDDE2AF8")
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package pgp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
. "gopkg.in/check.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Common set of tests shared by internal & external GnuPG implementations
|
||||||
|
type VerifierSuite struct {
|
||||||
|
verifier Verifier
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VerifierSuite) TestVerifyDetached(c *C) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
textName, signatureName string
|
||||||
|
}{
|
||||||
|
{"1.text", "1.signature"},
|
||||||
|
{"2.text", "2.signature"},
|
||||||
|
{"3.text", "3.signature"},
|
||||||
|
} {
|
||||||
|
cleartext, err := os.Open(test.textName)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
signature, err := os.Open(test.signatureName)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
err = s.verifier.VerifyDetachedSignature(signature, cleartext, false)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
signature.Close()
|
||||||
|
cleartext.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VerifierSuite) TestVerifyClearsigned(c *C) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
clearSignedName string
|
||||||
|
}{
|
||||||
|
{"1.clearsigned"},
|
||||||
|
} {
|
||||||
|
clearsigned, err := os.Open(test.clearSignedName)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
keyInfo, err := s.verifier.VerifyClearsigned(clearsigned, false)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Check(keyInfo.GoodKeys, DeepEquals, []Key{"8B48AD6246925553", "7638D0442B90D010"})
|
||||||
|
c.Check(keyInfo.MissingKeys, DeepEquals, []Key(nil))
|
||||||
|
|
||||||
|
clearsigned.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *VerifierSuite) TestExtractClearsigned(c *C) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
clearSignedName, clearTextName string
|
||||||
|
}{
|
||||||
|
{"1.clearsigned", "1.cleartext"},
|
||||||
|
} {
|
||||||
|
clearsigned, err := os.Open(test.clearSignedName)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
cleartext, err := os.Open(test.clearTextName)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
is, err := s.verifier.IsClearSigned(clearsigned)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Check(is, Equals, true)
|
||||||
|
|
||||||
|
clearsigned.Seek(0, 0)
|
||||||
|
|
||||||
|
extractedF, err := s.verifier.ExtractClearsigned(clearsigned)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
expected, err := ioutil.ReadAll(cleartext)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
extracted, err := ioutil.ReadAll(extractedF)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
// normalize newlines
|
||||||
|
extracted = bytes.TrimRight(bytes.Replace(extracted, []byte("\r\n"), []byte("\n"), -1), "\n")
|
||||||
|
expected = bytes.Replace(expected, []byte("\r\n"), []byte("\n"), -1)
|
||||||
|
|
||||||
|
c.Check(extracted, DeepEquals, expected)
|
||||||
|
|
||||||
|
extractedF.Close()
|
||||||
|
clearsigned.Close()
|
||||||
|
cleartext.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user