Golang : Secure file deletion with wipe example
Problem:
You are not sure if the file deleted by os.Remove()
function is good enough to remove your data forever. You have some sensitive data that you do not want the wrong hands to retrieve and you want to securely wipe the file before removing it. How to do that?
Solution:
First, we need to find out how large(size) the file is and create a new slice base on the size filled with 0
value. Use the slice to wipe/replace every single byte in the target file. In this way, we can be sure that the data that we want to remove is wiped clean. The first example is good enough to handle most files.
However, if the target file is big(more than 100MB)...it will use up a lot of available memory and it is not a robust program. To handle a large file, please use the code in example 2.
Here you go!
Example 1:
securedelete.go
package main
import (
"fmt"
"os"
)
func main() {
var targetFile = "somefile"
// make sure we open the file with correct permission
// otherwise we will get the
// bad file descriptor error
file, err := os.OpenFile(targetFile, os.O_RDWR, 0666)
if err != nil {
panic(err.Error())
}
defer file.Close()
// find out how large is the target file
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
// calculate the new slice size
// base on how large our target file is
var size int64 = fileInfo.Size()
zeroBytes := make([]byte, size)
// fill out the new slice with 0 value
copy(zeroBytes[:], "0")
fmt.Println(zeroBytes[:])
// wipe the content of the target file
n, err := file.Write([]byte(zeroBytes))
if err != nil {
panic(err)
}
fmt.Printf("Wiped %v bytes.\n", n)
// finally remove/delete our file
err = os.Remove(targetFile)
if err != nil {
panic(err)
}
}
To delete a large file, it is better to process the file chunk by chunk when wiping so that it doesn't consume a lot of memory.
securedeletelargefile.go
package main
import (
"fmt"
"math"
"os"
)
func main() {
var targetFile = "bigfile"
// make sure we open the file with correct permission
// otherwise we will get the
// bad file descriptor error
file, err := os.OpenFile(targetFile, os.O_RDWR, 0666)
if err != nil {
panic(err.Error())
}
defer file.Close()
// find out how large is the target file
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
// calculate the new slice size
// base on how large our target file is
var fileSize int64 = fileInfo.Size()
const fileChunk = 1 * (1 << 20) // 1 MB, change this to your requirement
// calculate total number of parts the file will be chunked into
totalPartsNum := uint64(math.Ceil(float64(fileSize) / float64(fileChunk)))
lastPosition := 0
for i := uint64(0); i < totalPartsNum; i++ {
partSize := int(math.Min(fileChunk, float64(fileSize-int64(i*fileChunk))))
partZeroBytes := make([]byte, partSize)
// fill out the part with zero value
copy(partZeroBytes[:], "0")
// over write every byte in the chunk with 0
fmt.Println("Writing to target file from position : ", lastPosition)
n, err := file.WriteAt([]byte(partZeroBytes), int64(lastPosition))
if err != nil {
panic(err.Error())
}
fmt.Printf("Wiped %v bytes.\n", n)
// update last written position
lastPosition = lastPosition + partSize
}
// finally remove/delete our file
err = os.Remove(targetFile)
if err != nil {
panic(err)
}
}
NOTE:
You need to provide both bigfile
and somefile
in order to run the codes above. To see if a file is really been securely wiped. Comment out the os.Remove()
function and then view the files content after executing the wipe process.
References:
https://www.socketloop.com/tutorials/golang-delete-file
https://socketloop.com/references/golang-os-file-write-writestring-and-writeat-functions-example
https://www.socketloop.com/tutorials/golang-read-binary-file-into-memory
https://www.socketloop.com/tutorials/golang-how-to-split-or-chunking-a-file-to-smaller-pieces
See also : Golang : Delete files by extension
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+9.8k CodeIgniter : Load different view for mobile devices
+19k Golang : Execute shell command
+9.2k Golang : Qt Yes No and Quit message box example
+19.6k Golang : How to run your code only once with sync.Once object
+10.2k Android Studio : Simple input textbox and intercept key example
+7.7k Golang : Gomobile init produce "iphoneos" cannot be located error
+34.7k Golang : Upload and download file to/from AWS S3
+13.6k Golang : convert(cast) string to float value
+5.3k PHP : Convert CSV to JSON with YQL example
+22.3k Generate checksum for a file in Go
+9.3k Golang : Validate IPv6 example
+8.7k Golang : How to capture return values from goroutines?