From fffb29e2cd705e04ea43a9e8ad3ce45dba2afcf5 Mon Sep 17 00:00:00 2001 From: Evan Su <48808396+HACKERALERT@users.noreply.github.com> Date: Sat, 29 May 2021 15:23:22 -0400 Subject: [PATCH] Create Picocrypt.go --- src/Picocrypt.go | 1647 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1647 insertions(+) create mode 100644 src/Picocrypt.go diff --git a/src/Picocrypt.go b/src/Picocrypt.go new file mode 100644 index 0000000..2db00f6 --- /dev/null +++ b/src/Picocrypt.go @@ -0,0 +1,1647 @@ +package main + +/* + +Picocrypt v1.13 +Copyright (c) Evan Su (https://evansu.cc) +Released under a GNU GPL v3 License +https://github.com/HACKERALERT/Picocrypt + +~ In cryptography we trust ~ + +*/ + +import ( + "io" + "os" + "fmt" + "math" + "time" + "sync" + "os/exec" + "strings" + "strconv" + "runtime" + "net/http" + "io/ioutil" + "image/color" + "crypto/md5" + "archive/zip" + "crypto/rand" + "crypto/sha1" + "encoding/hex" + "path/filepath" + "crypto/sha256" + "runtime/debug" + "github.com/pkg/browser" + "github.com/zeebo/blake3" + "golang.org/x/crypto/sha3" + "golang.org/x/crypto/argon2" + g "github.com/AllenDang/giu" + "golang.org/x/crypto/blake2b" + "golang.org/x/crypto/blake2s" + "github.com/atotto/clipboard" + di "github.com/OpenDiablo2/dialog" + "github.com/klauspost/reedsolomon" + ig "github.com/AllenDang/imgui-go" + "golang.org/x/crypto/chacha20poly1305" + "github.com/HACKERALERT/Picocypher/monocypher" +) + +var version = "v1.13" +var exe,_ = os.Executable() +var rootDir = filepath.Dir(exe) + +// Global variables +var dpi float32 +var mode string +var working = false +var onlyFiles []string +var onlyFolders []string +var allFiles []string +var inputFile string +var outputFile string + +// UI-related global variables +var tab = 0 +var inputLabel = "Drag and drop file(s) and folder(s) into this window." +var outputEntry string +var outputWidth float32 = 376 +var orLabel = "or" +var passwordState = g.InputTextFlags_Password +var showPassword = false +var keyfile = false +var keyfilePrompt = "Keyfile (optional):" +var progress float32 = 0 +var progressInfo = "" +var status = "Ready." +var _status = "Ready." +var _status_color = color.RGBA{0xff,0xff,0xff,255} +var splitUnits = []string{ + "KB", + "MB", + "GB", +} +var splitSelected int32 +var items = []string{ + "Normal (4 passes)", + "Paranoid (Still in development, don't use)", +} +var itemSelected int32 +var shredProgress float32 +var shredDone float32 +var shredTotal float32 +var shredOverlay string +var shredding = "Ready." + +var recombine bool + + +// User input variables +var password string +var cPassword string +var keyfilePath string +var keyfileLabel = "Use a keyfile" +var metadata string +var keep bool +var erase bool +var reedsolo bool +var split bool +var splitSize string +var fast bool +var _fast bool + +var kept = false + +// Reed-Solomon encoders +var rs5_128,_ = reedsolomon.New(5,128) +var rs10_128,_ = reedsolomon.New(10,128) +var rs16_128,_ = reedsolomon.New(16,128) +var rs24_128,_ = reedsolomon.New(24,128) +var rs32_128,_ = reedsolomon.New(32,128) +var rs64_128,_ = reedsolomon.New(64,128) + +// File checksum generator variables +var cs_md5 string +var cs_sha1 string +var cs_sha256 string +var cs_sha3_256 string +var cs_blake2b string +var cs_blake2s string +var cs_blake3 string +var cs_validate string +var md5_color = color.RGBA{0x10,0x10,0x10,255} +var sha1_color = color.RGBA{0x10,0x10,0x10,255} +var sha256_color = color.RGBA{0x10,0x10,0x10,255} +var sha3_256_color = color.RGBA{0x10,0x10,0x10,255} +var blake2b_color = color.RGBA{0x10,0x10,0x10,255} +var blake2s_color = color.RGBA{0x10,0x10,0x10,255} +var blake3_color = color.RGBA{0x10,0x10,0x10,255} +var cs_progress float32 = 0 +var md5_selected = false +var sha1_selected = false +var sha256_selected = false +var sha3_256_selected = false +var blake2b_selected = false +var blake2s_selected = false +var blake3_selected = false + +// Create the user interface +func startUI(){ + g.SingleWindow("Picocrypt").Layout( + g.Style().SetColor(ig.StyleColorBorder,color.RGBA{0x10,0x10,0x10,255}).To( + // The tab bar, which contains different tabs for different features + g.TabBar("TabBar").Layout( + // File encryption/decryption tab + g.TabItem("Encryption/decryption").Layout( + // Update 'tab' to indicate active tab + g.Custom(func(){ + if g.IsItemActive(){ + tab = 0 + } + }), + + // Confirm overwrite with a modal + g.PopupModal("Confirmation").Layout( + g.Label("Output already exists. Overwrite?"), + g.Row( + g.Button("No").Size(110,0).OnClick(func(){ + g.CloseCurrentPopup() + }), + g.Dummy(-118,0), + g.Button("Yes").Size(110,0).OnClick(func(){ + g.CloseCurrentPopup() + go work() + }), + + ), + ), + + // Label listing the input files and a button to clear input files + //g.Dummy(0,10), + g.Row( + g.Label(inputLabel), + g.Dummy(-55,0), + g.Button("Clear").Size(46,0).OnClick(resetUI), + ), + + // Allow user to choose a custom output path and name + //g.Dummy(10,0), + g.Label("Save output as:"), + g.Row( + g.InputText("##output",&outputEntry).Size(outputWidth/dpi), + g.Label(orLabel), + g.Button("Save as").OnClick(func(){ + file,_ := di.File().Title("Save as").Save() + + // Return if user canceled the file dialog + if file==""{ + return + } + + // Remove the extra ".pcv" extension if needed + if strings.HasSuffix(file,".pcv"){ + file = file[:len(file)-4] + } + outputEntry = file + }), + ), + + // Prompt for password + //g.Dummy(10,0), + g.Row( + g.Label("Password:"), + g.Dummy(-220,0), + g.Label(keyfilePrompt), + ), + g.Row( + g.InputText("##password",&password).Size(200/dpi).Flags(passwordState), + g.Checkbox("##showPassword",&showPassword).OnChange(func(){ + if passwordState==g.InputTextFlags_Password{ + passwordState = g.InputTextFlags_None + }else{ + passwordState = g.InputTextFlags_Password + } + g.Update() + }), + g.Dummy(-220,0), + g.Checkbox(keyfileLabel,&keyfile).OnChange(func(){ + if !keyfile{ + keyfileLabel = "Use a keyfile" + return + } + filename,err := di.File().Load() + if err!=nil{ + keyfile = false + return + } + keyfileLabel = filename + keyfilePath = filename + }), + ), + + // Prompt to confirm password + //g.Dummy(10,0), + g.Label("Confirm password:"), + g.InputText("##cPassword",&cPassword).Size(200/dpi).Flags(passwordState), + + // Optional metadata + //g.Dummy(10,0), + g.Label("Metadata (optional):"), + g.InputTextMultiline("##metadata",&metadata).Size(230,126), + + // Advanced options can be enabled with checkboxes + //g.Dummy(10,0), + g.Checkbox("Keep decrypted output even if it's corrupted or modified",&keep), + g.Checkbox("Securely shred the original file(s) and folder(s)",&erase), + g.Row( + g.Checkbox("(Not ready) Encode with Reed-Solomon to prevent corruption",&reedsolo), + g.Button("?").OnClick(func(){ + browser.OpenURL("https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction") + }), + ), + g.Row( + g.Checkbox("Split output into chunks of",&split), + g.InputText("##splitSize",&splitSize).Size(30).Flags(g.InputTextFlags_CharsDecimal), + g.Combo("##splitter",splitUnits[splitSelected],splitUnits,&splitSelected).Size(40), + //g.Label("MB"), + ), + g.Checkbox("Fast mode (less secure, not as durable)",&fast), + + // Start and cancel buttons + //g.Dummy(10,0), + g.Button("Start").Size(-1,20).OnClick(func(){ + if password!=cPassword{ + _status = "Passwords don't match." + _status_color = color.RGBA{0xff,0x00,0x00,255} + return + } + if mode=="encrypt"{ + outputFile = outputEntry+".pcv" + }else{ + outputFile = outputEntry + } + _,err := os.Stat(outputFile) + if err==nil{ + g.OpenPopup("Confirmation") + }else{ + go work() + } + }), + + //g.Dummy(10,0), + g.Style().SetColor(ig.StyleColorText,_status_color).To( + g.Label(_status), + ), + ), + + // File shredder tab + g.TabItem("Shredder").Layout( + // Update 'tab' to indicate active tab + g.Custom(func(){ + if g.IsItemActive(){ + tab = 1 + } + }), + + g.Label("Select a mode below and drop file(s) and folder(s) here."), + g.Label("Warning: Anything dropped here will be shredded immediately!"), + //g.Dummy(10,0), + g.Combo("##shredder_mode",items[itemSelected],items,&itemSelected).Size(463), + //g.Dummy(10,0), + g.ProgressBar(shredProgress).Overlay(shredOverlay).Size(-1,0), + g.Label(shredding).Wrapped(true), + ), + + // File checksum generator tab + g.TabItem("Checksum").Layout( + // Update 'tab' to indicate active tab + g.Custom(func(){ + if g.IsItemActive(){ + tab = 2 + } + }), + + g.Label("Toggle the hashes you would like to generate and drop a file here."), + + // MD5 + //g.Dummy(10,0), + g.Row( + g.Checkbox("MD5:",&md5_selected), + g.Dummy(-45,0), + g.Button("Copy##md5").Size(36,0).OnClick(func(){ + clipboard.WriteAll(cs_md5) + }), + ), + g.Style().SetColor(ig.StyleColorBorder,md5_color).To( + g.InputText("##cs_md5",&cs_md5).Size(-1).Flags(g.InputTextFlags_ReadOnly), + ), + + // SHA1 + //g.Dummy(10,0), + g.Row( + g.Checkbox("SHA1:",&sha1_selected), + g.Dummy(-45,0), + g.Button("Copy##sha1").Size(36,0).OnClick(func(){ + clipboard.WriteAll(cs_sha1) + }), + ), + g.Style().SetColor(ig.StyleColorBorder,sha1_color).To( + g.InputText("##cs_sha1",&cs_sha1).Size(-1).Flags(g.InputTextFlags_ReadOnly), + ), + + // SHA256 + //g.Dummy(10,0), + g.Row( + g.Checkbox("SHA256:",&sha256_selected), + g.Dummy(-45,0), + g.Button("Copy##sha256").Size(36,0).OnClick(func(){ + clipboard.WriteAll(cs_sha256) + }), + ), + g.Style().SetColor(ig.StyleColorBorder,sha256_color).To( + g.InputText("##cs_sha256",&cs_sha256).Size(-1).Flags(g.InputTextFlags_ReadOnly), + ), + + // SHA3-256 + //g.Dummy(10,0), + g.Row( + g.Checkbox("SHA3-256:",&sha3_256_selected), + g.Dummy(-45,0), + g.Button("Copy##sha3_256").Size(36,0).OnClick(func(){ + clipboard.WriteAll(cs_sha3_256) + }), + ), + g.Style().SetColor(ig.StyleColorBorder,sha3_256_color).To( + g.InputText("##cs_sha3_256",&cs_sha3_256).Size(-1).Flags(g.InputTextFlags_ReadOnly), + ), + + // BLAKE2b + //g.Dummy(10,0), + g.Row( + g.Checkbox("BLAKE2b:",&blake2b_selected), + g.Dummy(-45,0), + g.Button("Copy##blake2b").Size(36,0).OnClick(func(){ + clipboard.WriteAll(cs_blake2b) + }), + ), + g.Style().SetColor(ig.StyleColorBorder,blake2b_color).To( + g.InputText("##cs_blake2b",&cs_blake2b).Size(-1).Flags(g.InputTextFlags_ReadOnly), + ), + + // BLAKE2s + //g.Dummy(10,0), + g.Row( + g.Checkbox("BLAKE2s:",&blake2s_selected), + g.Dummy(-45,0), + g.Button("Copy##blake2s").Size(36,0).OnClick(func(){ + clipboard.WriteAll(cs_blake2s) + }), + ), + g.Style().SetColor(ig.StyleColorBorder,blake2s_color).To( + g.InputText("##cs_blake2s",&cs_blake2s).Size(-1).Flags(g.InputTextFlags_ReadOnly), + ), + + // BLAKE3 + //g.Dummy(10,0), + g.Row( + g.Checkbox("BLAKE3:",&blake3_selected), + g.Dummy(-45,0), + g.Button("Copy##blake3").Size(36,0).OnClick(func(){ + clipboard.WriteAll(cs_blake3) + }), + ), + g.Style().SetColor(ig.StyleColorBorder,blake3_color).To( + g.InputText("##cs_blake3",&cs_blake3).Size(-1).Flags(g.InputTextFlags_ReadOnly), + ), + + // Input box for validating checksum + //g.Dummy(10,0), + g.Label("Validate a checksum:"), + g.InputText("##cs_validate",&cs_validate).Size(-1).OnChange(func(){ + md5_color = color.RGBA{0x10,0x10,0x10,255} + sha1_color = color.RGBA{0x10,0x10,0x10,255} + sha256_color = color.RGBA{0x10,0x10,0x10,255} + sha3_256_color = color.RGBA{0x10,0x10,0x10,255} + blake2b_color = color.RGBA{0x10,0x10,0x10,255} + blake2s_color = color.RGBA{0x10,0x10,0x10,255} + blake3_color = color.RGBA{0x10,0x10,0x10,255} + if cs_validate==""{ + return + } + if cs_validate==cs_md5{ + md5_color = color.RGBA{0x00,0xff,0x00,255} + }else if cs_validate==cs_sha1{ + sha1_color = color.RGBA{0x00,0xff,0x00,255} + }else if cs_validate==cs_sha256{ + sha256_color = color.RGBA{0x00,0xff,0x00,255} + }else if cs_validate==cs_sha3_256{ + sha3_256_color = color.RGBA{0x00,0xff,0x00,255} + }else if cs_validate==cs_blake2b{ + blake2b_color = color.RGBA{0x00,0xff,0x00,255} + }else if cs_validate==cs_blake2s{ + blake2s_color = color.RGBA{0x00,0xff,0x00,255} + }else if cs_validate==cs_blake3{ + blake3_color = color.RGBA{0x00,0xff,0x00,255} + } + g.Update() + }), + + // Progress bar + //g.Dummy(10,0), + g.Label("Progress:"), + g.ProgressBar(cs_progress).Size(-1,0), + ), + g.TabItem("About").Layout( + // Update 'tab' to indicate active tab + g.Custom(func(){ + if g.IsItemActive(){ + tab = 3 + } + }), + //g.Dummy(30,0), + g.Label("Picocrypt "+version+", created by Evan Su (https://evansu.cc)"), + ), + ), + ), + ) + if working{ + g.SingleWindow("Working..").IsOpen(&working).Layout( + //g.Dummy(30,0), + g.Label("Tips:"), + g.Label(" - Choose a strong password with more than 16 characters."), + g.Label(" - Use a unique password that isn't used anywhere else."), + g.Label(" - Trust no one but yourself and never give out your key."), + g.Label(" - For highly sensitive files, encrypt them while offline."), + g.Label(" - An antivirus can be beneficial to prevent keyloggers."), + g.Label(" - Encrypt your root filesystem for maximal security."), + g.Dummy(0,-50), + + + // Progress bar + g.Row( + g.ProgressBar(progress).Size(-54,0).Overlay(progressInfo), + g.Dummy(-59,0), + g.Button("Cancel").Size(50,0).OnClick(func(){ + working = false + }), + ), + //g.Dummy(10,0), + g.Label(status), + ) + } +} + +// Handle files dropped into Picocrypt by user +func onDrop(names []string){ + _status = "" + recombine = false + if tab==0{ + // Clear variables + onlyFiles = nil + onlyFolders = nil + allFiles = nil + files,folders := 0,0 + + // Reset UI + resetUI() + + // Hide the ".pcv" label + orLabel = "or" + outputWidth = 376 + + // There's only one dropped item + if len(names)==1{ + stat,_ := os.Stat(names[0]) + + // Check if dropped item is a file or a folder + if stat.IsDir(){ + folders++ + inputLabel = "1 folder selected." + + // Add the folder + onlyFolders = append(onlyFolders,names[0]) + + // Set 'outputEntry' to 'Encrypted.zip' in the same directory + outputEntry = filepath.Join(filepath.Dir(names[0]),"Encrypted.zip") + + mode = "encrypt" + // Show the ".pcv" file extension + orLabel = ".pcv or" + outputWidth = 341 + }else{ + files++ + name := filepath.Base(names[0]) + + nums := []string{"0","1","2","3","4","5","6","7","8","9"} + endsNum := false + for _,i := range(nums){ + if strings.HasSuffix(names[0],i){ + endsNum = true + } + } + isSplit := strings.Contains(names[0],".pcv.")&&endsNum + + // Decide if encrypting or decrypting + if strings.HasSuffix(names[0],".pcv")||isSplit{ + mode = "decrypt" + inputLabel = name+" (will decrypt)" + + if isSplit{ + ind := strings.Index(names[0],".pcv") + names[0] = names[0][:ind] + outputEntry = names[0] + recombine = true + }else{ + outputEntry = names[0][:len(names[0])-4] + } + + + // Open input file in read-only mode + fin,_ := os.Open(names[0]) + + // Read metadata and insert into box + fin.Read(make([]byte,133)) + tmp := make([]byte,138) + fin.Read(tmp) + tmp = rsDecode(tmp,rs10_128,10) + metadataLength,_ := strconv.Atoi(string(tmp)) + //fmt.Println(metadataLength) + tmp = make([]byte,metadataLength) + fin.Read(tmp) + metadata = string(tmp) + + flags := make([]byte,133) + fin.Read(flags) + flags = rsDecode(flags,rs5_128,5) + + if flags[1]==1{ + keyfilePrompt = "Keyfile (required):" + keyfileLabel = "Click here to select keyfile." + } + + fin.Close() + }else{ + mode = "encrypt" + inputLabel = name+" (will encrypt)" + outputEntry = names[0] + + // Show the ".pcv" file extension + orLabel = ".pcv or" + outputWidth = 341 + } + + // Add the file + onlyFiles = append(onlyFiles,names[0]) + + inputFile = names[0] + } + }else{ + mode = "encrypt" + // Show the ".pcv" file extension + orLabel = ".pcv or" + outputWidth = 341 + + // There are multiple dropped items, check each one + for _,name := range names{ + stat,_ := os.Stat(name) + + // Check if item is a file or a directory + if stat.IsDir(){ + folders++ + onlyFolders = append(onlyFolders,name) + }else{ + files++ + onlyFiles = append(onlyFiles,name) + allFiles = append(allFiles,name) + } + } + + if folders==0{ + // If folders==0, then there are multiple files + inputLabel = fmt.Sprintf("%d files selected.",files) + }else if files==0{ + // If files==0, then there are multiple folders + inputLabel = fmt.Sprintf("%d folders selected.",folders) + }else{ + // There are multiple files and folders + if files==1&&folders>1{ + inputLabel = fmt.Sprintf("1 file and %d folders selected.",folders) + }else if folders==1&&files>1{ + inputLabel = fmt.Sprintf("%d files and 1 folder selected.",files) + }else if folders==1&&files==1{ + inputLabel = "1 file and 1 folder selected." + }else{ + inputLabel = fmt.Sprintf("%d files and %d folders selected.",files,folders) + } + } + + // Set 'outputEntry' to 'Encrypted.zip' in the same directory + outputEntry = filepath.Join(filepath.Dir(names[0]),"Encrypted.zip") + } + + // If there are folders that were dropped, recusively add all files into 'allFiles' + if folders>0{ + for _,name := range(onlyFolders){ + filepath.Walk(name,func(path string,_ os.FileInfo,_ error) error{ + stat,_ := os.Stat(path) + if !stat.IsDir(){ + allFiles = append(allFiles,path) + } + return nil + }) + } + } + }else if tab==1{ + go shred(names,true) + }else if tab==2{ + go generateChecksums(names[0]) + } + + // Update the UI + g.Update() +} + +// Start encryption/decryption +func work(){ + debug.FreeOSMemory() + // Set some variables + working = true + //headerBroken := false + //reedsoloFixed := 0 + //reedsoloErrors := 0 + var salt []byte + var nonce []byte + var keyHash []byte + var _keyHash []byte + var khash []byte + var khash_hash []byte + var _khash_hash []byte + var nonces []byte + _fast = fast + + // Set the output file based on mode + if mode=="encrypt"{ + // Compress files into a zip archive + if len(allFiles)>1||len(onlyFolders)>0{ + rootDir := filepath.Dir(outputEntry) + inputFile = outputEntry + fmt.Println(inputFile) + file,_ := os.Create(inputFile) + + w := zip.NewWriter(file) + for _,path := range(allFiles){ + if path==inputFile{ + continue + } + stat,_ := os.Stat(path) + header,_ := zip.FileInfoHeader(stat) + header.Name = strings.Replace(path,rootDir,"",1) + header.Method = zip.Deflate + writer,_ := w.CreateHeader(header) + file,_ := os.Open(path) + io.Copy(writer,file) + file.Close() + } + w.Flush() + w.Close() + file.Close() + } + } + + if recombine{ + status = "Recombining file..." + total := 0 + + for{ + _,err := os.Stat(fmt.Sprintf("%s.%d",inputFile+".pcv",total)) + if err!=nil{ + break + } + total++ + } + fout,_ := os.OpenFile( + outputEntry+".pcv", + os.O_RDWR|os.O_CREATE|os.O_TRUNC, + 0755, + ) + for i:=0;i=chunkSize{ + break + } + } + fout.Close() + finished++ + splitted = append(splitted,fmt.Sprintf("%s.%d",outputFile,i)) + progress = float32(finished)/float32(chunks) + progressInfo = fmt.Sprintf("%d/%d",finished,chunks) + g.Update() + } + fin.Close() + if erase{ + status = "Shredding the unsplitted file..." + progressInfo = "" + shred([]string{outputFile}[:],false) + }else{ + os.Remove(outputFile) + } + } + + if recombine{ + os.Remove(inputFile) + } + + // Delete the temporary zip file + if len(allFiles)>1{ + if erase{ + progressInfo = "" + status = "Shredding temporary files..." + shred([]string{outputEntry}[:],false) + }else{ + os.Remove(outputEntry) + } + } + fmt.Println("==============================") + if erase{ + progressInfo = "" + shred(onlyFiles,false) + shred(onlyFolders,false) + } + + + + + + resetUI() + if kept{ + _status = "The input is corrupted and/or modified. Please be careful." + _status_color = color.RGBA{0xff,0xff,0x00,255} + }else{ + _status = "Completed." + _status_color = color.RGBA{0x00,0xff,0x00,255} + } + working = false + kept = false + key = nil + status = "Ready." + debug.FreeOSMemory() + fmt.Println("Exit goroutine") +} + +func shred(names []string,separate bool){ + shredTotal = 0 + shredDone = 0 + if separate{ + shredOverlay = "Shredding..." + } + for _,name := range(names){ + filepath.Walk(name,func(path string,_ os.FileInfo,err error) error{ + if err!=nil{ + return nil + } + stat,_ := os.Stat(path) + if !stat.IsDir(){ + shredTotal++ + } + return nil + }) + } + for _,name := range(names){ + shredding = name + if runtime.GOOS=="linux"||runtime.GOOS=="darwin"{ + stat,_ := os.Stat(name) + if stat.IsDir(){ + var coming []string + filepath.Walk(name,func(path string,_ os.FileInfo,err error) error{ + if err!=nil{ + return nil + } + fmt.Println(path) + stat,_ := os.Stat(path) + if !stat.IsDir(){ + if len(coming)==128{ + var wg sync.WaitGroup + for i,j := range(coming){ + wg.Add(1) + go func(wg *sync.WaitGroup,id int,j string){ + defer wg.Done() + cmd := exec.Command("") + if runtime.GOOS=="linux"{ + cmd = exec.Command("shred","-ufvz","-n","3",j) + }else{ + cmd = exec.Command("rm","-rfP",j) + } + output,err := cmd.Output() + fmt.Println(err) + fmt.Println(output) + shredding = j + shredDone++ + shredUpdate(separate) + g.Update() + }(&wg,i,j) + + } + wg.Wait() + coming = nil + }else{ + coming = append(coming,path) + } + } + return nil + }) + fmt.Println(coming) + for _,i := range(coming){ + go func(){ + cmd := exec.Command("") + if runtime.GOOS=="linux"{ + cmd = exec.Command("shred","-ufvz","-n","3",i) + }else{ + cmd = exec.Command("rm","-rfP",i) + } + output,err := cmd.Output() + fmt.Println(err) + fmt.Println(output) + shredding = i + shredDone++ + shredUpdate(separate) + g.Update() + }() + } + os.RemoveAll(name) + }else{ + cmd := exec.Command("") + if runtime.GOOS=="linux"{ + cmd = exec.Command("shred","-ufvz","-n","3",name) + }else{ + cmd = exec.Command("rm","-rfP",name) + } + cmd.Run() + shredding = name+"/*" + shredDone++ + shredUpdate(separate) + } + }else if runtime.GOOS=="windows"{ + stat,_ := os.Stat(name) + if stat.IsDir(){ + filepath.Walk(name,func(path string,_ os.FileInfo,err error) error{ + if err!=nil{ + return nil + } + fmt.Println(path) + stat,_ := os.Stat(path) + if stat.IsDir(){ + t := 0 + files,_ := ioutil.ReadDir(path) + for _,f := range(files){ + if !f.IsDir(){ + t++ + } + } + shredDone += float32(t) + shredUpdate(separate) + tmp := filepath.Join(rootDir,"sdelete64.exe") + cmd := exec.Command(tmp,"*","-p","4") + cmd.Dir = path + cmd.Run() + shredding = strings.ReplaceAll(path,"\\","/")+"/*" + } + return nil + }) + os.RemoveAll(name) + }else{ + o,e := exec.Command(filepath.Join(rootDir,"sdelete64.exe"),name,"-p","4").Output() + fmt.Println(string(o),e) + shredDone++ + shredUpdate(separate) + } + } + fmt.Println(name) + g.Update() + } + /*if itemSelected==1&&runtime.GOOS=="windows"{ + cmd := exec.Command("cipher","/w:\""+name+"\"") + stdout,err := cmd.Output() + if err!=nil{ + fmt.Println(err) + } + fmt.Println(string(stdout)) + }*/ + shredding = "Ready." + shredProgress = 0 + shredOverlay = "" +} + +func shredUpdate(separate bool){ + if separate{ + shredOverlay = fmt.Sprintf("%d/%d",int(shredDone),int(shredTotal)) + shredProgress = shredDone/shredTotal + }else{ + status = fmt.Sprintf("%d/%d",int(shredDone),int(shredTotal)) + progress = shredDone/shredTotal + } + g.Update() +} + +// Generate file checksums +func generateChecksums(file string){ + fin,_ := os.Open(file) + + cs_md5 = "" + cs_sha1 = "" + cs_sha256 = "" + cs_sha3_256 = "" + cs_blake2b = "" + cs_blake2s = "" + cs_blake3 = "" + + if md5_selected{ + cs_md5 = "Calculating..." + } + if sha1_selected{ + cs_sha1 = "Calculating..." + } + if sha256_selected{ + cs_sha256 = "Calculating..." + } + if sha3_256_selected{ + cs_sha3_256 = "Calculating..." + } + if blake2b_selected{ + cs_blake2b = "Calculating..." + } + if blake2s_selected{ + cs_blake2s = "Calculating..." + } + if blake3_selected{ + cs_blake3 = "Calculating..." + } + + crc_md5 := md5.New() + crc_sha1 := sha1.New() + crc_sha256 := sha256.New() + crc_sha3_256 := sha3.New256() + crc_blake2b,_ := blake2b.New256(nil) + crc_blake2s,_ := blake2s.New256(nil) + crc_blake3 := blake3.New() + stat,_ := os.Stat(file) + total := stat.Size() + var done int64 = 0 + for{ + var data []byte + _data := make([]byte,1048576) + size,err := fin.Read(_data) + if err!=nil{ + break + } + data = _data[:size] + + if md5_selected{ + crc_md5.Write(data) + } + if sha1_selected{ + crc_sha1.Write(data) + } + if sha256_selected{ + crc_sha256.Write(data) + } + if sha3_256_selected{ + crc_sha3_256.Write(data) + } + if blake2b_selected{ + crc_blake2b.Write(data) + } + if blake2s_selected{ + crc_blake2s.Write(data) + } + if blake3_selected{ + crc_blake3.Write(data) + } + + done += int64(size) + cs_progress = float32(done)/float32(total) + g.Update() + } + cs_progress = 0 + if md5_selected{ + cs_md5 = hex.EncodeToString(crc_md5.Sum(nil)) + } + if sha1_selected{ + cs_sha1 = hex.EncodeToString(crc_sha1.Sum(nil)) + } + if sha256_selected{ + cs_sha256 = hex.EncodeToString(crc_sha256.Sum(nil)) + } + if sha3_256_selected{ + cs_sha3_256 = hex.EncodeToString(crc_sha3_256.Sum(nil)) + } + if blake2b_selected{ + cs_blake2b = hex.EncodeToString(crc_blake2b.Sum(nil)) + } + if blake2s_selected{ + cs_blake2s = hex.EncodeToString(crc_blake2s.Sum(nil)) + } + if blake3_selected{ + cs_blake3 = hex.EncodeToString(crc_blake3.Sum(nil)) + } + g.Update() +} + + +// Reset the UI to a clean state with no nothing selected +func resetUI(){ + inputLabel = "Drag and drop file(s) and folder(s) into this window." + outputEntry = "" + orLabel = "or" + outputWidth = 376 + password = "" + cPassword = "" + keyfilePrompt = "Keyfile (optional):" + keyfileLabel = "Use a keyfile" + keyfile = false + metadata = "" + keep = false + erase = false + reedsolo = false + split = false + splitSize = "" + fast = false + progress = 0 + progressInfo = "" + _status = "" + _status_color = color.RGBA{0xff,0xff,0xff,255} + g.Update() +} + +func broken(){ + working = false + _status = "The file is either corrupted or intentionally modified." + _status_color = color.RGBA{0xff,0x00,0x00,255} + os.Remove(outputFile) + debug.FreeOSMemory() +} + +func rsEncode(data []byte,encoder reedsolomon.Encoder,size int) []byte{ + shards,_ := encoder.Split(data) + encoder.Encode(shards) + tmp := make([]byte,size) + for i,shard := range(shards){ + tmp[i] = shard[0] + } + return tmp +} + +func rsDecode(data []byte,encoder reedsolomon.Encoder,size int) []byte{ + res := make([][]byte,len(data)) + for i,_ := range(data){ + tmp := make([]byte,1) + tmp[0] = data[i] + res[i] = tmp + } + _ = encoder.Reconstruct(res) + res = res[:size] + tmp := make([]byte,size) + for i,shard := range(res){ + tmp[i] = shard[0] + } + return tmp +} + +// Create the master window, set callbacks, and start the UI +func main(){ + go func(){ + v,err := http.Get("https://raw.githubusercontent.com/HACKERALERT/Picocrypt/main/internals/version.txt") + if err==nil{ + fmt.Println(v) + body,err := io.ReadAll(v.Body) + v.Body.Close() + if err==nil{ + if string(body[:5])!=version{ + _status = "A newer version is available." + _status_color = color.RGBA{0,0xff,0,255} + } + } + } + }() + di.Init() + if runtime.GOOS=="windows"{ + exec.Command(filepath.Join(rootDir,"sdelete64.exe"),"/accepteula") + } + window := g.NewMasterWindow("Picocrypt",480,488,g.MasterWindowFlagsNotResizable,nil) + window.SetDropCallback(onDrop) + dpi = g.Context.GetPlatform().GetContentScale() + window.Run(startUI) +}