5 Commits

6 changed files with 134 additions and 15 deletions

View File

@@ -1,8 +1,8 @@
name: build-and-test name: build-release
on: on:
push: push:
tags: tags:
- "*" - "v*.*.*"
jobs: jobs:
release: release:
@@ -10,10 +10,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v1 uses: actions/setup-go@v5
with: with:
go-version: 1.22.11 go-version: 1.22.11
@@ -30,3 +30,58 @@ jobs:
tag: ${{ github.ref_name }} tag: ${{ github.ref_name }}
file: ./releases/* file: ./releases/*
file_glob: true file_glob: true
- name: Build Changelog
id: github_release
uses: mikepenz/release-changelog-builder-action@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
mode: "PR"
configurationJson: |
{
"template": "#{{CHANGELOG}}\n\n**Full Changelog**: #{{RELEASE_DIFF}}",
"pr_template": "- #{{TITLE}} (##{{NUMBER}}) by #{{AUTHOR}}\n#{{BODY}}",
"empty_template": "- no changes",
"categories": [
{
"title": "## New Features",
"labels": ["add", "feature"]
},
{
"title": "## Bug Fixes",
"labels": ["fix", "bug", "revert"]
},
{
"title": "## Documentation Enhancements",
"labels": ["doc"]
},
{
"title": "## Refactoring Efforts",
"labels": ["refactor"]
},
{
"title": "## Miscellaneus Changes",
"labels": []
}
],
"ignore_labels": [
"duplicate", "good first issue", "help wanted", "invalid", "question", "wontfix"
],
"label_extractor": [
{
"pattern": "(.) (.+)",
"target": "$1"
},
{
"pattern": "(.) (.+)",
"target": "$1",
"on_property": "title"
}
]
}
- name: Create Release
uses: softprops/action-gh-release@v2
with:
body: ${{steps.github_release.outputs.changelog}}

View File

@@ -38,7 +38,7 @@ install: buildlocal
clean: clean:
rm -rf $(tool) coverage.out rm -rf $(tool) coverage.out
test: test: clean
go test -v ./... go test -v ./...
singletest: singletest:

View File

@@ -5,6 +5,52 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/tlinden/gowipe)](https://goreportcard.com/report/github.com/tlinden/gowipe) [![Go Report Card](https://goreportcard.com/badge/github.com/tlinden/gowipe)](https://goreportcard.com/report/github.com/tlinden/gowipe)
[![GitHub release](https://img.shields.io/github/v/release/tlinden/gowipe?color=%2300a719)](https://github.com/TLINDEN/gowipe/releases/latest) [![GitHub release](https://img.shields.io/github/v/release/tlinden/gowipe?color=%2300a719)](https://github.com/TLINDEN/gowipe/releases/latest)
## Description
`gowipe` is a simple self contained tool to securely wipe files and
directories. By default it renames and overwrites files and
directories 30 times and uses the `secure` mode, which uses strong
random bytes for the overwriting process. Gowipe writes as much bytes
into a file as its original size.
You can tweak mode and round numbers. Other modes are `zero`, which
uses zeroes for overwriting (not recommended) or `encrypt` which
encrypts the data using ChaCha20Poly1305 and a strong random key. This is the most
secure but also to slowest mode.
Although you can use `gowipe` on SSD disks, it doesn't make much
sense. To wipe such a disk you have to resort to other means. But you
can savely use it on magnetic discs or usb drives.
Of course there are many other such tools available, this one is
insofar special as you can download a pre-compiled binary without any
library dependencies. This allows you to wipe files on systems, where
you cannot install a wiper via some package management (such as
appliance systems or vm's).
## Example
Overwrite the directory `vhs` recursively 50 times using strong
encryption and verbose output:
```shell
gowipe -c 50 -E -r -v vhs
Wiped vhs/help.png (355011 bytes)
Wiped vhs/rec.Dockerfile (348 bytes)
Wiped vhs/rec.gif (3533338 bytes)
Wiped vhs/rec.tape (852 bytes)
Wiped vhs (4096 bytes)
Dirs wiped: 1
Files wiped: 5
Bytes deleted: 3889549
Time elapsed: 426.286639ms
Overwritten: 50 times
Wipe mode: encrypt
Recurse dirs: true
```
## Usage
``` ```
Usage: gowipe [-rcvz] <file|directory>... Usage: gowipe [-rcvz] <file|directory>...

View File

@@ -1,5 +1,5 @@
/* /*
Copyright © 2022 Thomas von Dein Copyright © 2022-2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

34
main.go
View File

@@ -1,5 +1,5 @@
/* /*
Copyright © 2022 Thomas von Dein Copyright © 2022-2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -22,12 +22,13 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time"
"github.com/JojiiOfficial/shred" "github.com/JojiiOfficial/shred"
flag "github.com/spf13/pflag" flag "github.com/spf13/pflag"
) )
const VERSION string = "0.0.3" const VERSION string = "0.0.4"
const Usage string = `This is gowipe - destruct files in a non-recoverable way. const Usage string = `This is gowipe - destruct files in a non-recoverable way.
Usage: gowipe [-rcvz] <file|directory>... Usage: gowipe [-rcvz] <file|directory>...
@@ -55,6 +56,9 @@ type Conf struct {
nodelete bool nodelete bool
norename bool norename bool
verbose bool verbose bool
files int
dirs int
size int64
} }
func main() { func main() {
@@ -138,14 +142,26 @@ func main() {
shredder := shred.Shredder{} shredder := shred.Shredder{}
shredconf := shred.NewShredderConf(&shredder, option, c.count, !c.nodelete) shredconf := shred.NewShredderConf(&shredder, option, c.count, !c.nodelete)
start := time.Now()
for _, file := range flag.Args() { for _, file := range flag.Args() {
Wipe(file, &c, shredconf) Wipe(file, &c, shredconf)
} }
if c.verbose {
fmt.Println()
fmt.Printf(" Dirs wiped: %d\n", c.dirs)
fmt.Printf(" Files wiped: %d\n", c.files)
fmt.Printf("Bytes deleted: %d\n", c.size)
fmt.Printf(" Time elapsed: %s\n", time.Since(start))
fmt.Printf(" Overwritten: %d times\n", c.count)
fmt.Printf(" Wipe mode: %s\n", c.mode)
fmt.Printf(" Recurse dirs: %t\n", c.recurse)
}
} }
func Wipe(file string, c *Conf, wiper *shred.ShredderConf) { func Wipe(file string, c *Conf, wiper *shred.ShredderConf) {
if info, err := os.Stat(file); err == nil { if info, err := os.Stat(file); err == nil {
if info.IsDir() { if info.IsDir() {
if !c.recurse { if !c.recurse {
fmt.Printf("-r not set, ignoring directory %s\n", file) fmt.Printf("-r not set, ignoring directory %s\n", file)
@@ -167,6 +183,8 @@ func Wipe(file string, c *Conf, wiper *shred.ShredderConf) {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
c.dirs++
} }
} else { } else {
if c.mode == "encrypt" { if c.mode == "encrypt" {
@@ -186,11 +204,15 @@ func Wipe(file string, c *Conf, wiper *shred.ShredderConf) {
log.Fatal(err) log.Fatal(err)
} }
} }
c.size += info.Size()
} }
if c.verbose { if c.verbose {
fmt.Printf("Wiped %d times: %s\n", c.count, file) fmt.Printf("Wiped %s (%d bytes)\n", file, info.Size())
} }
c.files++
} else { } else {
if os.IsNotExist(err) { if os.IsNotExist(err) {
fmt.Printf("No such file or directory: %s\n", file) fmt.Printf("No such file or directory: %s\n", file)
@@ -227,10 +249,6 @@ func Rename(file string, c *Conf) string {
} }
} }
if c.verbose {
fmt.Printf("renaming %s/%s => %s/%s\n", dir, base, dir, newname)
}
err := os.Rename(filepath.Join(dir, base), filepath.Join(dir, newname)) err := os.Rename(filepath.Join(dir, base), filepath.Join(dir, newname))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# Copyright © 2022 Thomas von Dein # Copyright © 2022-2025 Thomas von Dein
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by