mirror of https://github.com/aptly-dev/aptly
Refactor GPG signer/verifier
Goal is to make it easier to plug in another implementation.pull/575/head
parent
c026106352
commit
1be8d39105
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
|||
GOVERSION=$(shell go version | awk '{print $$3;}')
|
||||
VERSION=$(shell git describe --tags | sed 's@^v@@' | sed 's@-@+@g')
|
||||
PACKAGES=context database deb files http query swift s3 utils
|
||||
PACKAGES=context database deb files gpg http query swift s3 utils
|
||||
PYTHON?=python
|
||||
TESTS?=
|
||||
BINPATH?=$(GOPATH)/bin
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/smira/aptly/deb"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
)
|
||||
|
||||
|
@ -20,12 +21,12 @@ type SigningOptions struct {
|
|||
PassphraseFile string
|
||||
}
|
||||
|
||||
func getSigner(options *SigningOptions) (utils.Signer, error) {
|
||||
func getSigner(options *SigningOptions) (pgp.Signer, error) {
|
||||
if options.Skip {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
signer := &utils.GpgSigner{}
|
||||
signer := &pgp.GpgSigner{}
|
||||
signer.SetKey(options.GpgKey)
|
||||
signer.SetKeyRing(options.Keyring, options.SecretKeyring)
|
||||
signer.SetPassphrase(options.Passphrase, options.PassphraseFile)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/smira/aptly/aptly"
|
||||
"github.com/smira/aptly/database"
|
||||
"github.com/smira/aptly/deb"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
)
|
||||
|
||||
|
@ -296,7 +297,7 @@ func apiReposPackageFromDir(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
verifier := &utils.GpgVerifier{}
|
||||
verifier := &pgp.GpgVerifier{}
|
||||
|
||||
var (
|
||||
sources []string
|
||||
|
|
|
@ -3,19 +3,19 @@ package cmd
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/smira/aptly/utils"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/commander"
|
||||
"github.com/smira/flag"
|
||||
)
|
||||
|
||||
func getVerifier(flags *flag.FlagSet) (utils.Verifier, error) {
|
||||
func getVerifier(flags *flag.FlagSet) (pgp.Verifier, error) {
|
||||
if LookupOption(context.Config().GpgDisableVerify, flags, "ignore-signatures") {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
keyRings := flags.Lookup("keyring").Value.Get().([]string)
|
||||
|
||||
verifier := &utils.GpgVerifier{}
|
||||
verifier := &pgp.GpgVerifier{}
|
||||
for _, keyRing := range keyRings {
|
||||
verifier.AddKeyring(keyRing)
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/smira/aptly/utils"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/commander"
|
||||
"github.com/smira/flag"
|
||||
)
|
||||
|
||||
func getSigner(flags *flag.FlagSet) (utils.Signer, error) {
|
||||
func getSigner(flags *flag.FlagSet) (pgp.Signer, error) {
|
||||
if LookupOption(context.Config().GpgDisableSign, flags, "skip-signing") {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
signer := &utils.GpgSigner{}
|
||||
signer := &pgp.GpgSigner{}
|
||||
signer.SetKey(flags.Lookup("gpg-key").Value.String())
|
||||
signer.SetKeyRing(flags.Lookup("keyring").Value.String(), flags.Lookup("secret-keyring").Value.String())
|
||||
signer.SetPassphrase(flags.Lookup("passphrase").Value.String(), flags.Lookup("passphrase-file").Value.String())
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/smira/aptly/aptly"
|
||||
"github.com/smira/aptly/deb"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
"github.com/smira/commander"
|
||||
"github.com/smira/flag"
|
||||
|
@ -20,7 +21,7 @@ func aptlyRepoAdd(cmd *commander.Command, args []string) error {
|
|||
|
||||
name := args[0]
|
||||
|
||||
verifier := &utils.GpgVerifier{}
|
||||
verifier := &pgp.GpgVerifier{}
|
||||
|
||||
repo, err := context.CollectionFactory().LocalRepoCollection().ByName(name)
|
||||
if err != nil {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/smira/aptly/aptly"
|
||||
"github.com/smira/aptly/deb"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/query"
|
||||
"github.com/smira/aptly/utils"
|
||||
"github.com/smira/commander"
|
||||
|
@ -28,7 +29,7 @@ func aptlyRepoInclude(cmd *commander.Command, args []string) error {
|
|||
}
|
||||
|
||||
if verifier == nil {
|
||||
verifier = &utils.GpgVerifier{}
|
||||
verifier = &pgp.GpgVerifier{}
|
||||
}
|
||||
|
||||
forceReplace := context.Flags().Lookup("force-replace").Value.Get().(bool)
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/smira/aptly/aptly"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
)
|
||||
|
||||
|
@ -23,7 +24,7 @@ type Changes struct {
|
|||
Binary []string
|
||||
Architectures []string
|
||||
Stanza Stanza
|
||||
SignatureKeys []utils.GpgKey
|
||||
SignatureKeys []pgp.Key
|
||||
}
|
||||
|
||||
// NewChanges moves .changes file into temporary directory and creates Changes structure
|
||||
|
@ -50,7 +51,7 @@ func NewChanges(path string) (*Changes, error) {
|
|||
}
|
||||
|
||||
// VerifyAndParse does optional signature verification and parses changes files
|
||||
func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier utils.Verifier) error {
|
||||
func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier pgp.Verifier) error {
|
||||
input, err := os.Open(filepath.Join(c.TempDir, c.ChangesName))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -69,7 +70,7 @@ func (c *Changes) VerifyAndParse(acceptUnsigned, ignoreSignature bool, verifier
|
|||
}
|
||||
|
||||
if isClearSigned && !ignoreSignature {
|
||||
var keyInfo *utils.GpgKeyInfo
|
||||
var keyInfo *pgp.KeyInfo
|
||||
keyInfo, err = verifier.VerifyClearsigned(input, false)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/mkrautz/goar"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/smira/aptly/utils"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/go-xz"
|
||||
"github.com/smira/lzma"
|
||||
)
|
||||
|
@ -76,7 +76,7 @@ func GetControlFileFromDeb(packageFile string) (Stanza, error) {
|
|||
}
|
||||
|
||||
// GetControlFileFromDsc reads control file from dsc package
|
||||
func GetControlFileFromDsc(dscFile string, verifier utils.Verifier) (Stanza, error) {
|
||||
func GetControlFileFromDsc(dscFile string, verifier pgp.Verifier) (Stanza, error) {
|
||||
file, err := os.Open(dscFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/smira/aptly/utils"
|
||||
"github.com/smira/aptly/pgp"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
@ -39,7 +39,7 @@ func (s *DebSuite) TestGetControlFileFromDeb(c *C) {
|
|||
}
|
||||
|
||||
func (s *DebSuite) TestGetControlFileFromDsc(c *C) {
|
||||
verifier := &utils.GpgVerifier{}
|
||||
verifier := &pgp.GpgVerifier{}
|
||||
|
||||
_, err := GetControlFileFromDsc("/no/such/file", verifier)
|
||||
c.Check(err, ErrorMatches, ".*no such file or directory")
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/smira/aptly/aptly"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
)
|
||||
|
||||
|
@ -59,7 +60,7 @@ func CollectPackageFiles(locations []string, reporter aptly.ResultReporter) (pac
|
|||
}
|
||||
|
||||
// ImportPackageFiles imports files into local repository
|
||||
func ImportPackageFiles(list *PackageList, packageFiles []string, forceReplace bool, verifier utils.Verifier,
|
||||
func ImportPackageFiles(list *PackageList, packageFiles []string, forceReplace bool, verifier pgp.Verifier,
|
||||
pool aptly.PackagePool, collection *PackageCollection, reporter aptly.ResultReporter, restriction PackageQuery,
|
||||
checksumStorage aptly.ChecksumStorage) (processedFiles []string, failedFiles []string, err error) {
|
||||
if forceReplace {
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/smira/aptly/aptly"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
)
|
||||
|
||||
|
@ -48,7 +49,7 @@ func (file *indexFile) BufWriter() (*bufio.Writer, error) {
|
|||
return file.w, nil
|
||||
}
|
||||
|
||||
func (file *indexFile) Finalize(signer utils.Signer) error {
|
||||
func (file *indexFile) Finalize(signer pgp.Signer) error {
|
||||
if file.w == nil {
|
||||
if file.discardable {
|
||||
return nil
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
|
||||
"github.com/smira/aptly/aptly"
|
||||
"github.com/smira/aptly/database"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
)
|
||||
|
||||
|
@ -447,7 +448,7 @@ func (p *PublishedRepo) GetLabel() string {
|
|||
|
||||
// Publish publishes snapshot (repository) contents, links package files, generates Packages & Release files, signs them
|
||||
func (p *PublishedRepo) Publish(packagePool aptly.PackagePool, publishedStorageProvider aptly.PublishedStorageProvider,
|
||||
collectionFactory *CollectionFactory, signer utils.Signer, progress aptly.Progress, forceOverwrite bool) error {
|
||||
collectionFactory *CollectionFactory, signer pgp.Signer, progress aptly.Progress, forceOverwrite bool) error {
|
||||
publishedStorage := publishedStorageProvider.GetPublishedStorage(p.Storage)
|
||||
|
||||
err := publishedStorage.MkDir(filepath.Join(p.Prefix, "pool"))
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/smira/aptly/aptly"
|
||||
"github.com/smira/aptly/database"
|
||||
"github.com/smira/aptly/http"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
"github.com/smira/go-uuid/uuid"
|
||||
"github.com/ugorji/go/codec"
|
||||
|
@ -244,7 +245,7 @@ func (repo *RemoteRepo) PackageURL(filename string) *url.URL {
|
|||
}
|
||||
|
||||
// Fetch updates information about repository
|
||||
func (repo *RemoteRepo) Fetch(d aptly.Downloader, verifier utils.Verifier) error {
|
||||
func (repo *RemoteRepo) Fetch(d aptly.Downloader, verifier pgp.Verifier) error {
|
||||
var (
|
||||
release, inrelease, releasesig *os.File
|
||||
err error
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/smira/aptly/database"
|
||||
"github.com/smira/aptly/files"
|
||||
"github.com/smira/aptly/http"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
|
@ -31,7 +32,7 @@ func (n *NullVerifier) VerifyDetachedSignature(signature, cleartext io.Reader) e
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *NullVerifier) VerifyClearsigned(clearsigned io.Reader, hint bool) (*utils.GpgKeyInfo, error) {
|
||||
func (n *NullVerifier) VerifyClearsigned(clearsigned io.Reader, hint bool) (*pgp.KeyInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/DisposaBoy/JsonConfigReader"
|
||||
"github.com/smira/aptly/pgp"
|
||||
"github.com/smira/aptly/utils"
|
||||
)
|
||||
|
||||
|
@ -85,7 +86,7 @@ func (u *Uploaders) IsAllowed(changes *Changes) error {
|
|||
deny := u.ExpandGroups(rule.Deny)
|
||||
for _, key := range changes.SignatureKeys {
|
||||
for _, item := range deny {
|
||||
if item == "*" || key.Matches(utils.GpgKey(item)) {
|
||||
if item == "*" || key.Matches(pgp.Key(item)) {
|
||||
return fmt.Errorf("denied according to rule: %s", rule)
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +95,7 @@ func (u *Uploaders) IsAllowed(changes *Changes) error {
|
|||
allow := u.ExpandGroups(rule.Allow)
|
||||
for _, key := range changes.SignatureKeys {
|
||||
for _, item := range allow {
|
||||
if item == "*" || key.Matches(utils.GpgKey(item)) {
|
||||
if item == "*" || key.Matches(pgp.Key(item)) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package deb
|
||||
|
||||
import (
|
||||
"github.com/smira/aptly/utils"
|
||||
"github.com/smira/aptly/pgp"
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
|
@ -58,24 +58,24 @@ func (s *UploadersSuite) TestIsAllowed(c *C) {
|
|||
}
|
||||
|
||||
// no keys - not allowed
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []utils.GpgKey{}, Stanza: Stanza{"Source": "calamares"}}), ErrorMatches, "denied as no rule matches")
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []pgp.Key{}, Stanza: Stanza{"Source": "calamares"}}), ErrorMatches, "denied as no rule matches")
|
||||
|
||||
// no rule - not allowed
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []utils.GpgKey{"37E1C17570096AD1", "EC4B033C70096AD1"}, Stanza: Stanza{"Source": "unknown-calamares"}}), ErrorMatches, "denied as no rule matches")
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []pgp.Key{"37E1C17570096AD1", "EC4B033C70096AD1"}, Stanza: Stanza{"Source": "unknown-calamares"}}), ErrorMatches, "denied as no rule matches")
|
||||
|
||||
// first rule: allow anyone do stuff with calamares
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []utils.GpgKey{"ABCD1234", "1234ABCD"}, Stanza: Stanza{"Source": "calamares"}}), IsNil)
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []pgp.Key{"ABCD1234", "1234ABCD"}, Stanza: Stanza{"Source": "calamares"}}), IsNil)
|
||||
|
||||
// second rule: nobody is allowed to do stuff with never-calamares
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []utils.GpgKey{"ABCD1234", "1234ABCD"}, Stanza: Stanza{"Source": "never-calamares"}}),
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []pgp.Key{"ABCD1234", "1234ABCD"}, Stanza: Stanza{"Source": "never-calamares"}}),
|
||||
ErrorMatches, "denied according to rule: {\"condition\":\"\",\"allow\":null,\"deny\":\\[\"\\*\"\\]}")
|
||||
|
||||
// third rule: anyone from the group or explicit key
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []utils.GpgKey{"45678901", "12345678"}, Stanza: Stanza{"Source": "some-calamares"}}), IsNil)
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []utils.GpgKey{"37E1C17570096AD1"}, Stanza: Stanza{"Source": "some-calamares"}}), IsNil)
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []utils.GpgKey{"70096AD1"}, Stanza: Stanza{"Source": "some-calamares"}}), IsNil)
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []pgp.Key{"45678901", "12345678"}, Stanza: Stanza{"Source": "some-calamares"}}), IsNil)
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []pgp.Key{"37E1C17570096AD1"}, Stanza: Stanza{"Source": "some-calamares"}}), IsNil)
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []pgp.Key{"70096AD1"}, Stanza: Stanza{"Source": "some-calamares"}}), IsNil)
|
||||
|
||||
// fourth rule: some are not allowed
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []utils.GpgKey{"ABCD1234", "45678901"}, Stanza: Stanza{"Source": "some-calamares"}}),
|
||||
c.Check(u.IsAllowed(&Changes{SignatureKeys: []pgp.Key{"ABCD1234", "45678901"}, Stanza: Stanza{"Source": "some-calamares"}}),
|
||||
ErrorMatches, "denied according to rule: {\"condition\":\"\",\"allow\":null,\"deny\":\\[\"45678901\",\"12345678\"\\]}")
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package utils
|
||||
package pgp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -12,60 +12,13 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// Signer interface describes facility implementing signing of files
|
||||
type Signer interface {
|
||||
Init() error
|
||||
SetKey(keyRef string)
|
||||
SetKeyRing(keyring, secretKeyring string)
|
||||
SetPassphrase(passphrase, passphraseFile string)
|
||||
SetBatch(batch bool)
|
||||
DetachedSign(source string, destination string) error
|
||||
ClearSign(source string, destination string) error
|
||||
}
|
||||
|
||||
// Verifier interface describes signature verification factility
|
||||
type Verifier interface {
|
||||
InitKeyring() error
|
||||
AddKeyring(keyring string)
|
||||
VerifyDetachedSignature(signature, cleartext io.Reader) error
|
||||
IsClearSigned(clearsigned io.Reader) (bool, error)
|
||||
VerifyClearsigned(clearsigned io.Reader, showKeyTip bool) (*GpgKeyInfo, error)
|
||||
ExtractClearsigned(clearsigned io.Reader) (text *os.File, err error)
|
||||
}
|
||||
|
||||
// Test interface
|
||||
var (
|
||||
_ Signer = &GpgSigner{}
|
||||
_ Verifier = &GpgVerifier{}
|
||||
)
|
||||
|
||||
// GpgKey is key in GPG representation
|
||||
type GpgKey string
|
||||
|
||||
// Matches checks two keys for equality
|
||||
func (key1 GpgKey) Matches(key2 GpgKey) bool {
|
||||
if key1 == key2 {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(key1) == 8 && len(key2) == 16 {
|
||||
return key1 == key2[8:]
|
||||
}
|
||||
|
||||
if len(key1) == 16 && len(key2) == 8 {
|
||||
return key1[8:] == key2
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// GpgKeyInfo is response from signature verification
|
||||
type GpgKeyInfo struct {
|
||||
GoodKeys []GpgKey
|
||||
MissingKeys []GpgKey
|
||||
}
|
||||
|
||||
// GpgSigner is implementation of Signer interface using gpg
|
||||
// GpgSigner is implementation of Signer interface using gpg as external program
|
||||
type GpgSigner struct {
|
||||
keyRef string
|
||||
keyring, secretKeyring string
|
||||
|
@ -166,7 +119,7 @@ func (g *GpgSigner) ClearSign(source string, destination string) error {
|
|||
return cmd.Run()
|
||||
}
|
||||
|
||||
// GpgVerifier is implementation of Verifier interface using gpgv
|
||||
// GpgVerifier is implementation of Verifier interface using gpgv as external program
|
||||
type GpgVerifier struct {
|
||||
keyRings []string
|
||||
}
|
||||
|
@ -209,7 +162,7 @@ func (g *GpgVerifier) argsKeyrings() (args []string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (g *GpgVerifier) runGpgv(args []string, context string, showKeyTip bool) (*GpgKeyInfo, error) {
|
||||
func (g *GpgVerifier) runGpgv(args []string, context string, showKeyTip bool) (*KeyInfo, error) {
|
||||
args = append([]string{"--status-fd", "3"}, args...)
|
||||
cmd := exec.Command("gpgv", args...)
|
||||
|
||||
|
@ -250,15 +203,15 @@ func (g *GpgVerifier) runGpgv(args []string, context string, showKeyTip bool) (*
|
|||
|
||||
statusr := bufio.NewScanner(tempf)
|
||||
|
||||
result := &GpgKeyInfo{}
|
||||
result := &KeyInfo{}
|
||||
|
||||
for statusr.Scan() {
|
||||
line := strings.TrimSpace(statusr.Text())
|
||||
|
||||
if strings.HasPrefix(line, "[GNUPG:] GOODSIG ") {
|
||||
result.GoodKeys = append(result.GoodKeys, GpgKey(strings.Fields(line)[2]))
|
||||
result.GoodKeys = append(result.GoodKeys, Key(strings.Fields(line)[2]))
|
||||
} else if strings.HasPrefix(line, "[GNUPG:] NO_PUBKEY ") {
|
||||
result.MissingKeys = append(result.MissingKeys, GpgKey(strings.Fields(line)[2]))
|
||||
result.MissingKeys = append(result.MissingKeys, Key(strings.Fields(line)[2]))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,7 +286,7 @@ func (g *GpgVerifier) IsClearSigned(clearsigned io.Reader) (bool, error) {
|
|||
}
|
||||
|
||||
// VerifyClearsigned verifies clearsigned file using gpgv
|
||||
func (g *GpgVerifier) VerifyClearsigned(clearsigned io.Reader, showKeyTip bool) (*GpgKeyInfo, error) {
|
||||
func (g *GpgVerifier) VerifyClearsigned(clearsigned io.Reader, showKeyTip bool) (*KeyInfo, error) {
|
||||
args := g.argsKeyrings()
|
||||
|
||||
clearf, err := ioutil.TempFile("", "aptly-gpg")
|
|
@ -0,0 +1,54 @@
|
|||
// Package pgp provides interface to signature generation and validation
|
||||
package pgp
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Key is key in PGP representation
|
||||
type Key string
|
||||
|
||||
// Matches checks two keys for equality
|
||||
func (key1 Key) Matches(key2 Key) bool {
|
||||
if key1 == key2 {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(key1) == 8 && len(key2) == 16 {
|
||||
return key1 == key2[8:]
|
||||
}
|
||||
|
||||
if len(key1) == 16 && len(key2) == 8 {
|
||||
return key1[8:] == key2
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// KeyInfo is response from signature verification
|
||||
type KeyInfo struct {
|
||||
GoodKeys []Key
|
||||
MissingKeys []Key
|
||||
}
|
||||
|
||||
// Signer interface describes facility implementing signing of files
|
||||
type Signer interface {
|
||||
Init() error
|
||||
SetKey(keyRef string)
|
||||
SetKeyRing(keyring, secretKeyring string)
|
||||
SetPassphrase(passphrase, passphraseFile string)
|
||||
SetBatch(batch bool)
|
||||
DetachedSign(source string, destination string) error
|
||||
ClearSign(source string, destination string) error
|
||||
}
|
||||
|
||||
// Verifier interface describes signature verification factility
|
||||
type Verifier interface {
|
||||
InitKeyring() error
|
||||
AddKeyring(keyring string)
|
||||
VerifyDetachedSignature(signature, cleartext io.Reader) error
|
||||
IsClearSigned(clearsigned io.Reader) (bool, error)
|
||||
VerifyClearsigned(clearsigned io.Reader, showKeyTip bool) (*KeyInfo, error)
|
||||
ExtractClearsigned(clearsigned io.Reader) (text *os.File, err error)
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package pgp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
// Launch gocheck tests
|
||||
func Test(t *testing.T) {
|
||||
TestingT(t)
|
||||
}
|
||||
|
||||
type PGPSuite struct{}
|
||||
|
||||
var _ = Suite(&PGPSuite{})
|
||||
|
||||
func (s *PGPSuite) TestKeyMatch(c *C) {
|
||||
c.Check(Key("EC4B033C70096AD1").Matches(Key("EC4B033C70096AD1")), Equals, true)
|
||||
c.Check(Key("37E1C17570096AD1").Matches(Key("EC4B033C70096AD1")), Equals, false)
|
||||
|
||||
c.Check(Key("70096AD1").Matches(Key("70096AD1")), Equals, true)
|
||||
c.Check(Key("70096AD1").Matches(Key("EC4B033C")), Equals, false)
|
||||
|
||||
c.Check(Key("37E1C17570096AD1").Matches(Key("70096AD1")), Equals, true)
|
||||
c.Check(Key("70096AD1").Matches(Key("EC4B033C70096AD1")), Equals, true)
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
type GpgSuite struct{}
|
||||
|
||||
var _ = Suite(&GpgSuite{})
|
||||
|
||||
func (s *GpgSuite) TestGpgKeyMatch(c *C) {
|
||||
c.Check(GpgKey("EC4B033C70096AD1").Matches(GpgKey("EC4B033C70096AD1")), Equals, true)
|
||||
c.Check(GpgKey("37E1C17570096AD1").Matches(GpgKey("EC4B033C70096AD1")), Equals, false)
|
||||
|
||||
c.Check(GpgKey("70096AD1").Matches(GpgKey("70096AD1")), Equals, true)
|
||||
c.Check(GpgKey("70096AD1").Matches(GpgKey("EC4B033C")), Equals, false)
|
||||
|
||||
c.Check(GpgKey("37E1C17570096AD1").Matches(GpgKey("70096AD1")), Equals, true)
|
||||
c.Check(GpgKey("70096AD1").Matches(GpgKey("EC4B033C70096AD1")), Equals, true)
|
||||
}
|
Loading…
Reference in New Issue