Unverified Commit 7eb9c57a authored by Umberto Baldi's avatar Umberto Baldi Committed by GitHub

Implement function to verify index signature with custom key (#1304)

* add gpg public key to verify board_index.json

* add new function to allow the usage of another gpg key

* add new test and enhance existing ones

* apply suggestions by @cmaglie

* move `module_firmware_index.gpg.key` under `testdata/`
parent cdbebe98
......@@ -22,14 +22,36 @@ import (
"github.com/stretchr/testify/require"
)
func TestSignatureVerification(t *testing.T) {
res, signer, err := VerifyArduinoDetachedSignature(paths.New("testdata/package_index.json"), paths.New("testdata/package_index.json.sig"))
var (
PackageIndexPath = paths.New("testdata/package_index.json")
PackageSignaturePath = paths.New("testdata/package_index.json.sig")
BoardIndexPath = paths.New("testdata/module_firmware_index.json")
BoardSignaturePath = paths.New("testdata/module_firmware_index.json.sig")
BoardKey = paths.New("testdata/module_firmware_index_public.gpg.key")
InvalidIndexPath = paths.New("testdata/invalid_file.json")
)
func TestVerifyArduinoDetachedSignature(t *testing.T) {
res, signer, err := VerifyArduinoDetachedSignature(PackageIndexPath, PackageSignaturePath)
require.NoError(t, err)
require.NotNil(t, signer)
require.True(t, res)
require.Equal(t, uint64(0x7baf404c2dfab4ae), signer.PrimaryKey.KeyId)
res, signer, err = VerifyArduinoDetachedSignature(paths.New("testdata/invalid_file.json"), paths.New("testdata/package_index.json.sig"))
res, signer, err = VerifyArduinoDetachedSignature(InvalidIndexPath, PackageSignaturePath)
require.False(t, res)
require.Nil(t, signer)
require.Error(t, err)
}
func TestVerifyDetachedSignature(t *testing.T) {
res, signer, err := VerifyDetachedSignature(BoardIndexPath, BoardSignaturePath, BoardKey)
require.NoError(t, err)
require.NotNil(t, signer)
require.True(t, res)
require.Equal(t, uint64(0x82f2d7c7c5a22a73), signer.PrimaryKey.KeyId)
res, signer, err = VerifyDetachedSignature(InvalidIndexPath, PackageSignaturePath, BoardKey)
require.False(t, res)
require.Nil(t, signer)
require.Error(t, err)
......
......@@ -17,6 +17,8 @@ package security
import (
"fmt"
"io"
"os"
"github.com/arduino/go-paths-helper"
rice "github.com/cmaglie/go.rice"
......@@ -37,11 +39,33 @@ func VerifyArduinoDetachedSignature(targetPath *paths.Path, signaturePath *paths
if err != nil {
panic("could not find bundled signature keys")
}
return verifySignature(targetPath, signaturePath, arduinoKeyringFile)
}
// VerifyDetachedSignature checks that the detached GPG signature (in the
// signaturePath file) matches the given targetPath file and is an authentic
// signature from the bundled trusted keychain. The keyPath is the path of the public key used.
// This function allows to specify the path of the key to use.
// If any of the above conditions fails this function returns false.
// The PGP entity in the trusted keychain that produced the signature is returned too.
func VerifyDetachedSignature(targetPath *paths.Path, signaturePath *paths.Path, keyPath *paths.Path) (bool, *openpgp.Entity, error) {
arduinoKeyringFile, err := os.Open(keyPath.String())
if err != nil {
panic("could not open signature keys")
}
defer arduinoKeyringFile.Close()
return verifySignature(targetPath, signaturePath, arduinoKeyringFile)
}
//verifySignature is an helper function that checks that the detached GPG signature (in the
// signaturePath file) matches the given targetPath file and is an authentic
// signature. If any of the above conditions fails this function returns false.
// The PGP entity in the trusted keychain that produced the signature is returned too.
func verifySignature(targetPath *paths.Path, signaturePath *paths.Path, arduinoKeyringFile io.Reader) (bool, *openpgp.Entity, error) {
keyRing, err := openpgp.ReadKeyRing(arduinoKeyringFile)
if err != nil {
return false, nil, fmt.Errorf("retrieving Arduino public keys: %s", err)
}
target, err := targetPath.Open()
if err != nil {
return false, nil, fmt.Errorf("opening target file: %s", err)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment