handle more errors

This commit is contained in:
Evan Su 2025-04-18 16:48:29 -04:00
parent b0c2943bb0
commit 0cc109bc6b

View file

@ -1978,17 +1978,27 @@ func work() {
var mac hash.Hash var mac hash.Hash
subkey := make([]byte, 32) subkey := make([]byte, 32)
hkdf := hkdf.New(sha3.New256, key, hkdfSalt, nil) hkdf := hkdf.New(sha3.New256, key, hkdfSalt, nil)
hkdf.Read(subkey) if n, err := hkdf.Read(subkey); err != nil || n != 32 {
panic(errors.New("fatal hkdf.Read error"))
}
if paranoid { if paranoid {
mac = hmac.New(sha3.New512, subkey) // HMAC-SHA3 mac = hmac.New(sha3.New512, subkey) // HMAC-SHA3
} else { } else {
mac, _ = blake2b.New512(subkey) // Keyed BLAKE2b mac, err = blake2b.New512(subkey) // Keyed BLAKE2b
if err != nil {
panic(err)
}
} }
// Generate another subkey for use as Serpent's key // Generate another subkey for use as Serpent's key
serpentKey := make([]byte, 32) serpentKey := make([]byte, 32)
hkdf.Read(serpentKey) if n, err := hkdf.Read(serpentKey); err != nil || n != 32 {
s, _ := serpent.NewCipher(serpentKey) panic(errors.New("fatal hkdf.Read error"))
}
s, err := serpent.NewCipher(serpentKey)
if err != nil {
panic(err)
}
serpent := cipher.NewCTR(s, serpentIV) serpent := cipher.NewCTR(s, serpentIV)
// Start the main encryption process // Start the main encryption process
@ -2036,7 +2046,9 @@ func work() {
} }
chacha.XORKeyStream(dst, src) chacha.XORKeyStream(dst, src)
mac.Write(dst) if _, err := mac.Write(dst); err != nil {
panic(err)
}
if reedsolo { if reedsolo {
copy(src, dst) copy(src, dst)
@ -2090,7 +2102,7 @@ func work() {
} else { } else {
// Decode the full chunks // Decode the full chunks
chunks := len(dst)/136 - 1 chunks := len(dst)/136 - 1
for i := 0; i < chunks; i++ { for i := range chunks {
tmp, err := rsDecode(rs128, dst[i*136:(i+1)*136]) tmp, err := rsDecode(rs128, dst[i*136:(i+1)*136])
if err != nil { if err != nil {
if keep { if keep {
@ -2125,7 +2137,9 @@ func work() {
dst = make([]byte, len(src)) dst = make([]byte, len(src))
} }
mac.Write(src) if _, err := mac.Write(src); err != nil {
panic(err)
}
chacha.XORKeyStream(dst, src) chacha.XORKeyStream(dst, src)
if paranoid { if paranoid {
@ -2167,12 +2181,19 @@ func work() {
if counter >= 60*GiB { if counter >= 60*GiB {
// ChaCha20 // ChaCha20
nonce = make([]byte, 24) nonce = make([]byte, 24)
hkdf.Read(nonce) if n, err := hkdf.Read(nonce); err != nil || n != 24 {
chacha, _ = chacha20.NewUnauthenticatedCipher(key, nonce) panic(errors.New("fatal hkdf.Read error"))
}
chacha, err = chacha20.NewUnauthenticatedCipher(key, nonce)
if err != nil {
panic(err)
}
// Serpent // Serpent
serpentIV = make([]byte, 16) serpentIV = make([]byte, 16)
hkdf.Read(serpentIV) if n, err := hkdf.Read(serpentIV); err != nil || n != 16 {
panic(errors.New("fatal hkdf.Read error"))
}
serpent = cipher.NewCTR(s, serpentIV) serpent = cipher.NewCTR(s, serpentIV)
// Reset counter to 0 // Reset counter to 0
@ -2189,10 +2210,18 @@ func work() {
giu.Update() giu.Update()
// Seek back to header and write important values // Seek back to header and write important values
fout.Seek(int64(309+len(comments)*3), 0) if _, err := fout.Seek(int64(309+len(comments)*3), 0); err != nil {
fout.Write(rsEncode(rs64, keyHash)) panic(err)
fout.Write(rsEncode(rs32, keyfileHash)) }
fout.Write(rsEncode(rs64, mac.Sum(nil))) if _, err := fout.Write(rsEncode(rs64, keyHash)); err != nil {
panic(err)
}
if _, err := fout.Write(rsEncode(rs32, keyfileHash)); err != nil {
panic(err)
}
if _, err := fout.Write(rsEncode(rs64, mac.Sum(nil))); err != nil {
panic(err)
}
} else { } else {
popupStatus = "Comparing values..." popupStatus = "Comparing values..."
giu.Update() giu.Update()
@ -2217,10 +2246,16 @@ func work() {
} }
} }
fin.Close() if err := fin.Close(); err != nil {
fout.Close() panic(err)
}
if err := fout.Close(); err != nil {
panic(err)
}
os.Rename(outputFile+".incomplete", outputFile) if err := os.Rename(outputFile+".incomplete", outputFile); err != nil {
panic(err)
}
// Add plausible deniability // Add plausible deniability
if mode == "encrypt" && deniability { if mode == "encrypt" && deniability {
@ -2229,29 +2264,51 @@ func work() {
giu.Update() giu.Update()
// Get size of volume for showing progress // Get size of volume for showing progress
stat, _ := os.Stat(outputFile) stat, err := os.Stat(outputFile)
if err != nil {
panic(err)
}
total := stat.Size() total := stat.Size()
// Rename the output volume to free up the filename // Rename the output volume to free up the filename
os.Rename(outputFile, outputFile+".tmp") os.Rename(outputFile, outputFile+".tmp")
fin, _ := os.Open(outputFile + ".tmp") fin, err := os.Open(outputFile + ".tmp")
fout, _ := os.Create(outputFile + ".incomplete") if err != nil {
panic(err)
}
fout, err := os.Create(outputFile + ".incomplete")
if err != nil {
panic(err)
}
// Use a random Argon2 salt and XChaCha20 nonce // Use a random Argon2 salt and XChaCha20 nonce
salt := make([]byte, 16) salt := make([]byte, 16)
nonce := make([]byte, 24) nonce := make([]byte, 24)
if _, err := rand.Read(salt); err != nil { if n, err := rand.Read(salt); err != nil || n != 16 {
panic(errors.New("fatal crypto/rand error"))
}
if n, err := rand.Read(nonce); err != nil || n != 24 {
panic(errors.New("fatal crypto/rand error"))
}
if bytes.Equal(salt, make([]byte, 16)) || bytes.Equal(nonce, make([]byte, 24)) {
panic(errors.New("fatal crypto/rand error"))
}
if _, err := fout.Write(salt); err != nil {
panic(err) panic(err)
} }
if _, err := rand.Read(nonce); err != nil { if _, err := fout.Write(nonce); err != nil {
panic(err) panic(err)
} }
fout.Write(salt)
fout.Write(nonce)
// Generate key and XChaCha20 // Generate key and XChaCha20
key := argon2.IDKey([]byte(password), salt, 4, 1<<20, 4, 32) key := argon2.IDKey([]byte(password), salt, 4, 1<<20, 4, 32)
chacha, _ := chacha20.NewUnauthenticatedCipher(key, nonce) if bytes.Equal(key, make([]byte, 32)) {
panic(errors.New("fatal crypto/argon2 error"))
}
chacha, err := chacha20.NewUnauthenticatedCipher(key, nonce)
if err != nil {
panic(err)
}
// Encrypt the entire volume // Encrypt the entire volume
done, counter := 0, 0 done, counter := 0, 0
@ -2264,7 +2321,9 @@ func work() {
src = src[:size] src = src[:size]
dst := make([]byte, len(src)) dst := make([]byte, len(src))
chacha.XORKeyStream(dst, src) chacha.XORKeyStream(dst, src)
fout.Write(dst) if _, err := fout.Write(dst); err != nil {
panic(err)
}
// Update stats // Update stats
done += size done += size
@ -2275,17 +2334,30 @@ func work() {
// Change nonce after 60 GiB to prevent overflow // Change nonce after 60 GiB to prevent overflow
if counter >= 60*GiB { if counter >= 60*GiB {
tmp := sha3.New256() tmp := sha3.New256()
tmp.Write(nonce) if _, err := tmp.Write(nonce); err != nil {
panic(err)
}
nonce = tmp.Sum(nil)[:24] nonce = tmp.Sum(nil)[:24]
chacha, _ = chacha20.NewUnauthenticatedCipher(key, nonce) chacha, err = chacha20.NewUnauthenticatedCipher(key, nonce)
if err != nil {
panic(err)
}
counter = 0 counter = 0
} }
} }
fin.Close() if err := fin.Close(); err != nil {
fout.Close() panic(err)
os.Remove(fin.Name()) }
os.Rename(outputFile+".incomplete", outputFile) if err := fout.Close(); err != nil {
panic(err)
}
if err := os.Remove(fin.Name()); err != nil {
panic(err)
}
if err := os.Rename(outputFile+".incomplete", outputFile); err != nil {
panic(err)
}
canCancel = true canCancel = true
giu.Update() giu.Update()
} }
@ -2293,11 +2365,17 @@ func work() {
// Split the file into chunks // Split the file into chunks
if split { if split {
var splitted []string var splitted []string
stat, _ := os.Stat(outputFile) stat, err := os.Stat(outputFile)
if err != nil {
panic(err)
}
size := stat.Size() size := stat.Size()
finishedFiles := 0 finishedFiles := 0
finishedBytes := 0 finishedBytes := 0
chunkSize, _ := strconv.Atoi(splitSize) chunkSize, err := strconv.Atoi(splitSize)
if err != nil {
panic(err)
}
// Calculate chunk size // Calculate chunk size
if splitSelected == 0 { if splitSelected == 0 {
@ -2318,17 +2396,25 @@ func work() {
giu.Update() giu.Update()
// Open the volume for reading // Open the volume for reading
fin, _ := os.Open(outputFile) fin, err := os.Open(outputFile)
if err != nil {
panic(err)
}
// Delete existing chunks to prevent mixed chunks // Delete existing chunks to prevent mixed chunks
names, _ := filepath.Glob(outputFile + ".*") names, err := filepath.Glob(outputFile + ".*")
if err != nil {
panic(err)
}
for _, i := range names { for _, i := range names {
os.Remove(i) if err := os.Remove(i); err != nil {
panic(err)
}
} }
// Start the splitting process // Start the splitting process
startTime := time.Now() startTime := time.Now()
for i := 0; i < chunks; i++ { for i := range chunks {
// Make the chunk // Make the chunk
fout, _ := os.Create(fmt.Sprintf("%s.%d.incomplete", outputFile, i)) fout, _ := os.Create(fmt.Sprintf("%s.%d.incomplete", outputFile, i))
done := 0 done := 0
@ -2382,7 +2468,9 @@ func work() {
popupStatus = fmt.Sprintf("Splitting at %.2f MiB/s (ETA: %s)", speed, eta) popupStatus = fmt.Sprintf("Splitting at %.2f MiB/s (ETA: %s)", speed, eta)
giu.Update() giu.Update()
} }
fout.Close() if err := fout.Close(); err != nil {
panic(err)
}
// Update stats // Update stats
finishedFiles++ finishedFiles++
@ -2394,11 +2482,20 @@ func work() {
giu.Update() giu.Update()
} }
fin.Close() if err := fin.Close(); err != nil {
os.Remove(outputFile) panic(err)
names, _ = filepath.Glob(outputFile + ".*.incomplete") }
if err := os.Remove(outputFile); err != nil {
panic(err)
}
names, err = filepath.Glob(outputFile + ".*.incomplete")
if err != nil {
panic(err)
}
for _, i := range names { for _, i := range names {
os.Rename(i, strings.TrimSuffix(i, ".incomplete")) if err := os.Rename(i, strings.TrimSuffix(i, ".incomplete")); err != nil {
panic(err)
}
} }
} }
@ -2409,9 +2506,13 @@ func work() {
// Delete temporary files used during encryption and decryption // Delete temporary files used during encryption and decryption
if recombine || len(allFiles) > 1 || len(onlyFolders) > 0 || compress { if recombine || len(allFiles) > 1 || len(onlyFolders) > 0 || compress {
os.Remove(inputFile) if err := os.Remove(inputFile); err != nil {
panic(err)
}
if deniability { if deniability {
os.Remove(strings.TrimSuffix(inputFile, ".tmp")) if err := os.Remove(strings.TrimSuffix(inputFile, ".tmp")); err != nil {
panic(err)
}
} }
} }
@ -2428,26 +2529,38 @@ func work() {
if err != nil { if err != nil {
break break
} }
os.Remove(fmt.Sprintf("%s.%d", inputFileOld, i)) if err := os.Remove(fmt.Sprintf("%s.%d", inputFileOld, i)); err != nil {
panic(err)
}
i++ i++
} }
} else { } else {
os.Remove(inputFile) if err := os.Remove(inputFile); err != nil {
panic(err)
}
if deniability { if deniability {
os.Remove(strings.TrimSuffix(inputFile, ".tmp")) if err := os.Remove(strings.TrimSuffix(inputFile, ".tmp")); err != nil {
panic(err)
}
} }
} }
} else { } else {
for _, i := range onlyFiles { for _, i := range onlyFiles {
os.Remove(i) if err := os.Remove(i); err != nil {
panic(err)
}
} }
for _, i := range onlyFolders { for _, i := range onlyFolders {
os.RemoveAll(i) if err := os.RemoveAll(i); err != nil {
panic(err)
}
} }
} }
} }
if mode == "decrypt" && deniability { if mode == "decrypt" && deniability {
os.Remove(inputFile) if err := os.Remove(inputFile); err != nil {
panic(err)
}
} }
if mode == "decrypt" && !kept && autoUnzip { if mode == "decrypt" && !kept && autoUnzip {
@ -2462,7 +2575,9 @@ func work() {
return return
} }
os.Remove(outputFile) if err := os.Remove(outputFile); err != nil {
panic(err)
}
} }
// All done, reset the UI // All done, reset the UI