Data Masking
Data masking ensures sensitive information like passwords, tokens, and personal data are never logged. ByteHide Logger provides mechanisms to automatically mask specified sensitive keys.
Sensitive Data Types
Common sensitive data that should be masked:
- Authentication: passwords, tokens, session IDs, API keys, JWT
- Personal: email addresses, phone numbers, SSN, driver's license
- Payment: credit card numbers, bank accounts, CVV codes
- Medical: health records, diagnoses, prescriptions
- Business: trade secrets, proprietary algorithms, customer lists
Adding Sensitive Keys
Use AddSensitiveKey() to register keys that should always be masked:
Go
import "github.com/bytehide/bytehide-logs-go"
// Configure at application startup
func init() {
// Authentication
logs.AddSensitiveKey("password")
logs.AddSensitiveKey("token")
logs.AddSensitiveKey("apiKey")
logs.AddSensitiveKey("authToken")
logs.AddSensitiveKey("sessionId")
logs.AddSensitiveKey("refreshToken")
// Personal data
logs.AddSensitiveKey("email")
logs.AddSensitiveKey("phoneNumber")
logs.AddSensitiveKey("ssn")
logs.AddSensitiveKey("driverLicense")
// Payment
logs.AddSensitiveKey("creditCard")
logs.AddSensitiveKey("cardNumber")
logs.AddSensitiveKey("cvv")
logs.AddSensitiveKey("bankAccount")
// Other
logs.AddSensitiveKey("secretKey")
logs.AddSensitiveKey("privateKey")
logs.AddSensitiveKey("apiSecret")
}import "github.com/bytehide/bytehide-logs-go"
// Configure at application startup
func init() {
// Authentication
logs.AddSensitiveKey("password")
logs.AddSensitiveKey("token")
logs.AddSensitiveKey("apiKey")
logs.AddSensitiveKey("authToken")
logs.AddSensitiveKey("sessionId")
logs.AddSensitiveKey("refreshToken")
// Personal data
logs.AddSensitiveKey("email")
logs.AddSensitiveKey("phoneNumber")
logs.AddSensitiveKey("ssn")
logs.AddSensitiveKey("driverLicense")
// Payment
logs.AddSensitiveKey("creditCard")
logs.AddSensitiveKey("cardNumber")
logs.AddSensitiveKey("cvv")
logs.AddSensitiveKey("bankAccount")
// Other
logs.AddSensitiveKey("secretKey")
logs.AddSensitiveKey("privateKey")
logs.AddSensitiveKey("apiSecret")
}Basic Masking Examples
When context values have sensitive keys, they are automatically masked:
Go
import "github.com/bytehide/bytehide-logs-go"
// Sensitive value is masked
logs.WithContext("email", "john@example.com").
Info("User logged in")
// Logged as: User logged in {email: ****}
// Sensitive value is masked
logs.WithContext("creditCard", "4532-1234-5678-9012").
WithContext("amount", 99.99).
Info("Payment processed")
// Logged as: Payment processed {creditCard: ****, amount: 99.99}
// Multiple sensitive values
logs.WithContext("username", "john_doe").
WithContext("password", "SecurePass123").
WithContext("token", "eyJhbGc...").
Warn("Authentication failed")
// Logged as: Authentication failed {username: john_doe, password: ****, token: ****}import "github.com/bytehide/bytehide-logs-go"
// Sensitive value is masked
logs.WithContext("email", "john@example.com").
Info("User logged in")
// Logged as: User logged in {email: ****}
// Sensitive value is masked
logs.WithContext("creditCard", "4532-1234-5678-9012").
WithContext("amount", 99.99).
Info("Payment processed")
// Logged as: Payment processed {creditCard: ****, amount: 99.99}
// Multiple sensitive values
logs.WithContext("username", "john_doe").
WithContext("password", "SecurePass123").
WithContext("token", "eyJhbGc...").
Warn("Authentication failed")
// Logged as: Authentication failed {username: john_doe, password: ****, token: ****}Configuration Examples
Startup Configuration
Go
func init() {
// Register common sensitive patterns
setupSensitiveKeyConfiguration()
}
func setupSensitiveKeyConfiguration() {
// User authentication
logs.AddSensitiveKey("password")
logs.AddSensitiveKey("pwd")
logs.AddSensitiveKey("passwd")
// Tokens and keys
logs.AddSensitiveKey("token")
logs.AddSensitiveKey("apiKey")
logs.AddSensitiveKey("api_key")
logs.AddSensitiveKey("secretKey")
logs.AddSensitiveKey("secret")
logs.AddSensitiveKey("jwt")
logs.AddSensitiveKey("bearer")
logs.AddSensitiveKey("authorization")
// Personal identifiable information (PII)
logs.AddSensitiveKey("email")
logs.AddSensitiveKey("phoneNumber")
logs.AddSensitiveKey("phone")
logs.AddSensitiveKey("ssn")
logs.AddSensitiveKey("socialSecurityNumber")
logs.AddSensitiveKey("driverLicense")
logs.AddSensitiveKey("passport")
// Payment information
logs.AddSensitiveKey("creditCard")
logs.AddSensitiveKey("cardNumber")
logs.AddSensitiveKey("cvv")
logs.AddSensitiveKey("bankAccount")
logs.AddSensitiveKey("routingNumber")
}func init() {
// Register common sensitive patterns
setupSensitiveKeyConfiguration()
}
func setupSensitiveKeyConfiguration() {
// User authentication
logs.AddSensitiveKey("password")
logs.AddSensitiveKey("pwd")
logs.AddSensitiveKey("passwd")
// Tokens and keys
logs.AddSensitiveKey("token")
logs.AddSensitiveKey("apiKey")
logs.AddSensitiveKey("api_key")
logs.AddSensitiveKey("secretKey")
logs.AddSensitiveKey("secret")
logs.AddSensitiveKey("jwt")
logs.AddSensitiveKey("bearer")
logs.AddSensitiveKey("authorization")
// Personal identifiable information (PII)
logs.AddSensitiveKey("email")
logs.AddSensitiveKey("phoneNumber")
logs.AddSensitiveKey("phone")
logs.AddSensitiveKey("ssn")
logs.AddSensitiveKey("socialSecurityNumber")
logs.AddSensitiveKey("driverLicense")
logs.AddSensitiveKey("passport")
// Payment information
logs.AddSensitiveKey("creditCard")
logs.AddSensitiveKey("cardNumber")
logs.AddSensitiveKey("cvv")
logs.AddSensitiveKey("bankAccount")
logs.AddSensitiveKey("routingNumber")
}Practical Patterns
User Authentication
Go
type AuthService struct {
userRepo UserRepository
}
func (s *AuthService) Authenticate(email, password string) (*User, error) {
logs.WithContext("email", email).
Debug("Attempting user authentication")
// Logged as: {email: ****}
user, err := s.userRepo.GetByEmail(email)
if err != nil {
logs.WithContext("email", email).
WithContext("error", err.Error()).
Warn("User not found")
return nil, fmt.Errorf("authentication failed")
}
// Verify password
if !verifyPassword(password, user.PasswordHash) {
logs.WithContext("email", email).
Warn("Invalid password")
return nil, fmt.Errorf("authentication failed")
}
logs.WithContext("email", email).
WithContext("userId", user.ID).
Info("User authenticated successfully")
return user, nil
}type AuthService struct {
userRepo UserRepository
}
func (s *AuthService) Authenticate(email, password string) (*User, error) {
logs.WithContext("email", email).
Debug("Attempting user authentication")
// Logged as: {email: ****}
user, err := s.userRepo.GetByEmail(email)
if err != nil {
logs.WithContext("email", email).
WithContext("error", err.Error()).
Warn("User not found")
return nil, fmt.Errorf("authentication failed")
}
// Verify password
if !verifyPassword(password, user.PasswordHash) {
logs.WithContext("email", email).
Warn("Invalid password")
return nil, fmt.Errorf("authentication failed")
}
logs.WithContext("email", email).
WithContext("userId", user.ID).
Info("User authenticated successfully")
return user, nil
}API Key Management
Go
type APIKeyService struct {
repo APIKeyRepository
}
func (s *APIKeyService) CreateAPIKey(ctx context.Context, userId string) (string, error) {
logs.WithContext("userId", userId).
Debug("Creating API key")
apiKey := generateSecureKey()
hashedKey := hashKey(apiKey)
err := s.repo.Save(&APIKey{
UserID: userId,
KeyHash: hashedKey,
CreatedAt: time.Now(),
})
if err != nil {
logs.WithContext("userId", userId).
WithContext("apiKey", apiKey).
Error("Failed to save API key", err)
// Logged as: {userId: ..., apiKey: ****}
return "", err
}
logs.WithContext("userId", userId).
Info("API key created successfully")
return apiKey, nil
}
func (s *APIKeyService) ValidateAPIKey(apiKey string) (string, error) {
logs.WithContext("apiKey", apiKey).
Trace("Validating API key")
// Logged as: {apiKey: ****}
hashedKey := hashKey(apiKey)
keyRecord, err := s.repo.GetByHash(hashedKey)
if err != nil {
logs.WithContext("apiKey", apiKey).
Debug("API key not found")
return "", fmt.Errorf("invalid key")
}
if time.Now().After(keyRecord.ExpiresAt) {
logs.WithContext("apiKey", apiKey).
Warn("API key expired")
return "", fmt.Errorf("key expired")
}
logs.WithContext("userId", keyRecord.UserID).
Debug("API key validated successfully")
return keyRecord.UserID, nil
}type APIKeyService struct {
repo APIKeyRepository
}
func (s *APIKeyService) CreateAPIKey(ctx context.Context, userId string) (string, error) {
logs.WithContext("userId", userId).
Debug("Creating API key")
apiKey := generateSecureKey()
hashedKey := hashKey(apiKey)
err := s.repo.Save(&APIKey{
UserID: userId,
KeyHash: hashedKey,
CreatedAt: time.Now(),
})
if err != nil {
logs.WithContext("userId", userId).
WithContext("apiKey", apiKey).
Error("Failed to save API key", err)
// Logged as: {userId: ..., apiKey: ****}
return "", err
}
logs.WithContext("userId", userId).
Info("API key created successfully")
return apiKey, nil
}
func (s *APIKeyService) ValidateAPIKey(apiKey string) (string, error) {
logs.WithContext("apiKey", apiKey).
Trace("Validating API key")
// Logged as: {apiKey: ****}
hashedKey := hashKey(apiKey)
keyRecord, err := s.repo.GetByHash(hashedKey)
if err != nil {
logs.WithContext("apiKey", apiKey).
Debug("API key not found")
return "", fmt.Errorf("invalid key")
}
if time.Now().After(keyRecord.ExpiresAt) {
logs.WithContext("apiKey", apiKey).
Warn("API key expired")
return "", fmt.Errorf("key expired")
}
logs.WithContext("userId", keyRecord.UserID).
Debug("API key validated successfully")
return keyRecord.UserID, nil
}Payment Processing
Go
type PaymentProcessor struct {
gateway PaymentGateway
}
func (p *PaymentProcessor) ProcessPayment(ctx context.Context, payment *Payment) error {
logs.WithContext("amount", payment.Amount).
WithContext("currency", payment.Currency).
WithContext("cardNumber", payment.CardNumber).
WithContext("cardholderName", payment.CardholderName).
Debug("Processing payment")
// Logged as: {amount: ..., currency: ..., cardNumber: ****, cardholderName: ...}
// Call payment gateway
result, err := p.gateway.Charge(&GatewayRequest{
Amount: payment.Amount,
CardToken: payment.CardToken,
Currency: payment.Currency,
})
if err != nil {
logs.WithContext("amount", payment.Amount).
WithContext("cardNumber", payment.CardNumber).
WithContext("error", err.Error()).
Error("Payment processing failed", err)
return err
}
logs.WithContext("amount", payment.Amount).
WithContext("transactionId", result.ID).
Info("Payment processed successfully")
return nil
}type PaymentProcessor struct {
gateway PaymentGateway
}
func (p *PaymentProcessor) ProcessPayment(ctx context.Context, payment *Payment) error {
logs.WithContext("amount", payment.Amount).
WithContext("currency", payment.Currency).
WithContext("cardNumber", payment.CardNumber).
WithContext("cardholderName", payment.CardholderName).
Debug("Processing payment")
// Logged as: {amount: ..., currency: ..., cardNumber: ****, cardholderName: ...}
// Call payment gateway
result, err := p.gateway.Charge(&GatewayRequest{
Amount: payment.Amount,
CardToken: payment.CardToken,
Currency: payment.Currency,
})
if err != nil {
logs.WithContext("amount", payment.Amount).
WithContext("cardNumber", payment.CardNumber).
WithContext("error", err.Error()).
Error("Payment processing failed", err)
return err
}
logs.WithContext("amount", payment.Amount).
WithContext("transactionId", result.ID).
Info("Payment processed successfully")
return nil
}Configuration Management
Go
type ConfigService struct {
store ConfigStore
}
func (s *ConfigService) SetConfig(key string, value interface{}) error {
logs.WithContext("key", key).
WithContext("value", value).
Debug("Updating configuration")
// Logged as: {key: ..., value: **** if key is sensitive}
err := s.store.Set(key, value)
if err != nil {
logs.WithContext("key", key).
WithContext("value", value).
Error("Failed to update configuration", err)
return err
}
logs.WithContext("key", key).
Info("Configuration updated successfully")
return nil
}
func (s *ConfigService) GetConfig(key string) (interface{}, error) {
logs.WithContext("key", key).
Trace("Retrieving configuration")
value, err := s.store.Get(key)
if err != nil {
logs.WithContext("key", key).
Error("Failed to retrieve configuration", err)
return nil, err
}
logs.WithContext("key", key).
Trace("Configuration retrieved")
return value, nil
}type ConfigService struct {
store ConfigStore
}
func (s *ConfigService) SetConfig(key string, value interface{}) error {
logs.WithContext("key", key).
WithContext("value", value).
Debug("Updating configuration")
// Logged as: {key: ..., value: **** if key is sensitive}
err := s.store.Set(key, value)
if err != nil {
logs.WithContext("key", key).
WithContext("value", value).
Error("Failed to update configuration", err)
return err
}
logs.WithContext("key", key).
Info("Configuration updated successfully")
return nil
}
func (s *ConfigService) GetConfig(key string) (interface{}, error) {
logs.WithContext("key", key).
Trace("Retrieving configuration")
value, err := s.store.Get(key)
if err != nil {
logs.WithContext("key", key).
Error("Failed to retrieve configuration", err)
return nil, err
}
logs.WithContext("key", key).
Trace("Configuration retrieved")
return value, nil
}Data Masking Patterns
Consistent Key Naming
Go
// Use consistent naming across your application
// All password-related fields
logs.AddSensitiveKey("password")
logs.AddSensitiveKey("newPassword")
logs.AddSensitiveKey("oldPassword")
logs.AddSensitiveKey("confirmPassword")
// All token-related fields
logs.AddSensitiveKey("token")
logs.AddSensitiveKey("accessToken")
logs.AddSensitiveKey("refreshToken")
logs.AddSensitiveKey("bearerToken")
// All credential fields
logs.AddSensitiveKey("credentials")
logs.AddSensitiveKey("secret")
logs.AddSensitiveKey("key")// Use consistent naming across your application
// All password-related fields
logs.AddSensitiveKey("password")
logs.AddSensitiveKey("newPassword")
logs.AddSensitiveKey("oldPassword")
logs.AddSensitiveKey("confirmPassword")
// All token-related fields
logs.AddSensitiveKey("token")
logs.AddSensitiveKey("accessToken")
logs.AddSensitiveKey("refreshToken")
logs.AddSensitiveKey("bearerToken")
// All credential fields
logs.AddSensitiveKey("credentials")
logs.AddSensitiveKey("secret")
logs.AddSensitiveKey("key")Best Practices
Data Masking Best Practices
- Configure at startup - register all sensitive keys during initialization
- Use consistent naming - standardize sensitive field names across your app
- Be comprehensive - include all sensitive data types (auth, PII, payment, etc.)
- Don't log sensitive data directly - always use context with registered keys
- Review periodically - audit logs to ensure sensitive data isn't exposed
- Team documentation - document which keys are sensitive in your codebase
- Test masking - verify sensitive data is masked in log output
Compliance Considerations
Data masking helps meet compliance requirements like GDPR, HIPAA, and PCI-DSS. Always ensure sensitive data is masked before logs leave your system.