verifyChecksum downloads the expected SHA256 checksum and verifies the file.
(filePath, checksumURL string)
| 267 | |
| 268 | // verifyChecksum downloads the expected SHA256 checksum and verifies the file. |
| 269 | func verifyChecksum(filePath, checksumURL string) error { |
| 270 | // Download checksum file |
| 271 | client := &http.Client{Timeout: checkTimeout} |
| 272 | resp, err := client.Get(checksumURL) |
| 273 | if err != nil { |
| 274 | return fmt.Errorf("downloading checksum: %w", err) |
| 275 | } |
| 276 | defer resp.Body.Close() |
| 277 | |
| 278 | if resp.StatusCode != http.StatusOK { |
| 279 | return fmt.Errorf("checksum download returned status %d", resp.StatusCode) |
| 280 | } |
| 281 | |
| 282 | body, err := io.ReadAll(resp.Body) |
| 283 | if err != nil { |
| 284 | return fmt.Errorf("reading checksum: %w", err) |
| 285 | } |
| 286 | |
| 287 | // Parse checksum (format: "hash filename" or just "hash") |
| 288 | expectedHash := strings.Fields(strings.TrimSpace(string(body)))[0] |
| 289 | |
| 290 | // Calculate actual hash |
| 291 | f, err := os.Open(filePath) |
| 292 | if err != nil { |
| 293 | return fmt.Errorf("opening file for checksum: %w", err) |
| 294 | } |
| 295 | defer f.Close() |
| 296 | |
| 297 | h := sha256.New() |
| 298 | if _, err := io.Copy(h, f); err != nil { |
| 299 | return fmt.Errorf("computing checksum: %w", err) |
| 300 | } |
| 301 | actualHash := hex.EncodeToString(h.Sum(nil)) |
| 302 | |
| 303 | if actualHash != expectedHash { |
| 304 | return fmt.Errorf("expected %s, got %s", expectedHash, actualHash) |
| 305 | } |
| 306 | |
| 307 | return nil |
| 308 | } |
no outgoing calls