From babc4c6f78683295b110a6ef98a656bc3544ea95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Eduardo=20Jer=C3=A9z=20Gir=C3=B3n?= Date: Wed, 4 Sep 2024 23:59:55 -0600 Subject: [PATCH] Implement GetSHA256FromFS function to compute SHA256 hash from a filesystem. Add tests and sample files for validation --- .../util/cryptoutil/get_sha256_from_fs.go | 44 +++++++++++++++++++ .../cryptoutil/get_sha256_from_fs_test.go | 32 ++++++++++++++ .../get_sha256_from_fs_test_data/file1.txt | 1 + .../get_sha256_from_fs_test_data/file2.txt | 1 + .../subfolder/subfolder/file3.txt | 1 + 5 files changed, 79 insertions(+) create mode 100644 internal/util/cryptoutil/get_sha256_from_fs.go create mode 100644 internal/util/cryptoutil/get_sha256_from_fs_test.go create mode 100644 internal/util/cryptoutil/get_sha256_from_fs_test_data/file1.txt create mode 100644 internal/util/cryptoutil/get_sha256_from_fs_test_data/file2.txt create mode 100644 internal/util/cryptoutil/get_sha256_from_fs_test_data/subfolder/subfolder/file3.txt diff --git a/internal/util/cryptoutil/get_sha256_from_fs.go b/internal/util/cryptoutil/get_sha256_from_fs.go new file mode 100644 index 0000000..3836fe6 --- /dev/null +++ b/internal/util/cryptoutil/get_sha256_from_fs.go @@ -0,0 +1,44 @@ +package cryptoutil + +import ( + "crypto/sha256" + "encoding/hex" + "io" + "io/fs" +) + +// GetSHA256FromFS takes a fs.FS and returns a SHA256 hash of the combined contents +// of all files in the filesystem. +// +// If there is an error, it returns an empty string. +func GetSHA256FromFS(fsys fs.FS) string { + hash := sha256.New() + + err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } + + file, err := fsys.Open(path) + if err != nil { + return err + } + defer file.Close() + + if _, err := io.Copy(hash, file); err != nil { + return err + } + + return nil + }) + + if err != nil { + return "" + } + + return hex.EncodeToString(hash.Sum(nil)) +} diff --git a/internal/util/cryptoutil/get_sha256_from_fs_test.go b/internal/util/cryptoutil/get_sha256_from_fs_test.go new file mode 100644 index 0000000..7179128 --- /dev/null +++ b/internal/util/cryptoutil/get_sha256_from_fs_test.go @@ -0,0 +1,32 @@ +package cryptoutil + +import ( + "crypto/sha256" + "embed" + "encoding/hex" + "testing" + + "github.com/stretchr/testify/assert" +) + +//go:embed get_sha256_from_fs_test_data/* +var testFS embed.FS + +func TestGetSHA256FromFS_ValidFS(t *testing.T) { + hash := GetSHA256FromFS(testFS) + assert.NotEmpty(t, hash) + + // To generate the expected hash, you must combine the contents of all the + // files in the test_data directory and calculate the SHA256 hash of the + // resulting string. + expectedHash := "d2c58b6783050a95542286a58250d4dc872877a6cf28610669516dcfacf954af" + assert.Equal(t, expectedHash, hash) +} + +func TestGetSHA256FromFS_EmptyFS(t *testing.T) { + var emptyFS embed.FS + hash := GetSHA256FromFS(emptyFS) + + expectedHash := sha256.New().Sum(nil) + assert.Equal(t, hex.EncodeToString(expectedHash), hash) +} diff --git a/internal/util/cryptoutil/get_sha256_from_fs_test_data/file1.txt b/internal/util/cryptoutil/get_sha256_from_fs_test_data/file1.txt new file mode 100644 index 0000000..a732ac0 --- /dev/null +++ b/internal/util/cryptoutil/get_sha256_from_fs_test_data/file1.txt @@ -0,0 +1 @@ +file 1 contents \ No newline at end of file diff --git a/internal/util/cryptoutil/get_sha256_from_fs_test_data/file2.txt b/internal/util/cryptoutil/get_sha256_from_fs_test_data/file2.txt new file mode 100644 index 0000000..211e228 --- /dev/null +++ b/internal/util/cryptoutil/get_sha256_from_fs_test_data/file2.txt @@ -0,0 +1 @@ +file 2 contents \ No newline at end of file diff --git a/internal/util/cryptoutil/get_sha256_from_fs_test_data/subfolder/subfolder/file3.txt b/internal/util/cryptoutil/get_sha256_from_fs_test_data/subfolder/subfolder/file3.txt new file mode 100644 index 0000000..f0313b0 --- /dev/null +++ b/internal/util/cryptoutil/get_sha256_from_fs_test_data/subfolder/subfolder/file3.txt @@ -0,0 +1 @@ +file 3 contents \ No newline at end of file