96 lines
2.9 KiB
Go
96 lines
2.9 KiB
Go
// Package memutil provides utilities for secure memory handling.
|
|
// These utilities help prevent sensitive data from remaining in memory
|
|
// after use, protecting against memory dump attacks.
|
|
package memutil
|
|
|
|
import (
|
|
"crypto/subtle"
|
|
|
|
"github.com/awnumar/memguard"
|
|
|
|
sbytes "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/security/securebytes"
|
|
sstring "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/security/securestring"
|
|
)
|
|
|
|
// WipeString overwrites a string's backing array with zeros and clears the string.
|
|
// Note: This only works if the string variable is the only reference to the data.
|
|
// For better security, use SecureString instead of plain strings for sensitive data.
|
|
func WipeString(s *string) {
|
|
if s == nil || *s == "" {
|
|
return
|
|
}
|
|
// Convert to byte slice and wipe
|
|
// Note: This creates a copy, but we wipe what we can
|
|
bytes := []byte(*s)
|
|
memguard.WipeBytes(bytes)
|
|
*s = ""
|
|
}
|
|
|
|
// SecureCompareStrings performs constant-time comparison of two strings.
|
|
// This prevents timing attacks when comparing secrets.
|
|
func SecureCompareStrings(a, b string) bool {
|
|
return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1
|
|
}
|
|
|
|
// SecureCompareBytes performs constant-time comparison of two byte slices.
|
|
// If wipeAfter is true, both slices are wiped after comparison.
|
|
func SecureCompareBytes(a, b []byte, wipeAfter bool) bool {
|
|
if wipeAfter {
|
|
defer memguard.WipeBytes(a)
|
|
defer memguard.WipeBytes(b)
|
|
}
|
|
return subtle.ConstantTimeCompare(a, b) == 1
|
|
}
|
|
|
|
// WithSecureBytes executes a function with secure byte handling.
|
|
// The bytes are automatically wiped after the function returns.
|
|
func WithSecureBytes(data []byte, fn func([]byte) error) error {
|
|
defer memguard.WipeBytes(data)
|
|
return fn(data)
|
|
}
|
|
|
|
// WithSecureString executes a function with secure string handling.
|
|
// The SecureString is automatically wiped after the function returns.
|
|
func WithSecureString(str string, fn func(*sstring.SecureString) error) error {
|
|
secure, err := sstring.NewSecureString(str)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer secure.Wipe()
|
|
return fn(secure)
|
|
}
|
|
|
|
// CloneAndWipe creates a copy of data and wipes the original.
|
|
// Useful when you need to pass data to a function that will store it,
|
|
// but want to ensure the original is wiped.
|
|
func CloneAndWipe(data []byte) []byte {
|
|
if data == nil {
|
|
return nil
|
|
}
|
|
clone := make([]byte, len(data))
|
|
copy(clone, data)
|
|
memguard.WipeBytes(data)
|
|
return clone
|
|
}
|
|
|
|
// SecureZero overwrites memory with zeros.
|
|
// This is a convenience wrapper around memguard.WipeBytes.
|
|
func SecureZero(data []byte) {
|
|
memguard.WipeBytes(data)
|
|
}
|
|
|
|
// WipeSecureString wipes a SecureString if it's not nil.
|
|
// This is a nil-safe convenience wrapper.
|
|
func WipeSecureString(s *sstring.SecureString) {
|
|
if s != nil {
|
|
s.Wipe()
|
|
}
|
|
}
|
|
|
|
// WipeSecureBytes wipes a SecureBytes if it's not nil.
|
|
// This is a nil-safe convenience wrapper.
|
|
func WipeSecureBytes(s *sbytes.SecureBytes) {
|
|
if s != nil {
|
|
s.Wipe()
|
|
}
|
|
}
|