mirror of
https://github.com/Picocrypt/Picocrypt.git
synced 2025-05-12 05:48:30 +02:00
handle more errors
This commit is contained in:
parent
b0c2943bb0
commit
0cc109bc6b
1 changed files with 167 additions and 52 deletions
219
src/Picocrypt.go
219
src/Picocrypt.go
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue