diff --git a/.ideas/future_improvements.md b/.ideas/future_improvements.md new file mode 100644 index 0000000..391b41d --- /dev/null +++ b/.ideas/future_improvements.md @@ -0,0 +1,7 @@ +# Future Improvements + +This file contains a list of ideas for future improvements to the Enchantrix library. + +- **Fully implement the PGP module:** The PGP module is currently commented out due to dependency issues. This needs to be resolved so that the PGP functionality can be used. +- **Define the `.trix` file format:** The `.trix` file format needs to be defined and implemented. This will be the standard file format for encrypted data. +- **Build the rootFS passthrough storage:** The rootFS passthrough storage needs to be built. This will allow Web3 apps to use Enchantrix to give clients private keys securely. diff --git a/chachapoly/chachapoly.go b/chachapoly/chachapoly.go index 60f356a..2520c67 100644 --- a/chachapoly/chachapoly.go +++ b/chachapoly/chachapoly.go @@ -10,9 +10,6 @@ import ( // Encrypt encrypts data using ChaCha20-Poly1305. func Encrypt(plaintext []byte, key []byte) ([]byte, error) { - if len(key) != chacha20poly1305.KeySize { - return nil, fmt.Errorf("invalid key size: got %d bytes, want %d bytes", len(key), chacha20poly1305.KeySize) - } aead, err := chacha20poly1305.NewX(key) if err != nil { return nil, err @@ -28,9 +25,6 @@ func Encrypt(plaintext []byte, key []byte) ([]byte, error) { // Decrypt decrypts data using ChaCha20-Poly1305. func Decrypt(ciphertext []byte, key []byte) ([]byte, error) { - if len(key) != chacha20poly1305.KeySize { - return nil, fmt.Errorf("invalid key size: got %d bytes, want %d bytes", len(key), chacha20poly1305.KeySize) - } aead, err := chacha20poly1305.NewX(key) if err != nil { return nil, err @@ -43,5 +37,14 @@ func Decrypt(ciphertext []byte, key []byte) ([]byte, error) { nonce, ciphertext := ciphertext[:aead.NonceSize()], ciphertext[aead.NonceSize():] - return aead.Open(nil, nonce, ciphertext, nil) + decrypted, err := aead.Open(nil, nonce, ciphertext, nil) + if err != nil { + return nil, err + } + + if len(decrypted) == 0 { + return []byte{}, nil + } + + return decrypted, nil } diff --git a/chachapoly/chachapoly_test.go b/chachapoly/chachapoly_test.go index fb5ef73..539569d 100644 --- a/chachapoly/chachapoly_test.go +++ b/chachapoly/chachapoly_test.go @@ -21,3 +21,65 @@ func TestEncryptDecrypt(t *testing.T) { assert.Equal(t, plaintext, decrypted) } + +func TestEncryptInvalidKeySize(t *testing.T) { + key := make([]byte, 16) // Wrong size + plaintext := []byte("test") + _, err := Encrypt(plaintext, key) + assert.Error(t, err) +} + +func TestDecryptWithWrongKey(t *testing.T) { + key1 := make([]byte, 32) + key2 := make([]byte, 32) + key2[0] = 1 // Different key + + plaintext := []byte("secret") + ciphertext, err := Encrypt(plaintext, key1) + assert.NoError(t, err) + + _, err = Decrypt(ciphertext, key2) + assert.Error(t, err) // Should fail authentication +} + +func TestDecryptTamperedCiphertext(t *testing.T) { + key := make([]byte, 32) + plaintext := []byte("secret") + ciphertext, err := Encrypt(plaintext, key) + assert.NoError(t, err) + + // Tamper with the ciphertext + ciphertext[0] ^= 0xff + + _, err = Decrypt(ciphertext, key) + assert.Error(t, err) +} + +func TestEncryptEmptyPlaintext(t *testing.T) { + key := make([]byte, 32) + plaintext := []byte("") + ciphertext, err := Encrypt(plaintext, key) + assert.NoError(t, err) + + decrypted, err := Decrypt(ciphertext, key) + assert.NoError(t, err) + + assert.Equal(t, plaintext, decrypted) +} + +func TestDecryptShortCiphertext(t *testing.T) { + key := make([]byte, 32) + shortCiphertext := []byte("short") + + _, err := Decrypt(shortCiphertext, key) + assert.Error(t, err) + assert.Contains(t, err.Error(), "too short") +} + +func TestCiphertextDiffersFromPlaintext(t *testing.T) { + key := make([]byte, 32) + plaintext := []byte("Hello, world!") + ciphertext, err := Encrypt(plaintext, key) + assert.NoError(t, err) + assert.NotEqual(t, plaintext, ciphertext) +}