Documentation
¶
Overview ¶
Package qasago contains secure cryptographic utility functions This file provides secure encryption and decryption using AES-256-GCM AES-256-GCM provides authenticated encryption with associated data (AEAD)
Example ¶
Example demonstrates basic encryption and decryption
package main
import (
"fmt"
"log"
"github.com/djwarf/qasago"
)
func main() {
// Generate a new encryption key
key, err := qasago.GenerateEncryptionKey()
if err != nil {
log.Fatal(err)
}
// Encrypt some sensitive data
plaintext := "my-secret-password"
ciphertext, err := qasago.Encrypt(plaintext, key)
if err != nil {
log.Fatal(err)
}
// Decrypt the data
decrypted, err := qasago.Decrypt(ciphertext, key)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Original: %s\nDecrypted: %s\n", plaintext, decrypted)
}
Output: Original: my-secret-password Decrypted: my-secret-password
Example (ErrorHandling) ¶
Example_errorHandling demonstrates proper error handling
package main
import (
"fmt"
"github.com/djwarf/qasago"
)
func main() {
// Wrong key size
wrongKey := make([]byte, 16) // Should be 32 bytes
_, err := qasago.Encrypt("data", wrongKey)
if err == qasago.ErrInvalidKeySize {
fmt.Println("Error: Key must be 32 bytes for AES-256")
}
// Invalid ciphertext
validKey := make([]byte, 32)
_, err = qasago.Decrypt("not-valid-base64!", validKey)
if err != nil {
fmt.Println("Error: Invalid ciphertext format")
}
}
Output: Error: Key must be 32 bytes for AES-256 Error: Invalid ciphertext format
Example (KeyRotation) ¶
Example_keyRotation demonstrates how to rotate encryption keys
package main
import (
"fmt"
"github.com/djwarf/qasago"
)
func main() {
// Generate old and new keys
oldKey, _ := qasago.GenerateEncryptionKey()
newKey, _ := qasago.GenerateEncryptionKey()
// Encrypt with old key
plaintext := "sensitive data"
ciphertext, _ := qasago.Encrypt(plaintext, oldKey)
// Rotate: decrypt with old key, re-encrypt with new key
decrypted, _ := qasago.Decrypt(ciphertext, oldKey)
newCiphertext, _ := qasago.Encrypt(decrypted, newKey)
// Verify with new key
verified, _ := qasago.Decrypt(newCiphertext, newKey)
fmt.Printf("Data successfully rotated: %s\n", verified)
}
Output: Data successfully rotated: sensitive data
Index ¶
- Constants
- Variables
- func DecodeKey(encoded string) ([]byte, error)
- func Decrypt(encryptedData string, key []byte) (string, error)
- func EncodeKey(key []byte) string
- func Encrypt(plaintext string, key []byte) (string, error)
- func GenerateEncryptionKey() ([]byte, error)
- func ValidateEncryptionKey(key []byte) error
- type CipherText
- type Config
- type EncryptionKey
- type PlainText
Examples ¶
Constants ¶
const ( // KeySize is the required size for AES-256 encryption (256 bits = 32 bytes) KeySize = 32 // NonceSize is the size of the nonce for GCM mode (96 bits = 12 bytes) // GCM recommends 96-bit nonces for optimal performance NonceSize = 12 )
Constants for encryption configuration
Variables ¶
var ( // ErrInvalidKeySize indicates the encryption key is not 32 bytes ErrInvalidKeySize = errors.New("encryption key must be exactly 32 bytes for AES-256") // ErrEmptyPlaintext indicates attempt to encrypt empty data ErrEmptyPlaintext = errors.New("plaintext cannot be empty") // ErrInvalidCiphertext indicates the ciphertext is too short or corrupted ErrInvalidCiphertext = errors.New("invalid ciphertext format or length") // ErrDecryptionFailed indicates authentication tag verification failed ErrDecryptionFailed = errors.New("decryption failed: data may be corrupted or tampered") )
Common errors returned by encryption functions
Functions ¶
func DecodeKey ¶
DecodeKey converts a base64-encoded key back to binary. Use this when loading keys from environment variables or config files.
Parameters:
- encoded: Base64-encoded key string
Returns:
- []byte: Binary encryption key
- error: Any decoding error
Example ¶
ExampleDecodeKey demonstrates decoding a stored key
package main
import (
"fmt"
"os"
"github.com/djwarf/qasago"
)
func main() {
// In practice, this would come from an environment variable
encodedKey := os.Getenv("ENCRYPTION_KEY")
if encodedKey == "" {
// For example purposes, use a dummy value
// This is a valid 32-byte key encoded in base64
key := make([]byte, 32)
for i := range key {
key[i] = byte(i)
}
encodedKey = qasago.EncodeKey(key)
}
key, err := qasago.DecodeKey(encodedKey)
if err != nil {
fmt.Printf("Failed to decode key: %v\n", err)
return
}
fmt.Printf("Key decoded successfully, length: %d bytes\n", len(key))
}
Output: Key decoded successfully, length: 32 bytes
func Decrypt ¶
Decrypt decrypts a base64-encoded AES-256-GCM ciphertext. The function expects the nonce to be prepended to the ciphertext. Authentication tag verification ensures data integrity.
Parameters:
- encryptedData: Base64-encoded nonce + ciphertext + auth tag
- key: The same 32-byte key used for encryption
Returns:
- string: The decrypted plaintext
- error: Any decryption or authentication error
Security: Returns error if authentication fails (tampering detected)
Example ¶
ExampleDecrypt demonstrates decrypting data
package main
import (
"fmt"
"github.com/djwarf/qasago"
)
func main() {
// In production, retrieve your key securely
key := make([]byte, 32)
// Example ciphertext (in practice, this would be retrieved from storage)
// This is just for demonstration - it won't actually decrypt
ciphertext := "base64-encoded-ciphertext-here"
_, err := qasago.Decrypt(ciphertext, key)
if err != nil {
// Handle decryption error
fmt.Println("Decryption failed: invalid ciphertext or wrong key")
}
}
Output: Decryption failed: invalid ciphertext or wrong key
func EncodeKey ¶
EncodeKey converts a binary key to base64 for configuration storage. Use this when storing keys in environment variables or config files.
Parameters:
- key: Binary encryption key
Returns:
- string: Base64-encoded key safe for text storage
Example ¶
ExampleEncodeKey demonstrates encoding a key for storage
package main
import (
"fmt"
"log"
"github.com/djwarf/qasago"
)
func main() {
key, err := qasago.GenerateEncryptionKey()
if err != nil {
log.Fatal(err)
}
// Encode for storage (e.g., in environment variable)
encoded := qasago.EncodeKey(key)
// The encoded key is base64
fmt.Printf("Encoded key ready for storage: %t\n", len(encoded) > 0)
}
Output: Encoded key ready for storage: true
func Encrypt ¶
Encrypt securely encrypts plaintext using AES-256-GCM with a random nonce. The function prepends the nonce to the ciphertext for self-contained storage. The result is base64-encoded for safe storage in text fields.
Parameters:
- plaintext: The data to encrypt (cannot be empty)
- key: Exactly 32 bytes for AES-256 encryption
Returns:
- string: Base64-encoded nonce + ciphertext + auth tag
- error: Any encryption error
Format: base64(nonce[12] || ciphertext[...] || authTag[16])
Example ¶
ExampleEncrypt demonstrates encrypting data
package main
import (
"fmt"
"log"
"github.com/djwarf/qasago"
)
func main() {
// In production, generate or retrieve your key securely
key := make([]byte, 32)
// ... populate key from secure storage ...
plaintext := "sensitive information"
ciphertext, err := qasago.Encrypt(plaintext, key)
if err != nil {
log.Fatal(err)
}
// The ciphertext is base64 encoded and safe to store as text
fmt.Printf("Ciphertext is base64 encoded: %t\n", len(ciphertext) > 0)
}
Output: Ciphertext is base64 encoded: true
func GenerateEncryptionKey ¶
GenerateEncryptionKey creates a cryptographically secure 256-bit key. This should be called once during initial setup and the key stored securely.
Returns:
- []byte: 32-byte encryption key
- error: Any generation error
Security: Store this key securely (environment variable, secrets manager) WARNING: Losing this key means encrypted data cannot be recovered
Example ¶
ExampleGenerateEncryptionKey demonstrates key generation
package main
import (
"fmt"
"log"
"github.com/djwarf/qasago"
)
func main() {
key, err := qasago.GenerateEncryptionKey()
if err != nil {
log.Fatal(err)
}
// Key is 32 bytes for AES-256
fmt.Printf("Key length: %d bytes\n", len(key))
}
Output: Key length: 32 bytes
func ValidateEncryptionKey ¶
ValidateEncryptionKey checks if a key is suitable for AES-256 encryption. This helps catch configuration errors early.
Parameters:
- key: The encryption key to validate
Returns:
- error: nil if valid, error describing the issue otherwise
Types ¶
type CipherText ¶ added in v1.1.0
type CipherText string
CipherText represents encrypted data in base64 format. It contains the nonce, ciphertext, and authentication tag.
func (CipherText) String ¶ added in v1.1.0
func (c CipherText) String() string
String returns the string representation of the ciphertext.
type Config ¶ added in v1.1.0
type Config struct {
// Key is the AES-256 encryption key (must be 32 bytes)
Key EncryptionKey
}
Config represents encryption configuration options. This type can be extended in the future to support additional encryption modes.
Example ¶
ExampleConfig demonstrates using the Config type
package main
import (
"fmt"
"log"
"github.com/djwarf/qasago"
)
func main() {
// Generate a new key
key, err := qasago.GenerateEncryptionKey()
if err != nil {
log.Fatal(err)
}
// Create a config instance
config := qasago.Config{
Key: key,
}
// Use the config for encryption
plaintext := "database-connection-string"
ciphertext, err := config.Encrypt(plaintext)
if err != nil {
log.Fatal(err)
}
// Use the same config for decryption
decrypted, err := config.Decrypt(ciphertext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Successfully encrypted and decrypted: %s\n", decrypted)
}
Output: Successfully encrypted and decrypted: database-connection-string
func NewConfig ¶ added in v1.1.0
NewConfig creates a new encryption configuration with the provided key.
type EncryptionKey ¶ added in v1.1.0
type EncryptionKey []byte
EncryptionKey represents a 256-bit AES encryption key. It provides type safety and clarity when working with encryption keys.
func (EncryptionKey) Bytes ¶ added in v1.1.0
func (k EncryptionKey) Bytes() []byte
Bytes returns the raw byte representation of the key.
func (EncryptionKey) String ¶ added in v1.1.0
func (k EncryptionKey) String() string
String returns the base64-encoded representation of the key.
func (EncryptionKey) Validate ¶ added in v1.1.0
func (k EncryptionKey) Validate() error
Validate checks if the encryption key is valid for AES-256.