Skip to content

Commit 589e46a

Browse files
author
Anand
committed
Support for XChacha20-Poly1305 cipher
1 parent 45161cb commit 589e46a

File tree

1 file changed

+159
-8
lines changed

1 file changed

+159
-8
lines changed

crypto.go

Lines changed: 159 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"crypto/sha512"
99
"errors"
1010
"fmt"
11+
chacha "golang.org/x/crypto/chacha20poly1305"
1112
"golang.org/x/crypto/pbkdf2"
1213
"io"
1314
"math/big"
@@ -96,7 +97,7 @@ func isFileEncrypted(encDbPath string) (error, bool) {
9697
}
9798

9899
// Encrypt the database path using AES
99-
func encryptFile(dbPath string, password string) error {
100+
func encryptFileAES(dbPath string, password string) error {
100101

101102
var err error
102103
var key []byte
@@ -136,10 +137,12 @@ func encryptFile(dbPath string, password string) error {
136137
return err
137138
}
138139

139-
err, nonce = generateRandomBytes(aesGCM.NonceSize())
140+
nonceSize := aesGCM.NonceSize()
141+
// fmt.Printf("%d\n", nonceSize)
142+
err, nonce = generateRandomBytes(nonceSize)
140143

141144
if err != nil {
142-
fmt.Printf("Error - Init vector generation failed -\"%s\"\n", err)
145+
fmt.Printf("Error - Nonce generation failed -\"%s\"\n", err)
143146
return err
144147
}
145148

@@ -159,9 +162,9 @@ func encryptFile(dbPath string, password string) error {
159162

160163
encDbPath = dbPath + ".varuh"
161164

162-
err = os.WriteFile(encDbPath, encText, 0644)
165+
err = os.WriteFile(encDbPath, encText, 0600)
163166
if err == nil {
164-
err = os.WriteFile(dbPath, encText, 0644)
167+
err = os.WriteFile(dbPath, encText, 0600)
165168
if err == nil {
166169
// Remove backup
167170
os.Remove(encDbPath)
@@ -174,8 +177,8 @@ func encryptFile(dbPath string, password string) error {
174177
return err
175178
}
176179

177-
// Decrypt an already encrypted database file using given password
178-
func decryptFile(encDbPath string, password string) error {
180+
// Decrypt an already encrypted database file using given password using AES
181+
func decryptFileAES(encDbPath string, password string) error {
179182

180183
var encText []byte
181184
var cipherText []byte
@@ -246,7 +249,155 @@ func decryptFile(encDbPath string, password string) error {
246249
return err
247250
}
248251

249-
err = rewriteBaseFile(encDbPath, plainText, 0600)
252+
err, origFile = rewriteBaseFile(encDbPath, plainText, 0600)
253+
254+
if err != nil {
255+
fmt.Printf("Error writing decrypted data to %s - \"%s\"\n", origFile, err.Error())
256+
}
257+
258+
// fmt.Printf("%s\n", string(plainText))
259+
return err
260+
}
261+
262+
// Encrypt a file using XChaCha20-Poly1305 cipher
263+
func encryptFileXChachaPoly(dbPath string, password string) error {
264+
265+
var err error
266+
var key []byte
267+
var nonce []byte
268+
var salt []byte
269+
var plainText []byte
270+
var cipherText []byte
271+
var magicBytes []byte
272+
var encText []byte
273+
var encDbPath string
274+
var hmacHash []byte
275+
276+
plainText, err = os.ReadFile(dbPath)
277+
if err != nil {
278+
fmt.Printf("Error - Can't read database -\"%s\"\n", err)
279+
return err
280+
}
281+
282+
err, key, salt = generateKey(password, nil)
283+
284+
if err != nil {
285+
fmt.Printf("Error - Key derivation failed -\"%s\"\n", err)
286+
return err
287+
}
288+
289+
aead, err := chacha.NewX(key)
290+
291+
if err != nil {
292+
fmt.Printf("Error - AEAD creation failed - \"%s\"\n", err)
293+
return err
294+
}
295+
296+
nonce = make([]byte, aead.NonceSize(), aead.NonceSize()+len(plainText)+aead.Overhead())
297+
if _, err = crand.Read(nonce); err != nil {
298+
fmt.Printf("Error - Nonce generation failed -\"%s\"\n", err)
299+
return err
300+
}
301+
302+
magicBytes = []byte(fmt.Sprintf("%x", MAGIC_HEADER))
303+
cipherText = aead.Seal(nonce, nonce, plainText, nil)
304+
305+
// Calculate hmac signature and write it
306+
hCipher := hmac.New(sha512.New, key)
307+
hCipher.Write(cipherText)
308+
309+
hmacHash = hCipher.Sum(nil)
310+
311+
// No need for salt in chacha
312+
encText = append(magicBytes, salt...)
313+
encText = append(encText, hmacHash...)
314+
encText = append(encText, cipherText...)
315+
316+
encDbPath = dbPath + ".varuh"
317+
318+
err = os.WriteFile(encDbPath, encText, 0600)
319+
if err == nil {
320+
err = os.WriteFile(dbPath, encText, 0600)
321+
if err == nil {
322+
// Remove backup
323+
os.Remove(encDbPath)
324+
} else {
325+
fmt.Printf("Error writing encrypted database - \"%s\"\n", err.Error())
326+
}
327+
}
328+
// fmt.Printf("%x\n", cipherText)
329+
330+
return err
331+
}
332+
333+
// Decrypt an already encrypted database file using given password using AES
334+
func decryptFileXChachaPoly(encDbPath string, password string) error {
335+
336+
var encText []byte
337+
var cipherText []byte
338+
var plainText []byte
339+
var salt []byte
340+
var key []byte
341+
var nonce []byte
342+
var hmacHash []byte
343+
var hmacSig []byte
344+
var origFile string
345+
346+
var err error
347+
348+
encText, err = os.ReadFile(encDbPath)
349+
if err != nil {
350+
fmt.Printf("Error - Can't read database -\"%s\"\n", err)
351+
return err
352+
}
353+
354+
encText = encText[unsafe.Sizeof(MAGIC_HEADER):]
355+
// Read the old salt
356+
salt, encText = encText[:SALT_SIZE], encText[SALT_SIZE:]
357+
// Read the hmac hash checksum
358+
hmacHash, encText = encText[:HMAC_SHA512_SIZE], encText[HMAC_SHA512_SIZE:]
359+
360+
err, key, _ = generateKey(password, &salt)
361+
362+
if err != nil {
363+
fmt.Printf("Error - Key derivation failed -\"%s\"\n", err)
364+
return err
365+
}
366+
367+
// verify the hmac
368+
// Calculate hmac signature and write it
369+
hCipher := hmac.New(sha512.New, key)
370+
hCipher.Write(encText)
371+
372+
hmacSig = hCipher.Sum(nil)
373+
374+
// Compare
375+
if !hmac.Equal(hmacSig, hmacHash) {
376+
fmt.Println("Invalid password or tampered data. Aborted")
377+
return errors.New("signature check failed")
378+
}
379+
// fmt.Printf("\nsalt: %x\n", salt)
380+
// fmt.Printf("key: %x\n", key)
381+
382+
aead, err := chacha.NewX(key)
383+
if err != nil {
384+
fmt.Printf("Error - AEAD creation failed - \"%s\"\n", err)
385+
return err
386+
}
387+
388+
nonceSize := aead.NonceSize()
389+
390+
nonce, cipherText = encText[:nonceSize], encText[nonceSize:]
391+
// fmt.Printf("nonce: %x\n", nonce)
392+
plainText, err = aead.Open(nil, nonce, cipherText, nil)
393+
394+
if err != nil {
395+
fmt.Printf("Error - Decryption failed - \"%s\"\n", err)
396+
return err
397+
}
398+
399+
// err = os.WriteFile("test.sqlite3", plainText, 0600)
400+
err, origFile = rewriteBaseFile(encDbPath, plainText, 0600)
250401

251402
if err != nil {
252403
fmt.Printf("Error writing decrypted data to %s - \"%s\"\n", origFile, err.Error())

0 commit comments

Comments
 (0)