mirror of
https://github.com/HACKERALERT/Picocrypt.git
synced 2025-01-01 12:22:25 +00:00
Update Picocrypt.go
This commit is contained in:
parent
3ab5c42e52
commit
ccb473703c
1 changed files with 303 additions and 38 deletions
|
@ -12,18 +12,23 @@ https://github.com/HACKERALERT/Picocrypt
|
|||
*/
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
"strings"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"image/color"
|
||||
g "github.com/AllenDang/giu"
|
||||
ig "github.com/AllenDang/imgui-go"
|
||||
di "github.com/sqweek/dialog"
|
||||
"crypto/rand"
|
||||
"path/filepath"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"golang.org/x/crypto/argon2"
|
||||
"golang.org/x/crypto/blake2b"
|
||||
g "github.com/AllenDang/giu"
|
||||
di "github.com/sqweek/dialog"
|
||||
ig "github.com/AllenDang/imgui-go"
|
||||
"github.com/klauspost/reedsolomon"
|
||||
_ "golang.org/x/crypto/argon2"
|
||||
_ "github.com/HACKERALERT/Monocypher-Go/monocypher"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
)
|
||||
|
||||
// Global variables
|
||||
|
@ -41,7 +46,9 @@ var inputLabel = "Drag and drop file(s) and folder(s) into this window."
|
|||
var outputEntry string
|
||||
var outputWidth float32 = 376
|
||||
var orLabel = "or"
|
||||
var progress float32 = 0
|
||||
var progressInfo = ""
|
||||
var status = "Ready."
|
||||
|
||||
// User input variables
|
||||
var password string
|
||||
|
@ -52,9 +59,12 @@ var erase bool
|
|||
var reedsolo bool
|
||||
|
||||
// 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)
|
||||
|
||||
// Create the user interface
|
||||
func startUI(){
|
||||
|
@ -128,11 +138,11 @@ func startUI(){
|
|||
),
|
||||
|
||||
// Progress bar
|
||||
g.ProgressBar(0).Size(-1,0).Overlay(progressInfo),
|
||||
g.ProgressBar(progress).Size(-1,0).Overlay(progressInfo),
|
||||
|
||||
// Status label
|
||||
g.Dummy(10,0),
|
||||
g.Label("Ready."),
|
||||
g.Label(status),
|
||||
|
||||
// Credits and version
|
||||
g.Line(
|
||||
|
@ -162,6 +172,9 @@ func onDrop(names []string){
|
|||
onlyFolders = nil
|
||||
allFiles = nil
|
||||
files,folders := 0,0
|
||||
|
||||
// Reset UI
|
||||
resetUI()
|
||||
|
||||
// Hide the ".pcv" label
|
||||
orLabel = "or"
|
||||
|
@ -190,6 +203,22 @@ func onDrop(names []string){
|
|||
mode = "decrypt"
|
||||
inputLabel = name+" (will decrypt)"
|
||||
outputEntry = names[0][:len(names[0])-4]
|
||||
|
||||
// Open input file in read-only mode
|
||||
fin,_ := os.Open(names[0])
|
||||
defer fin.Close()
|
||||
|
||||
// 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)
|
||||
|
||||
}else{
|
||||
mode = "encrypt"
|
||||
inputLabel = name+" (will encrypt)"
|
||||
|
@ -205,6 +234,8 @@ func onDrop(names []string){
|
|||
|
||||
// Set the file as 'outputEntry'
|
||||
outputEntry = names[0]
|
||||
|
||||
inputFile = names[0]
|
||||
}
|
||||
}else{
|
||||
// There are multiple dropped items, check each one
|
||||
|
@ -267,6 +298,16 @@ func work(){
|
|||
//headerBroken := false
|
||||
//reedsoloFixed := 0
|
||||
//reedsoloErrors := 0
|
||||
|
||||
// Declare salt and nonce
|
||||
var salt []byte
|
||||
var nonce []byte
|
||||
var keyHash []byte
|
||||
var crcHash []byte
|
||||
var nonces []byte
|
||||
|
||||
stat,_ := os.Stat(inputFile)
|
||||
total := stat.Size()
|
||||
|
||||
// Set the output file based on mode
|
||||
if mode=="encrypt"{
|
||||
|
@ -274,62 +315,262 @@ func work(){
|
|||
}else{
|
||||
outputFile = outputEntry
|
||||
}
|
||||
|
||||
// Open input file in read-only mode
|
||||
fin,_ := os.Open(inputFile)
|
||||
defer fin.Close()
|
||||
|
||||
var fout *os.File
|
||||
|
||||
// If encrypting, generate values. If decrypting, read values from file
|
||||
if mode=="encrypt"{
|
||||
fout,_ := os.OpenFile(
|
||||
status = "Generating values..."
|
||||
g.Update()
|
||||
fout,_ = os.OpenFile(
|
||||
outputFile,
|
||||
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||
0666,
|
||||
os.O_RDWR|os.O_CREATE|os.O_TRUNC,
|
||||
0755,
|
||||
)
|
||||
defer fout.Close()
|
||||
|
||||
// Argon2 salt and XChaCha20 nonce
|
||||
salt := make([]byte,16)
|
||||
nonce := make([]byte,24)
|
||||
salt = make([]byte,16)
|
||||
nonce = make([]byte,24)
|
||||
|
||||
// Write version to file
|
||||
fout.Write(rsEncode([]byte("v1.13"),rs5_128,133))
|
||||
|
||||
// Encode the length of the metadata with Reed-Solomon
|
||||
metadataLength := []byte(fmt.Sprintf("%010d",len(metadata)))
|
||||
/*shards,_ := rs10_128.Split(metadataLength)
|
||||
rs10_128.Encode(shards)
|
||||
tmp := make([]byte,138)
|
||||
for i,shard := range(shards){
|
||||
tmp[i] = shard[0]
|
||||
}
|
||||
|
||||
fout.Write(tmp)*/
|
||||
metadataLength = rsEncode(metadataLength,rs10_128,138)
|
||||
// Write the length of the metadata to file
|
||||
fout.Write(metadataLength)
|
||||
|
||||
// Write the actual metadata
|
||||
fout.Write([]byte(metadata))
|
||||
|
||||
// Fill salt and nonce with Go's CSPRNG
|
||||
rand.Read(salt)
|
||||
rand.Read(nonce)
|
||||
|
||||
//fmt.Println("Encrypting salt: ",salt)
|
||||
//fmt.Println("Encrypting nonce: ",nonce)
|
||||
|
||||
// Encode salt with Reed-Solomon and write to file
|
||||
/*shards,_ = rs16_128.Split(salt)
|
||||
rs16_128.Encode(shards)
|
||||
tmp = make([]byte,144)
|
||||
for i,shard := range(shards){
|
||||
tmp[i] = shard[0]
|
||||
}
|
||||
fout.Write(tmp)*/
|
||||
salt = rsEncode(salt,rs16_128,144)
|
||||
fout.Write(salt)
|
||||
|
||||
// Encode nonce with Reed-Solomon and write to file
|
||||
/*shards,_ = rs24_128.Split(nonce)
|
||||
rs24_128.Encode(shards)
|
||||
tmp = make([]byte,152)
|
||||
for i,shard := range(shards){
|
||||
tmp[i] = shard[0]
|
||||
}
|
||||
fout.Write(tmp)*/
|
||||
nonce = rsEncode(nonce,rs24_128,152)
|
||||
fout.Write(nonce)
|
||||
tmp := rsEncode(nonce,rs24_128,152)
|
||||
fout.Write(tmp)
|
||||
|
||||
// Write placeholder for hash of key
|
||||
fout.Write(make([]byte,192))
|
||||
|
||||
// Write placeholder for Blake2 CRC
|
||||
fout.Write(make([]byte,160))
|
||||
|
||||
|
||||
pairs := int(math.Ceil(float64(total)/1048576))
|
||||
|
||||
offset := 152*pairs+144
|
||||
|
||||
// Write placeholder for nonce/Poly1305 pairs
|
||||
fout.Write(make([]byte,offset))
|
||||
}else{
|
||||
g.Update()
|
||||
status = "Reading values..."
|
||||
version := make([]byte,133)
|
||||
fin.Read(version)
|
||||
version = rsDecode(version,rs5_128,5)
|
||||
|
||||
tmp := make([]byte,138)
|
||||
fin.Read(tmp)
|
||||
tmp = rsDecode(tmp,rs10_128,10)
|
||||
metadataLength,_ := strconv.Atoi(string(tmp))
|
||||
|
||||
fin.Read(make([]byte,metadataLength))
|
||||
|
||||
salt = make([]byte,144)
|
||||
fin.Read(salt)
|
||||
salt = rsDecode(salt,rs16_128,16)
|
||||
|
||||
nonce = make([]byte,152)
|
||||
fin.Read(nonce)
|
||||
nonce = rsDecode(nonce,rs24_128,24)
|
||||
|
||||
//fmt.Println("Decrypting salt: ",salt)
|
||||
//fmt.Println("Decrypting nonce: ",nonce)
|
||||
|
||||
keyHash = make([]byte,192)
|
||||
fin.Read(keyHash)
|
||||
keyHash = rsDecode(keyHash,rs64_128,64)
|
||||
|
||||
crcHash = make([]byte,160)
|
||||
fin.Read(crcHash)
|
||||
crcHash = rsDecode(crcHash,rs32_128,32)
|
||||
|
||||
_tmp := math.Ceil(float64(total-int64(metadataLength+919))/float64(1048744))
|
||||
nonces = make([]byte,int(_tmp*152)+144)
|
||||
fin.Read(nonces)
|
||||
|
||||
//fmt.Println("Nonces: ",nonces)
|
||||
}
|
||||
|
||||
g.Update()
|
||||
status = "Deriving key..."
|
||||
|
||||
// Derive encryption/decryption key
|
||||
key := argon2.IDKey(
|
||||
[]byte(password),
|
||||
salt,
|
||||
4,
|
||||
1048576/2,
|
||||
4,
|
||||
32,
|
||||
)[:]
|
||||
|
||||
key = make([]byte,32)
|
||||
|
||||
sha3_512 := sha3.New512()
|
||||
sha3_512.Write(key)
|
||||
keyHash = sha3_512.Sum(nil)
|
||||
//fmt.Println("keyHash: ",keyHash)
|
||||
|
||||
// Check is password is correct
|
||||
|
||||
if mode=="decrypt"{
|
||||
fout,_ = os.OpenFile(
|
||||
outputFile,
|
||||
os.O_RDWR|os.O_CREATE|os.O_TRUNC,
|
||||
0755,
|
||||
)
|
||||
defer fout.Close()
|
||||
}
|
||||
|
||||
crc,_ := blake2b.New256(nil)
|
||||
|
||||
done := 0
|
||||
counter := 0
|
||||
startTime := time.Now()
|
||||
|
||||
cipher,_ := chacha20poly1305.NewX(key)
|
||||
|
||||
if mode=="decrypt"{
|
||||
_mac := nonces[len(nonces)-144:]
|
||||
_mac = rsDecode(_mac,rs16_128,16)
|
||||
//fmt.Println("_mac len: ",len(_mac))
|
||||
nonces = nonces[:len(nonces)-144]
|
||||
var tmp []byte
|
||||
var chunk []byte
|
||||
for i,j := range(nonces){
|
||||
chunk = append(chunk,j)
|
||||
if (i+1)%152==0{
|
||||
chunk = rsDecode(chunk,rs24_128,24)
|
||||
for _,k := range(chunk){
|
||||
tmp = append(tmp,k)
|
||||
}
|
||||
chunk = nil
|
||||
}
|
||||
}
|
||||
for _,j := range(_mac){
|
||||
tmp = append(tmp,j)
|
||||
}
|
||||
//fmt.Println("ENCRYPTED NONCES: ",tmp)
|
||||
// XXXXXXXXXXXXXXXXFSFSDFFFSFF
|
||||
nonces,_ = cipher.Open(nil,nonce,tmp,nil)
|
||||
//fmt.Println("UNENCRYPTED NONCES: ",nonces)
|
||||
}
|
||||
for{
|
||||
//fmt.Println("Encrypt/decrypt loop")
|
||||
var _data []byte
|
||||
var data []byte
|
||||
var _nonce []byte
|
||||
if mode=="encrypt"{
|
||||
_data = make([]byte,1048576)
|
||||
}else{
|
||||
_data = make([]byte,1048592)
|
||||
}
|
||||
|
||||
size,err := fin.Read(_data)
|
||||
if err!=nil{
|
||||
break
|
||||
}
|
||||
data = _data[:size]
|
||||
|
||||
|
||||
if mode=="encrypt"{
|
||||
_nonce = make([]byte,24)
|
||||
rand.Read(_nonce)
|
||||
for _,i := range(_nonce){
|
||||
nonces = append(nonces,i)
|
||||
}
|
||||
}else{
|
||||
_nonce = nonces[counter*24:counter*24+24]
|
||||
}
|
||||
|
||||
//fmt.Println("Data nonce: ",_nonce)
|
||||
//fmt.Println("Data: ",data)
|
||||
if mode=="encrypt"{
|
||||
data = cipher.Seal(nil,_nonce,data,nil)
|
||||
crc.Write(data)
|
||||
fout.Write(data)
|
||||
}else{
|
||||
//fmt.Println("DECODE LOOP")
|
||||
crc.Write(data)
|
||||
data,_ := cipher.Open(nil,_nonce,data,nil)
|
||||
fout.Write(data)
|
||||
//fmt.Println(authentic)
|
||||
//fmt.Println("DECRYPTED DATA: ",data)
|
||||
}
|
||||
|
||||
done += 1048576
|
||||
counter++
|
||||
progress = float32(done)/float32(total)
|
||||
|
||||
elapsed:= float64(int64(time.Now().Sub(startTime)))/float64(1000000000)
|
||||
|
||||
speed := (float64(done)/elapsed)/1000000
|
||||
eta := float64(total-int64(done))/(speed*1000000)
|
||||
|
||||
progressInfo = fmt.Sprintf("%.2f%%",progress*100)
|
||||
|
||||
status = fmt.Sprintf("Working at %.2f MB/s (ETA: %.1fs)",speed,eta)
|
||||
|
||||
g.Update()
|
||||
data = nil
|
||||
}
|
||||
|
||||
if mode=="encrypt"{
|
||||
//fmt.Println("'nonces' before RS: ",nonces)
|
||||
fout.Seek(int64(567+len(metadata)),0)
|
||||
fout.Write(rsEncode(keyHash,rs64_128,192))
|
||||
fout.Write(rsEncode(crc.Sum(nil),rs32_128,160))
|
||||
//fmt.Println("UNENCRYPTED NONCES: ",nonces)
|
||||
tmp := cipher.Seal(nil,nonce,nonces,nil)
|
||||
//fmt.Println("ENCRYPTED NONCES: ",tmp)
|
||||
_mac := tmp[len(tmp)-16:]
|
||||
//fmt.Println("_mac len: ",len(_mac))
|
||||
tmp = tmp[:len(tmp)-16]
|
||||
var chunk []byte
|
||||
//fmt.Println("<Nonces>")
|
||||
for i,j := range(tmp){
|
||||
chunk = append(chunk,j)
|
||||
if (i+1)%24==0{
|
||||
fout.Write(rsEncode(chunk,rs24_128,152))
|
||||
//fmt.Println(rsEncode(chunk,rs24_128,152))
|
||||
chunk = nil
|
||||
}
|
||||
}
|
||||
fout.Write(rsEncode(_mac,rs16_128,144))
|
||||
//fmt.Println("</Nonces>")
|
||||
}else{
|
||||
fmt.Println("crcHash: ",crcHash)
|
||||
fmt.Println("crc.Sum: ",crc.Sum(nil))
|
||||
}
|
||||
fmt.Println("==============================")
|
||||
resetUI()
|
||||
status = "Completed."
|
||||
}
|
||||
|
||||
// Reset the UI to a clean state with no nothing selected
|
||||
|
@ -338,6 +579,14 @@ func resetUI(){
|
|||
outputEntry = ""
|
||||
orLabel = "or"
|
||||
outputWidth = 376
|
||||
password = ""
|
||||
cPassword = ""
|
||||
metadata = ""
|
||||
keep = false
|
||||
erase = false
|
||||
reedsolo = false
|
||||
progress = 0
|
||||
progressInfo = ""
|
||||
g.Update()
|
||||
}
|
||||
|
||||
|
@ -351,6 +600,22 @@ func rsEncode(data []byte,encoder reedsolomon.Encoder,size int) []byte{
|
|||
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(){
|
||||
window := g.NewMasterWindow("Picocrypt",480,470,g.MasterWindowFlagsNotResizable,nil)
|
||||
|
|
Loading…
Reference in a new issue