From fa61efc332504c32901786f49bd0a83d9a3d61d4 Mon Sep 17 00:00:00 2001 From: Giacomo Benedetti Date: Thu, 11 Sep 2025 15:09:33 +0200 Subject: [PATCH 1/2] Compute hash for stabilized artifact and compare with original artifact's hash --- pkg/archive/zip.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/pkg/archive/zip.go b/pkg/archive/zip.go index 6b841fe0..9f19d696 100644 --- a/pkg/archive/zip.go +++ b/pkg/archive/zip.go @@ -7,6 +7,7 @@ import ( "archive/zip" "bytes" "crypto/sha256" + "encoding/base64" "encoding/hex" "io" "slices" @@ -216,14 +217,22 @@ func StabilizeZip(zr *zip.Reader, zw *zip.Writer, opts StabilizeOpts) error { } mr := NewMutableReader(zr) for _, s := range opts.Stabilizers { + var currentStabName string + originalArchiveHash := getArchiveHash(&mr) switch s.(type) { case ZipArchiveStabilizer: + currentStabName = s.(ZipArchiveStabilizer).Name s.(ZipArchiveStabilizer).Stabilize(&mr) case ZipEntryStabilizer: + currentStabName = s.(ZipEntryStabilizer).Name for _, mf := range mr.File { s.(ZipEntryStabilizer).Stabilize(mf) } } + newArchiveHash := getArchiveHash(&mr) + if originalArchiveHash != newArchiveHash { + println("Stabilizer taking effect:", currentStabName) + } } return mr.WriteTo(zw) } @@ -252,3 +261,27 @@ func toZipCompatibleReader(r io.Reader) (io.ReaderAt, int64, error) { } return bytes.NewReader(b), int64(len(b)), nil } + +// Helper to compute SHA256 and encode as base64 (url encoding, no padding) +func computeSHA256Base64(data []byte) string { + h := sha256.New() + h.Write(data) + sum := h.Sum(nil) + return base64.RawURLEncoding.EncodeToString(sum) +} + +func getArchiveHash(zr *MutableZipReader) string { + var buf bytes.Buffer + for _, zf := range zr.File { + content, err := zf.Open() + if err != nil { + continue + } + data, err := io.ReadAll(content) + if err != nil { + continue + } + buf.Write(data) + } + return computeSHA256Base64(buf.Bytes()) +} From 3c492ae9da538897c6bed93b420d6851820e70cd Mon Sep 17 00:00:00 2001 From: Giacomo Benedetti Date: Thu, 25 Sep 2025 14:59:36 +0200 Subject: [PATCH 2/2] remove helper functions and reuse mutableReader + write to stderr --- pkg/archive/zip.go | 64 +++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/pkg/archive/zip.go b/pkg/archive/zip.go index 9f19d696..f4f1cca4 100644 --- a/pkg/archive/zip.go +++ b/pkg/archive/zip.go @@ -7,9 +7,9 @@ import ( "archive/zip" "bytes" "crypto/sha256" - "encoding/base64" "encoding/hex" "io" + "log" "slices" "strings" "time" @@ -211,27 +211,39 @@ var StableZipMisc = ZipEntryStabilizer{ // StabilizeZip strips volatile metadata and rewrites the provided archive in a standard form. func StabilizeZip(zr *zip.Reader, zw *zip.Writer, opts StabilizeOpts) error { defer zw.Close() - var headers []zip.FileHeader - for _, zf := range zr.File { - headers = append(headers, zf.FileHeader) - } mr := NewMutableReader(zr) for _, s := range opts.Stabilizers { var currentStabName string - originalArchiveHash := getArchiveHash(&mr) - switch s.(type) { + + // Compute original archive hash + h1 := sha256.New() + err := mr.WriteTo(zip.NewWriter(h1)) + if err != nil { + return errors.Wrap(err, "computing original archive hash") + } + originalArchiveHash := h1.Sum(nil) + + switch s := s.(type) { case ZipArchiveStabilizer: - currentStabName = s.(ZipArchiveStabilizer).Name - s.(ZipArchiveStabilizer).Stabilize(&mr) + currentStabName = s.Name + s.Stabilize(&mr) case ZipEntryStabilizer: - currentStabName = s.(ZipEntryStabilizer).Name + currentStabName = s.Name for _, mf := range mr.File { - s.(ZipEntryStabilizer).Stabilize(mf) + s.Stabilize(mf) } } - newArchiveHash := getArchiveHash(&mr) - if originalArchiveHash != newArchiveHash { - println("Stabilizer taking effect:", currentStabName) + + // Compute new archive hash + h2 := sha256.New() + err = mr.WriteTo(zip.NewWriter(h2)) + if err != nil { + return errors.Wrap(err, "computing new archive hash") + } + newArchiveHash := h2.Sum(nil) + + if !bytes.Equal(originalArchiveHash, newArchiveHash) { + log.Printf("Stabilizer taking effect: %s\n", currentStabName) } } return mr.WriteTo(zw) @@ -261,27 +273,3 @@ func toZipCompatibleReader(r io.Reader) (io.ReaderAt, int64, error) { } return bytes.NewReader(b), int64(len(b)), nil } - -// Helper to compute SHA256 and encode as base64 (url encoding, no padding) -func computeSHA256Base64(data []byte) string { - h := sha256.New() - h.Write(data) - sum := h.Sum(nil) - return base64.RawURLEncoding.EncodeToString(sum) -} - -func getArchiveHash(zr *MutableZipReader) string { - var buf bytes.Buffer - for _, zf := range zr.File { - content, err := zf.Open() - if err != nil { - continue - } - data, err := io.ReadAll(content) - if err != nil { - continue - } - buf.Write(data) - } - return computeSHA256Base64(buf.Bytes()) -}