Skip to content

Commit bfd2fb4

Browse files
committed
GPG check and avoid redownloading the json every time
1 parent 453530a commit bfd2fb4

File tree

1 file changed

+41
-60
lines changed

1 file changed

+41
-60
lines changed

tools/download.go

+41-60
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ import (
1919
"path/filepath"
2020
"runtime"
2121
"strings"
22+
"time"
2223

23-
"golang.org/x/crypto/openpgp/packet"
24+
"golang.org/x/crypto/openpgp"
2425

2526
"github.com/arduino/arduino-create-agent/utilities"
2627
"github.com/blang/semver"
@@ -65,68 +66,64 @@ var publicKeyHex string = "99020D0452FAA2FA011000D0C5604932111750628F171E4E612D5
6566

6667
func checkGPGSig(fileName string, sigFileName string) error {
6768

68-
// First, get the content of the file we have signed
69-
fileContent, err := ioutil.ReadFile(fileName)
70-
if err != nil {
71-
return err
72-
}
73-
7469
// Get a Reader for the signature file
7570
sigFile, err := os.Open(sigFileName)
7671
if err != nil {
7772
return err
7873
}
7974

80-
defer func() {
81-
if err := sigFile.Close(); err != nil {
82-
panic(err)
83-
}
84-
}()
75+
defer sigFile.Close()
8576

86-
// Read the signature file
87-
pack, err := packet.Read(sigFile)
77+
// Get a Reader for the signature file
78+
file, err := os.Open(fileName)
8879
if err != nil {
8980
return err
9081
}
9182

92-
// Was it really a signature file ? If yes, get the Signature
93-
signature, ok := pack.(*packet.Signature)
94-
if !ok {
95-
return errors.New("Not a valid signature file.")
96-
}
83+
defer file.Close()
9784

98-
// For convenience, we have the key in hexadecimal, convert it to binary
9985
publicKeyBin, err := hex.DecodeString(publicKeyHex)
10086
if err != nil {
10187
return err
10288
}
10389

104-
// Read the key
105-
pack, err = packet.Read(bytes.NewReader(publicKeyBin))
90+
keyring, _ := openpgp.ReadKeyRing(bytes.NewReader(publicKeyBin))
91+
92+
_, err = openpgp.CheckDetachedSignature(keyring, file, sigFile)
93+
94+
return err
95+
}
96+
97+
func (t *Tools) DownloadPackageIndex(index_file, signature_file string) error {
98+
// Fetch the index
99+
resp, err := http.Get(t.IndexURL)
106100
if err != nil {
107101
return err
108102
}
103+
defer resp.Body.Close()
109104

110-
// Was it really a public key file ? If yes, get the PublicKey
111-
publicKey, ok := pack.(*packet.PublicKey)
112-
if !ok {
113-
return errors.New("Invalid public key.")
105+
// Read the body
106+
body, err := ioutil.ReadAll(resp.Body)
107+
if err != nil {
108+
return err
114109
}
115110

116-
// Get the hash method used for the signature
117-
hash := signature.Hash.New()
118-
119-
// Hash the content of the file (if the file is big, that's where you have to change the code to avoid getting the whole file in memory, by reading and writting in small chunks)
120-
_, err = hash.Write(fileContent)
111+
// Fetch the signature
112+
signature, err := http.Get(t.IndexURL + ".sig")
121113
if err != nil {
122114
return err
123115
}
116+
defer signature.Body.Close()
124117

125-
// Check the signature
126-
err = publicKey.VerifySignature(hash, signature)
118+
// Read the body
119+
signature_body, err := ioutil.ReadAll(signature.Body)
127120
if err != nil {
128121
return err
129122
}
123+
ioutil.WriteFile(index_file, body, 0644)
124+
ioutil.WriteFile(signature_file, signature_body, 0644)
125+
126+
t.LastRefresh = time.Now()
130127

131128
return nil
132129
}
@@ -147,35 +144,27 @@ func checkGPGSig(fileName string, sigFileName string) error {
147144
// if it already exists.
148145
func (t *Tools) Download(name, version, behaviour string) error {
149146

150-
// Fetch the index
151-
resp, err := http.Get(t.IndexURL)
152-
if err != nil {
153-
return err
154-
}
155-
defer resp.Body.Close()
147+
index_file := path.Join(t.Directory, "package_index.json")
148+
signature_file := path.Join(t.Directory, "package_index.json.sig")
156149

157-
// Read the body
158-
body, err := ioutil.ReadAll(resp.Body)
159-
if err != nil {
160-
return err
150+
if _, err := os.Stat(path.Join(t.Directory, "package_index.json")); err != nil || time.Since(t.LastRefresh) > 1*time.Hour {
151+
// Download the file again and save it
152+
err = t.DownloadPackageIndex(index_file, signature_file)
153+
if err != nil {
154+
return err
155+
}
161156
}
162157

163-
// Fetch the signature
164-
signature, err := http.Get(t.IndexURL + ".sig")
158+
err := checkGPGSig(index_file, signature_file)
165159
if err != nil {
166160
return err
167161
}
168-
defer signature.Body.Close()
169162

170-
// Read the body
171-
signature_body, err := ioutil.ReadAll(signature.Body)
163+
body, err := ioutil.ReadFile(index_file)
172164
if err != nil {
173165
return err
174166
}
175167

176-
index_file, err := utilities.SaveFileonTempDir("package_index.json", bytes.NewReader(body))
177-
signature_file, err := utilities.SaveFileonTempDir("package_index.json.sig", bytes.NewReader(signature_body))
178-
179168
var data index
180169
json.Unmarshal(body, &data)
181170

@@ -210,17 +199,9 @@ func (t *Tools) Download(name, version, behaviour string) error {
210199
}
211200
}
212201

213-
err = checkGPGSig(index_file, signature_file)
214-
// FIXME - try to understand why it fails
215-
/*
216-
if err != nil {
217-
return err
218-
}
219-
*/
220-
221202
// Download the tool
222203
t.Logger.Println("Downloading tool " + name + " from " + correctSystem.URL)
223-
resp, err = http.Get(correctSystem.URL)
204+
resp, err := http.Get(correctSystem.URL)
224205
if err != nil {
225206
return err
226207
}

0 commit comments

Comments
 (0)