From 0191e17d98e74cdee206d07e211543cb910a3711 Mon Sep 17 00:00:00 2001 From: harisabdullah Date: Mon, 7 Aug 2023 11:21:42 +0500 Subject: [PATCH 1/3] Performing checksums after downloading the file. --- ipinfo/cmd_download.go | 65 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/ipinfo/cmd_download.go b/ipinfo/cmd_download.go index 6cb8e36e..4e124f7c 100644 --- a/ipinfo/cmd_download.go +++ b/ipinfo/cmd_download.go @@ -2,6 +2,8 @@ package main import ( "compress/gzip" + "crypto/sha256" + "encoding/json" "errors" "fmt" "io" @@ -17,6 +19,14 @@ import ( const dbDownloadURL = "https://ipinfo.io/data/free/" +type ChecksumResponse struct { + Checksums struct { + MD5 string `json:"md5"` + SHA1 string `json:"sha1"` + SHA256 string `json:"sha256"` + } `json:"checksums"` +} + var completionsDownload = &complete.Command{ Flags: map[string]complete.Predictor{ "-c": predict.Nothing, @@ -136,6 +146,26 @@ func cmdDownload() error { url := fmt.Sprintf("%s%s.%s?token=%s", dbDownloadURL, dbName, format, token) err := downloadDb(url, fileName, format, fZip) + + // check if checksums match. + checksumUrl := fmt.Sprintf("%s%s.%s/checksums?token=%s", dbDownloadURL, dbName, format, token) + // fetch checksums from API. + checksumResponse, err := fetchChecksums(checksumUrl) + if err != nil { + return err + } + + // compute checksum of downloaded file. + localChecksum, err := computeSHA256(fileName) + if err != nil { + return err + } + + // compare checksums. + if localChecksum != checksumResponse.Checksums.SHA256 { + return errors.New("checksums do not match. File might be corrupted") + } + if err != nil { return err } @@ -238,3 +268,38 @@ func unzipWrite(file *os.File, data io.Reader) error { return nil } + +func computeSHA256(filepath string) (string, error) { + file, err := os.Open(filepath) + if err != nil { + return "", err + } + defer file.Close() + + hasher := sha256.New() + if _, err := io.Copy(hasher, file); err != nil { + return "", err + } + + return fmt.Sprintf("%x", hasher.Sum(nil)), nil +} + +func fetchChecksums(url string) (*ChecksumResponse, error) { + resp, err := http.Get(url) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var checksumResponse ChecksumResponse + if err := json.Unmarshal(body, &checksumResponse); err != nil { + return nil, err + } + + return &checksumResponse, nil +} From e357a68dc1ec4423bd758b7ab22c5557fa6c3caa Mon Sep 17 00:00:00 2001 From: Haris Date: Mon, 7 Aug 2023 13:08:29 +0500 Subject: [PATCH 2/3] Update ipinfo/cmd_download.go Co-authored-by: Uman Shahzad --- ipinfo/cmd_download.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ipinfo/cmd_download.go b/ipinfo/cmd_download.go index 4e124f7c..5b37711d 100644 --- a/ipinfo/cmd_download.go +++ b/ipinfo/cmd_download.go @@ -147,9 +147,8 @@ func cmdDownload() error { url := fmt.Sprintf("%s%s.%s?token=%s", dbDownloadURL, dbName, format, token) err := downloadDb(url, fileName, format, fZip) - // check if checksums match. + // fetch checksums from API and check if they match. checksumUrl := fmt.Sprintf("%s%s.%s/checksums?token=%s", dbDownloadURL, dbName, format, token) - // fetch checksums from API. checksumResponse, err := fetchChecksums(checksumUrl) if err != nil { return err From b96512a039fb42542c708b186cd924665949d9e6 Mon Sep 17 00:00:00 2001 From: harisabdullah Date: Mon, 7 Aug 2023 13:24:33 +0500 Subject: [PATCH 3/3] Refactoring --- ipinfo/cmd_download.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ipinfo/cmd_download.go b/ipinfo/cmd_download.go index 5b37711d..fa1ffc21 100644 --- a/ipinfo/cmd_download.go +++ b/ipinfo/cmd_download.go @@ -146,6 +146,9 @@ func cmdDownload() error { url := fmt.Sprintf("%s%s.%s?token=%s", dbDownloadURL, dbName, format, token) err := downloadDb(url, fileName, format, fZip) + if err != nil { + return err + } // fetch checksums from API and check if they match. checksumUrl := fmt.Sprintf("%s%s.%s/checksums?token=%s", dbDownloadURL, dbName, format, token) @@ -165,10 +168,6 @@ func cmdDownload() error { return errors.New("checksums do not match. File might be corrupted") } - if err != nil { - return err - } - return nil } @@ -288,8 +287,8 @@ func fetchChecksums(url string) (*ChecksumResponse, error) { if err != nil { return nil, err } - defer resp.Body.Close() + defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, err