remove aes comparison and add ciphertext overhead comments
This commit is contained in:
@@ -25,7 +25,8 @@ func GenerateKey() ([]byte, error) {
|
|||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptWithKey encrypts data using secretbox with the provided key
|
// EncryptWithKey encrypts data using NaCl's secretbox with the provided key.
|
||||||
|
// 40 bytes of overhead (24-byte nonce + 16-byte MAC) are added to the plaintext size.
|
||||||
func EncryptWithKey(data, key []byte) ([]byte, error) {
|
func EncryptWithKey(data, key []byte) ([]byte, error) {
|
||||||
if err := validateKey(key); err != nil {
|
if err := validateKey(key); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -2,12 +2,7 @@ package crypto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -147,147 +142,3 @@ func tamperWithBytes(data []byte) []byte {
|
|||||||
tampered[24] ^= 0x01 // Modify first byte after nonce
|
tampered[24] ^= 0x01 // Modify first byte after nonce
|
||||||
return tampered
|
return tampered
|
||||||
}
|
}
|
||||||
|
|
||||||
func encryptWithAESKey(data, key []byte) ([]byte, error) {
|
|
||||||
if err := validateKey(key); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
aesGCM, err := cipher.NewGCM(block)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
nonce := make([]byte, aesGCM.NonceSize())
|
|
||||||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return aesGCM.Seal(nonce, nonce, data, nil), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func decryptWithAESKey(data, key []byte) ([]byte, error) {
|
|
||||||
if err := validateKey(key); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
aesGCM, err := cipher.NewGCM(block)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
nonceSize := aesGCM.NonceSize()
|
|
||||||
if len(data) < nonceSize {
|
|
||||||
return nil, ErrShortCipherText
|
|
||||||
}
|
|
||||||
|
|
||||||
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
|
|
||||||
plaintext, err := aesGCM.Open(nil, nonce, ciphertext, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("decryption failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
return plaintext, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEncryption(b *testing.B) {
|
|
||||||
key := make([]byte, keySize)
|
|
||||||
_, err := rand.Read(key)
|
|
||||||
require.NoError(b, err)
|
|
||||||
|
|
||||||
sizes := []int{16, 64, 256, 1024, 4096} // Test different payload sizes
|
|
||||||
for _, size := range sizes {
|
|
||||||
data := make([]byte, size)
|
|
||||||
_, err := rand.Read(data)
|
|
||||||
require.NoError(b, err)
|
|
||||||
|
|
||||||
b.Run(fmt.Sprintf("Secretbox-%dB", size), func(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
encrypted, err := EncryptWithKey(data, key)
|
|
||||||
require.NoError(b, err)
|
|
||||||
b.SetBytes(int64(len(encrypted)))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
b.Run(fmt.Sprintf("AES-GCM-%dB", size), func(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
encrypted, err := encryptWithAESKey(data, key)
|
|
||||||
require.NoError(b, err)
|
|
||||||
b.SetBytes(int64(len(encrypted)))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkDecryption(b *testing.B) {
|
|
||||||
key := make([]byte, keySize)
|
|
||||||
_, err := rand.Read(key)
|
|
||||||
require.NoError(b, err)
|
|
||||||
|
|
||||||
sizes := []int{16, 64, 256, 1024, 4096}
|
|
||||||
for _, size := range sizes {
|
|
||||||
data := make([]byte, size)
|
|
||||||
_, err := rand.Read(data)
|
|
||||||
require.NoError(b, err)
|
|
||||||
|
|
||||||
secretboxEncrypted, err := EncryptWithKey(data, key)
|
|
||||||
require.NoError(b, err)
|
|
||||||
|
|
||||||
aesGCMEncrypted, err := encryptWithAESKey(data, key)
|
|
||||||
require.NoError(b, err)
|
|
||||||
|
|
||||||
b.Run(fmt.Sprintf("Secretbox-%dB", size), func(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
decrypted, err := DecryptStringWithKey(secretboxEncrypted, key)
|
|
||||||
require.NoError(b, err)
|
|
||||||
b.SetBytes(int64(len(decrypted)))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
b.Run(fmt.Sprintf("AES-GCM-%dB", size), func(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
decrypted, err := decryptWithAESKey(aesGCMEncrypted, key)
|
|
||||||
require.NoError(b, err)
|
|
||||||
b.SetBytes(int64(len(decrypted)))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestCiphertextSizeComparison shows that Secretbox encryption entails
|
|
||||||
// a slightly larger ciphertext overhead of 40 bytes, compared to AES-GCM,
|
|
||||||
// whose overhead is just 28 bytes.
|
|
||||||
func TestCiphertextSizeComparison(t *testing.T) {
|
|
||||||
key := make([]byte, keySize)
|
|
||||||
_, err := rand.Read(key)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
sizes := []int{0, 16, 64, 256, 1024, 4096}
|
|
||||||
for _, size := range sizes {
|
|
||||||
t.Run(fmt.Sprintf("size-%d", size), func(t *testing.T) {
|
|
||||||
data := make([]byte, size)
|
|
||||||
_, err := rand.Read(data)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
sbCiphertext, err := EncryptWithKey(data, key)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
aesCiphertext, err := encryptWithAESKey(data, key)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
t.Logf("Input size: %d bytes", size)
|
|
||||||
t.Logf("Secretbox size: %d bytes (overhead: %d bytes)", len(sbCiphertext), len(sbCiphertext)-size)
|
|
||||||
t.Logf("AES-GCM size: %d bytes (overhead: %d bytes)", len(aesCiphertext), len(aesCiphertext)-size)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ func (m *Meta) Add(key string, val any) error {
|
|||||||
// AddEncrypted adds a key/value pair in the meta set.
|
// AddEncrypted adds a key/value pair in the meta set.
|
||||||
// The value is encrypted with the given encryptionKey.
|
// The value is encrypted with the given encryptionKey.
|
||||||
// Accepted types for the value are: string, []byte.
|
// Accepted types for the value are: string, []byte.
|
||||||
|
// The ciphertext will be 40 bytes larger than the plaintext due to encryption overhead.
|
||||||
func (m *Meta) AddEncrypted(key string, val any, encryptionKey []byte) error {
|
func (m *Meta) AddEncrypted(key string, val any, encryptionKey []byte) error {
|
||||||
var encrypted []byte
|
var encrypted []byte
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ func WithMeta(key string, val any) Option {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithEncryptedMetaString adds a key/value pair in the "meta" field.
|
// WithEncryptedMetaString adds a key/value pair in the "meta" field.
|
||||||
// The string value is encrypted with the given aesKey.
|
// The string value is encrypted with the given key.
|
||||||
|
// The ciphertext will be 40 bytes larger than the plaintext due to encryption overhead.
|
||||||
func WithEncryptedMetaString(key, val string, encryptionKey []byte) Option {
|
func WithEncryptedMetaString(key, val string, encryptionKey []byte) Option {
|
||||||
return func(t *Token) error {
|
return func(t *Token) error {
|
||||||
return t.meta.AddEncrypted(key, val, encryptionKey)
|
return t.meta.AddEncrypted(key, val, encryptionKey)
|
||||||
@@ -53,7 +54,8 @@ func WithEncryptedMetaString(key, val string, encryptionKey []byte) Option {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithEncryptedMetaBytes adds a key/value pair in the "meta" field.
|
// WithEncryptedMetaBytes adds a key/value pair in the "meta" field.
|
||||||
// The []byte value is encrypted with the given aesKey.
|
// The []byte value is encrypted with the given key.
|
||||||
|
// The ciphertext will be 40 bytes larger than the plaintext due to encryption overhead.
|
||||||
func WithEncryptedMetaBytes(key string, val, encryptionKey []byte) Option {
|
func WithEncryptedMetaBytes(key string, val, encryptionKey []byte) Option {
|
||||||
return func(t *Token) error {
|
return func(t *Token) error {
|
||||||
return t.meta.AddEncrypted(key, val, encryptionKey)
|
return t.meta.AddEncrypted(key, val, encryptionKey)
|
||||||
|
|||||||
Reference in New Issue
Block a user