Finalize v1.15
This commit is contained in:
parent
c59d8f0f69
commit
69c2b49a48
114
src/Picocrypt.go
114
src/Picocrypt.go
|
@ -2,7 +2,7 @@ package main
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Picocrypt v1.14
|
Picocrypt v1.15
|
||||||
Copyright (c) Evan Su (https://evansu.cc)
|
Copyright (c) Evan Su (https://evansu.cc)
|
||||||
Released under a GNU GPL v3 License
|
Released under a GNU GPL v3 License
|
||||||
https://github.com/HACKERALERT/Picocrypt
|
https://github.com/HACKERALERT/Picocrypt
|
||||||
|
@ -21,6 +21,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"math"
|
"math"
|
||||||
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
"sync"
|
"sync"
|
||||||
"hash"
|
"hash"
|
||||||
|
@ -69,7 +70,7 @@ import (
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "v1.14"
|
var version = "v1.15"
|
||||||
|
|
||||||
//go:embed NotoSans-Regular.ttf
|
//go:embed NotoSans-Regular.ttf
|
||||||
var font []byte
|
var font []byte
|
||||||
|
@ -118,6 +119,8 @@ var splitUnits = []string{
|
||||||
"GiB",
|
"GiB",
|
||||||
}
|
}
|
||||||
var splitSelected int32 // Index of which splitting unit was chosen from above
|
var splitSelected int32 // Index of which splitting unit was chosen from above
|
||||||
|
var shredPasses = "4"
|
||||||
|
var stopShredding = false
|
||||||
var shredProgress float32
|
var shredProgress float32
|
||||||
var shredDone float32
|
var shredDone float32
|
||||||
var shredTotal float32 // Total files to shred (recursive)
|
var shredTotal float32 // Total files to shred (recursive)
|
||||||
|
@ -171,6 +174,9 @@ var sha3_256_selected = false
|
||||||
var blake2b_selected = false
|
var blake2b_selected = false
|
||||||
var blake2s_selected = false
|
var blake2s_selected = false
|
||||||
|
|
||||||
|
// Link to a Wikipedia article on Reed-Solomon
|
||||||
|
var rsWikipedia = "https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction"
|
||||||
|
|
||||||
// Create the UI
|
// Create the UI
|
||||||
func startUI(){
|
func startUI(){
|
||||||
giu.SingleWindow().Layout(
|
giu.SingleWindow().Layout(
|
||||||
|
@ -291,11 +297,21 @@ func startUI(){
|
||||||
// Prompt for password
|
// Prompt for password
|
||||||
giu.Row(
|
giu.Row(
|
||||||
giu.Label("Password:"),
|
giu.Label("Password:"),
|
||||||
|
giu.SmallButton("Generate").OnClick(func(){
|
||||||
|
tmp := genPassword()
|
||||||
|
password = tmp
|
||||||
|
cPassword = tmp
|
||||||
|
passwordStrength = zxcvbn.PasswordStrength(password,nil).Score
|
||||||
|
giu.Update()
|
||||||
|
}),
|
||||||
|
giu.SmallButton("Copy").OnClick(func(){
|
||||||
|
clipboard.WriteAll(password)
|
||||||
|
}),
|
||||||
giu.Dummy(-200,0),
|
giu.Dummy(-200,0),
|
||||||
giu.Label(keyfilePrompt),
|
giu.Label(keyfilePrompt),
|
||||||
),
|
),
|
||||||
giu.Row(
|
giu.Row(
|
||||||
giu.InputText(&password).Size(240/dpi).Flags(giu.InputTextFlagsPassword).OnChange(func(){
|
giu.InputText(&password).Size(241/dpi).Flags(giu.InputTextFlagsPassword).OnChange(func(){
|
||||||
passwordStrength = zxcvbn.PasswordStrength(password,nil).Score
|
passwordStrength = zxcvbn.PasswordStrength(password,nil).Score
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -325,7 +341,10 @@ func startUI(){
|
||||||
int(math.Round(float64(6*dpi))),
|
int(math.Round(float64(6*dpi))),
|
||||||
int(math.Round(float64(12*dpi))),
|
int(math.Round(float64(12*dpi))),
|
||||||
))
|
))
|
||||||
canvas.PathArcTo(path,8*dpi,0,float32(passwordStrength+1)/5*(2*math.Pi),-1)
|
canvas.PathArcTo(path,
|
||||||
|
8*dpi,-math.Pi/2,
|
||||||
|
float32(passwordStrength+1)/5*(2*math.Pi)-math.Pi/2,
|
||||||
|
-1)
|
||||||
canvas.PathStroke(col,false,3)
|
canvas.PathStroke(col,false,3)
|
||||||
}),
|
}),
|
||||||
giu.Dummy(-200,0),
|
giu.Dummy(-200,0),
|
||||||
|
@ -348,7 +367,7 @@ func startUI(){
|
||||||
// Prompt to confirm password
|
// Prompt to confirm password
|
||||||
giu.Label("Confirm password:"),
|
giu.Label("Confirm password:"),
|
||||||
giu.Row(
|
giu.Row(
|
||||||
giu.InputText(&cPassword).Size(240/dpi).Flags(giu.InputTextFlagsPassword),
|
giu.InputText(&cPassword).Size(241/dpi).Flags(giu.InputTextFlagsPassword),
|
||||||
giu.Custom(func(){
|
giu.Custom(func(){
|
||||||
canvas := giu.GetCanvas()
|
canvas := giu.GetCanvas()
|
||||||
pos := giu.GetCursorScreenPos()
|
pos := giu.GetCursorScreenPos()
|
||||||
|
@ -388,12 +407,14 @@ func startUI(){
|
||||||
giu.Row(
|
giu.Row(
|
||||||
giu.Checkbox("Encode with Reed-Solomon to prevent corruption (slow)",&reedsolo),
|
giu.Checkbox("Encode with Reed-Solomon to prevent corruption (slow)",&reedsolo),
|
||||||
giu.Button("?").Size(24,25).OnClick(func(){
|
giu.Button("?").Size(24,25).OnClick(func(){
|
||||||
browser.OpenURL("https://bit.ly/3A2V7LR")
|
browser.OpenURL(rsWikipedia)
|
||||||
}),
|
}),
|
||||||
).Build()
|
).Build()
|
||||||
giu.Row(
|
giu.Row(
|
||||||
giu.Checkbox("Split output into chunks of",&split),
|
giu.Checkbox("Split output into chunks of",&split),
|
||||||
giu.InputText(&splitSize).Size(50).Flags(giu.InputTextFlagsCharsDecimal),
|
giu.InputText(&splitSize).Size(50).Flags(giu.InputTextFlagsCharsDecimal).OnChange(func(){
|
||||||
|
split = true
|
||||||
|
}),
|
||||||
giu.Combo("##splitter",splitUnits[splitSelected],splitUnits,&splitSelected).Size(52),
|
giu.Combo("##splitter",splitUnits[splitSelected],splitUnits,&splitSelected).Size(52),
|
||||||
).Build()
|
).Build()
|
||||||
giu.Dummy(0,1).Build()
|
giu.Dummy(0,1).Build()
|
||||||
|
@ -569,7 +590,26 @@ func startUI(){
|
||||||
}),
|
}),
|
||||||
|
|
||||||
giu.Label("Drop file(s) and folder(s) here to shred them."),
|
giu.Label("Drop file(s) and folder(s) here to shred them."),
|
||||||
giu.ProgressBar(shredProgress).Overlay(shredOverlay).Size(-0.0000001,0),
|
giu.Custom(func(){
|
||||||
|
if runtime.GOOS=="darwin"{
|
||||||
|
giu.Label("Number of passes: Not supported on macOS").Build()
|
||||||
|
}else{
|
||||||
|
giu.Row(
|
||||||
|
giu.Label("Number of passes:"),
|
||||||
|
giu.InputText(&shredPasses).Size(16).Flags(giu.InputTextFlagsCharsDecimal),
|
||||||
|
).Build()
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
giu.Dummy(0,-50),
|
||||||
|
giu.Row(
|
||||||
|
giu.ProgressBar(shredProgress).Overlay(shredOverlay).Size(-65,0),
|
||||||
|
giu.Button("Cancel").Size(58,0).OnClick(func(){
|
||||||
|
stopShredding = true
|
||||||
|
shredding = "Ready."
|
||||||
|
shredProgress = 0
|
||||||
|
shredOverlay = ""
|
||||||
|
}),
|
||||||
|
),
|
||||||
giu.Custom(func(){
|
giu.Custom(func(){
|
||||||
if len(shredding)>50{
|
if len(shredding)>50{
|
||||||
shredding = "....."+shredding[len(shredding)-50:]
|
shredding = "....."+shredding[len(shredding)-50:]
|
||||||
|
@ -688,7 +728,7 @@ func onDrop(names []string){
|
||||||
fin.Close()
|
fin.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if valid,_:=regexp.Match(`^v\d\.\d{2}.{10}0?\d+`,tmp);!valid{
|
if valid,_:=regexp.Match(`^v\d\.\d{2}.{10}0?\d+`,tmp);!valid&&!isSplit{
|
||||||
resetUI()
|
resetUI()
|
||||||
_status = "This doesn't seem to be a Picocrypt volume."
|
_status = "This doesn't seem to be a Picocrypt volume."
|
||||||
_status_color = color.RGBA{0xff,0x00,0x00,255}
|
_status_color = color.RGBA{0xff,0x00,0x00,255}
|
||||||
|
@ -1633,6 +1673,7 @@ func generateChecksums(file string){
|
||||||
|
|
||||||
// Recursively shred all file(s) and folder(s) passed in as 'names'
|
// Recursively shred all file(s) and folder(s) passed in as 'names'
|
||||||
func shred(names []string,separate bool){
|
func shred(names []string,separate bool){
|
||||||
|
stopShredding = false
|
||||||
shredTotal = 0
|
shredTotal = 0
|
||||||
shredDone = 0
|
shredDone = 0
|
||||||
|
|
||||||
|
@ -1669,6 +1710,9 @@ func shred(names []string,separate bool){
|
||||||
if err!=nil{
|
if err!=nil{
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if stopShredding{
|
||||||
|
return nil
|
||||||
|
}
|
||||||
stat,_ := os.Stat(path)
|
stat,_ := os.Stat(path)
|
||||||
if !stat.IsDir(){
|
if !stat.IsDir(){
|
||||||
if len(coming)==128{
|
if len(coming)==128{
|
||||||
|
@ -1678,15 +1722,15 @@ func shred(names []string,separate bool){
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(wg *sync.WaitGroup,id int,j string){
|
go func(wg *sync.WaitGroup,id int,j string){
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
shredding = j
|
||||||
cmd := exec.Command("")
|
cmd := exec.Command("")
|
||||||
if runtime.GOOS=="linux"{
|
if runtime.GOOS=="linux"{
|
||||||
cmd = exec.Command("shred","-ufvz","-n","3",j)
|
cmd = exec.Command("shred","-ufvz","-n",shredPasses,j)
|
||||||
}else{
|
}else{
|
||||||
cmd = exec.Command("rm","-rfP",j)
|
cmd = exec.Command("rm","-rfP",j)
|
||||||
}
|
}
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
shredding = j
|
|
||||||
shredDone++
|
shredDone++
|
||||||
shredUpdate(separate)
|
shredUpdate(separate)
|
||||||
giu.Update()
|
giu.Update()
|
||||||
|
@ -1701,32 +1745,37 @@ func shred(names []string,separate bool){
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
for _,i := range coming{
|
for _,i := range coming{
|
||||||
|
if stopShredding{
|
||||||
|
break
|
||||||
|
}
|
||||||
go func(){
|
go func(){
|
||||||
|
shredding = i
|
||||||
cmd := exec.Command("")
|
cmd := exec.Command("")
|
||||||
if runtime.GOOS=="linux"{
|
if runtime.GOOS=="linux"{
|
||||||
cmd = exec.Command("shred","-ufvz","-n","3",i)
|
cmd = exec.Command("shred","-ufvz","-n",shredPasses,i)
|
||||||
}else{
|
}else{
|
||||||
cmd = exec.Command("rm","-rfP",i)
|
cmd = exec.Command("rm","-rfP",i)
|
||||||
}
|
}
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
shredding = i
|
|
||||||
shredDone++
|
shredDone++
|
||||||
shredUpdate(separate)
|
shredUpdate(separate)
|
||||||
giu.Update()
|
giu.Update()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
os.RemoveAll(name)
|
if !stopShredding{
|
||||||
|
os.RemoveAll(name)
|
||||||
|
}
|
||||||
}else{ // The path is a file, not a directory, so just shred it
|
}else{ // The path is a file, not a directory, so just shred it
|
||||||
|
shredding = name
|
||||||
cmd := exec.Command("")
|
cmd := exec.Command("")
|
||||||
if runtime.GOOS=="linux"{
|
if runtime.GOOS=="linux"{
|
||||||
cmd = exec.Command("shred","-ufvz","-n","3",name)
|
cmd = exec.Command("shred","-ufvz","-n",shredPasses,name)
|
||||||
}else{
|
}else{
|
||||||
cmd = exec.Command("rm","-rfP",name)
|
cmd = exec.Command("rm","-rfP",name)
|
||||||
}
|
}
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
shredding = name+"/*"
|
|
||||||
shredDone++
|
shredDone++
|
||||||
shredUpdate(separate)
|
shredUpdate(separate)
|
||||||
}
|
}
|
||||||
|
@ -1740,6 +1789,10 @@ func shred(names []string,separate bool){
|
||||||
}
|
}
|
||||||
stat,_ := os.Stat(path)
|
stat,_ := os.Stat(path)
|
||||||
if stat.IsDir(){
|
if stat.IsDir(){
|
||||||
|
if stopShredding{
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
t := 0
|
t := 0
|
||||||
files,_ := ioutil.ReadDir(path)
|
files,_ := ioutil.ReadDir(path)
|
||||||
for _,f := range files{
|
for _,f := range files{
|
||||||
|
@ -1749,18 +1802,23 @@ func shred(names []string,separate bool){
|
||||||
}
|
}
|
||||||
shredDone += float32(t)
|
shredDone += float32(t)
|
||||||
shredUpdate(separate)
|
shredUpdate(separate)
|
||||||
cmd := exec.Command(sdelete64path,"*","-p","4")
|
shredding = strings.ReplaceAll(path,"\\","/")+"/*"
|
||||||
|
cmd := exec.Command(sdelete64path,"*","-p",shredPasses)
|
||||||
cmd.Dir = path
|
cmd.Dir = path
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
shredding = strings.ReplaceAll(path,"\\","/")+"/*"
|
giu.Update()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
// sdelete64 doesn't delete the empty folder, so I'll do it manually
|
|
||||||
os.RemoveAll(name)
|
if !stopShredding{
|
||||||
|
// sdelete64 doesn't delete the empty folder, so I'll do it manually
|
||||||
|
os.RemoveAll(name)
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
cmd := exec.Command(sdelete64path,name,"-p","4")
|
shredding = name
|
||||||
|
cmd := exec.Command(sdelete64path,name,"-p",shredPasses)
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow:true}
|
||||||
cmd.Run()
|
cmd.Run()
|
||||||
shredDone++
|
shredDone++
|
||||||
|
@ -1768,6 +1826,9 @@ func shred(names []string,separate bool){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
giu.Update()
|
giu.Update()
|
||||||
|
if stopShredding{
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear UI state
|
// Clear UI state
|
||||||
|
@ -1866,6 +1927,17 @@ func humanize(seconds int) string{
|
||||||
return fmt.Sprintf("%02d:%02d:%02d",hours,minutes,seconds)
|
return fmt.Sprintf("%02d:%02d:%02d",hours,minutes,seconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate cryptographically secure high-entropy passwords
|
||||||
|
func genPassword() string{
|
||||||
|
chars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=!@#$^&()_+?"
|
||||||
|
tmp := make([]byte,32)
|
||||||
|
for i:=0;i<32;i++{
|
||||||
|
j,_ := rand.Int(rand.Reader,new(big.Int).SetUint64(uint64(len(chars))))
|
||||||
|
tmp[i] = chars[j.Int64()]
|
||||||
|
}
|
||||||
|
return string(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
func main(){
|
func main(){
|
||||||
// Create a temporary file to store sdelete64.exe
|
// Create a temporary file to store sdelete64.exe
|
||||||
sdelete64,_ := os.CreateTemp("","sdelete64.*.exe")
|
sdelete64,_ := os.CreateTemp("","sdelete64.*.exe")
|
||||||
|
|
Loading…
Reference in New Issue