Documentation
¶
Index ¶
Examples ¶
Constants ¶
const ( // EncryptTagName is the struct tag name used to mark fields for encryption EncryptTagName = "encrypt" // HashTagName is the struct tag name used to mark fields for hashing HashTagName = "hash" // PluginName is the name of the GORM plugin PluginName = "encryption" )
Variables ¶
var ( // ErrInvalidKeySize is returned when the encryption key size is invalid ErrInvalidKeySize = errors.New("encryption key must be 16, 24, or 32 bytes for AES-128, AES-192, or AES-256") // ErrEncryptionFailed is returned when encryption fails ErrEncryptionFailed = errors.New("encryption failed") // ErrDecryptionFailed is returned when decryption fails ErrDecryptionFailed = errors.New("decryption failed") // ErrInvalidCiphertext is returned when the ciphertext is invalid ErrInvalidCiphertext = errors.New("invalid ciphertext: too short or malformed") )
Functions ¶
func GenerateKey ¶
GenerateKey generates a random encryption key of the specified size size should be 16, 24, or 32 for AES-128, AES-192, or AES-256
func GenerateKeyString ¶
GenerateKeyString generates a random encryption key and returns it as a base64-encoded string
func Hash ¶
Hash generates a SHA-256 hash of the input string This is useful for creating searchable hashes of encrypted fields Returns a hex-encoded hash string
Example ¶
ExampleHash demonstrates searching encrypted fields using hashes
package main
import (
"fmt"
"log"
"github.com/cgholdings/go-common/database/encryption"
"gorm.io/gorm"
)
// User model with encrypted fields
type User struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"type:varchar(255)"`
Email string `gorm:"type:varchar(255)"`
SSN string `gorm:"type:text" encrypt:"true"`
SSNHash string `gorm:"type:varchar(64);index" hash:"SSN"`
CreditCard string `gorm:"type:text" encrypt:"true"`
CCHash string `gorm:"type:varchar(64);index" hash:"CreditCard"`
}
func main() {
// Setup (omitted for brevity - see ExampleGORMIntegration)
var db *gorm.DB
// Search for a user by SSN using the hash
searchSSN := "123-45-6789"
ssnHash := encryption.Hash(searchSSN)
var user User
if err := db.Where("ssn_hash = ?", ssnHash).First(&user).Error; err != nil {
log.Fatal(err)
}
// The SSN field is automatically decrypted
fmt.Printf("Found user: %s, SSN: %s\n", user.Name, user.SSN)
}
Example (Searching) ¶
ExampleHash_searching demonstrates manual hashing
package main
import (
"fmt"
"github.com/cgholdings/go-common/database/encryption"
)
func main() {
// Hash a value for searching
ssn := "123-45-6789"
hash := encryption.Hash(ssn)
fmt.Printf("SSN: %s\n", ssn)
fmt.Printf("Hash: %s\n", hash)
// Hash is deterministic
hash2 := encryption.Hash(ssn)
fmt.Printf("Hashes match: %v\n", hash == hash2)
// Different values produce different hashes
hash3 := encryption.Hash("999-88-7777")
fmt.Printf("Different hashes: %v\n", hash != hash3)
}
Types ¶
type Config ¶
type Config struct {
// Key is the encryption key (16, 24, or 32 bytes)
Key []byte
// KeyString is the base64-encoded encryption key (alternative to Key)
KeyString string
// KeyEnvVar is the environment variable name containing the encryption key
KeyEnvVar string
}
Config holds the configuration for the encryption plugin
func DefaultConfig ¶
func DefaultConfig() *Config
DefaultConfig returns a default configuration that reads the key from the ENCRYPTION_KEY environment variable
Example ¶
ExampleDefaultConfig demonstrates loading config from environment
package main
import (
"fmt"
"log"
"github.com/cgholdings/go-common/database/encryption"
)
func main() {
// Set environment variable: export ENCRYPTION_KEY="base64-encoded-key"
// Load config from default environment variable
config := encryption.DefaultConfig()
_, err := encryption.NewEncryptorFromConfig(config)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Encryptor created from environment variable\n")
}
type Encryptor ¶
type Encryptor struct {
// contains filtered or unexported fields
}
Encryptor handles encryption and decryption operations
func NewEncryptor ¶
NewEncryptor creates a new Encryptor with the provided key The key should be 16, 24, or 32 bytes for AES-128, AES-192, or AES-256
Example ¶
ExampleNewEncryptor demonstrates basic encryption/decryption
package main
import (
"fmt"
"log"
"github.com/cgholdings/go-common/database/encryption"
)
func main() {
// Generate a new encryption key (32 bytes for AES-256)
key, err := encryption.GenerateKey(32)
if err != nil {
log.Fatal(err)
}
// Create encryptor
encryptor, err := encryption.NewEncryptor(key)
if err != nil {
log.Fatal(err)
}
// Encrypt data
plaintext := "sensitive-data-123"
ciphertext, err := encryptor.Encrypt(plaintext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Encrypted: %s\n", ciphertext)
// Decrypt data
decrypted, err := encryptor.Decrypt(ciphertext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Decrypted: %s\n", decrypted)
}
func NewEncryptorFromConfig ¶
NewEncryptorFromConfig creates a new Encryptor from a Config
Example ¶
ExampleNewEncryptorFromConfig demonstrates using a base64-encoded key
package main
import (
"fmt"
"log"
"github.com/cgholdings/go-common/database/encryption"
)
func main() {
// Generate a key string once and save it securely
keyString, err := encryption.GenerateKeyString(32)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Generated key (save this securely): %s\n", keyString)
// Later, load from config
config := &encryption.Config{
KeyString: keyString,
}
encryptor, err := encryption.NewEncryptorFromConfig(config)
if err != nil {
log.Fatal(err)
}
// Use encryptor...
_ = encryptor
}
func NewEncryptorFromString ¶
NewEncryptorFromString creates a new Encryptor from a base64-encoded key string
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin is a GORM plugin that automatically encrypts and decrypts fields
func NewPlugin ¶
NewPlugin creates a new encryption plugin for GORM
Example ¶
ExampleNewPlugin demonstrates GORM plugin usage
package main
import (
"fmt"
"log"
"github.com/cgholdings/go-common/database/encryption"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
// User model with encrypted fields
type User struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"type:varchar(255)"`
Email string `gorm:"type:varchar(255)"`
SSN string `gorm:"type:text" encrypt:"true"`
SSNHash string `gorm:"type:varchar(64);index" hash:"SSN"`
CreditCard string `gorm:"type:text" encrypt:"true"`
CCHash string `gorm:"type:varchar(64);index" hash:"CreditCard"`
}
func main() {
// Generate encryption key
key, err := encryption.GenerateKey(32)
if err != nil {
log.Fatal(err)
}
// Create encryptor
encryptor, err := encryption.NewEncryptor(key)
if err != nil {
log.Fatal(err)
}
// Setup database
dsn := "host=localhost user=postgres password=pass dbname=dbname port=5432 sslmode=disable"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
// Register encryption plugin
if err := db.Use(encryption.NewPlugin(encryptor)); err != nil {
log.Fatal(err)
}
// Auto migrate
if err := db.AutoMigrate(&User{}); err != nil {
log.Fatal(err)
}
// Create user - SSN and CreditCard will be encrypted automatically
user := User{
Name: "John Doe",
Email: "john@example.com",
SSN: "123-45-6789",
CreditCard: "4111111111111111",
}
if err := db.Create(&user).Error; err != nil {
log.Fatal(err)
}
fmt.Printf("Created user with ID: %d\n", user.ID)
fmt.Printf("SSN Hash: %s\n", user.SSNHash)
// Query user - encrypted fields will be decrypted automatically
var retrieved User
if err := db.First(&retrieved, user.ID).Error; err != nil {
log.Fatal(err)
}
fmt.Printf("Retrieved SSN: %s\n", retrieved.SSN)
}
Example (Batch) ¶
ExampleNewPlugin_batch demonstrates batch create and query
package main
import (
"fmt"
"log"
"gorm.io/gorm"
)
// User model with encrypted fields
type User struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"type:varchar(255)"`
Email string `gorm:"type:varchar(255)"`
SSN string `gorm:"type:text" encrypt:"true"`
SSNHash string `gorm:"type:varchar(64);index" hash:"SSN"`
CreditCard string `gorm:"type:text" encrypt:"true"`
CCHash string `gorm:"type:varchar(64);index" hash:"CreditCard"`
}
func main() {
// Setup (omitted for brevity)
var db *gorm.DB
// Create multiple users - all encrypted automatically
users := []User{
{Name: "User1", SSN: "111-11-1111", CreditCard: "4111111111111111"},
{Name: "User2", SSN: "222-22-2222", CreditCard: "4222222222222222"},
{Name: "User3", SSN: "333-33-3333", CreditCard: "4333333333333333"},
}
if err := db.Create(&users).Error; err != nil {
log.Fatal(err)
}
fmt.Printf("Created %d users\n", len(users))
// Query all users - all decrypted automatically
var retrieved []User
if err := db.Find(&retrieved).Error; err != nil {
log.Fatal(err)
}
for _, user := range retrieved {
fmt.Printf("User: %s, SSN: %s\n", user.Name, user.SSN)
}
}
Example (Update) ¶
ExampleNewPlugin_update demonstrates updating encrypted fields
package main
import (
"fmt"
"log"
"gorm.io/gorm"
)
// User model with encrypted fields
type User struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"type:varchar(255)"`
Email string `gorm:"type:varchar(255)"`
SSN string `gorm:"type:text" encrypt:"true"`
SSNHash string `gorm:"type:varchar(64);index" hash:"SSN"`
CreditCard string `gorm:"type:text" encrypt:"true"`
CCHash string `gorm:"type:varchar(64);index" hash:"CreditCard"`
}
func main() {
// Setup (omitted for brevity)
var db *gorm.DB
var user User
// Update SSN - will be re-encrypted automatically
user.SSN = "999-88-7777"
if err := db.Save(&user).Error; err != nil {
log.Fatal(err)
}
// SSNHash is also updated automatically
fmt.Printf("Updated SSN, new hash: %s\n", user.SSNHash)
}
func NewPluginFromConfig ¶
NewPluginFromConfig creates a new encryption plugin from a Config
func (*Plugin) Initialize ¶
Initialize initializes the plugin and registers callbacks