Project 13: File integrity checker

Nemuel Wainaina
3 min readOct 1, 2024

--

Complete video course: Udemy

Introduction

File integrity checker is a program that uses a hashing algorithm to verify the authenticity of a file. A hash is a fixed-size value generated from some input using a hashing algorithm. A hashing algorithm is a mathematical function that takes data as input and generates a fixed-size value unique to that specific input. Even changing a single bit in the input results in an entirely new hash.

Thanks to these properties of hashing, it has been adopted for many uses, among them verifying data integrity. Armed with a file and the hash value of the original file, we can confirm that what we have is indeed the original one. This is done by generating a hash of our file and comparing the result with the original hash value. A match indicates it is indeed original and unmanipulated.

Practical

Boilerplate code:

package main

import (

)

func main() {

}

As with the previous project, we shall use command-line arguments to pass 2 values to our program: the file to verify, and the original hash. Let us first import the packages that we will need:

import (
"crypto/sha256"
"encoding/hex"
"fmt"
"os"
)

The sha256 and hex packages will be used for the hashing process, fmt for the usual input/output operations, and the os package for reading the file contents for hashing.

In the main function, we can start by verifying that all required arguments are provided using the os.Args value:

if len(os.Args) != 3 {
fmt.Println("Usage: ./fichecker <filename> <originalhash>")
return
}

Next, we will save the provided values (filename and original hash) to variables:

file_name := os.Args[1]
original_hash := os.Args[2]

We start with index 1 since index 0 is reserved for the program name. With the filename, we can open the file and read its contents:

contents, err := os.ReadFile(file_name)
if err != nil {
fmt.Println(err)
return
}

Once we have the file contents, we can go ahead and hash it before comparing it with the original hash. Let us create a separate function to handle the hashing:

func hash_content(content []byte) string {
hasher := sha256.New()
hasher.Write(content)
result := hasher.Sum(nil)
hash := hex.EncodeToString(result)
return hash
}

The above function takes in a single argument which is a slice of bytes, hashes it, and returns the hash as a string. The hashing process involves first creating an instance of sha256 using the New() function, writing the passed content to it, hashing it using the Sum() function, and finally encoding it as a string. This is because the Sum() returns a hexadecimal representation. Since we will be comparing this to the user-provided hash (which is of type string), we need to convert this to a string as well. We finally return this value using the return keyword.

Back in the main function, we can now call the hash_content function to get the hash of the user-provided file:

hash := hash_content(contents)

Finally, we display the result to the user based on whether or not the above hash is similar to the user-provided hash:

if hash == original_hash {
fmt.Println("The file is intact")
} else {
fmt.Println("The file is not intact and has been tampered with")
}

Complete code:

package main

import (
"crypto/sha256"
"encoding/hex"
"fmt"
"os"
)

func hash_content(content []byte) string {
hasher := sha256.New()
hasher.Write(content)
result := hasher.Sum(nil)
hash := hex.EncodeToString(result)
return hash
}


func main() {
// ./fichecker filename originalhash
if len(os.Args) != 3 {
fmt.Println("Usage: ./fichecker <filename> <originalhash>")
return
}

file_name := os.Args[1]
original_hash := os.Args[2]
contents, err := os.ReadFile(file_name)
if err != nil {
fmt.Println(err)
return
}
hash := hash_content(contents)
if hash == original_hash {
fmt.Println("The file is intact")
} else {
fmt.Println("The file is not intact and has been tampered with")
}
}

Next: Project 14: Profile viewer

--

--

Nemuel Wainaina
Nemuel Wainaina

Written by Nemuel Wainaina

Security Researcher | Software Engineer

No responses yet