- AGE encryption with master password model - Core commands: init, show, insert, edit, generate, rm, mv, cp, find, grep, ls - Git integration for version control - Clipboard support (X11 and Wayland) - Secure password generation - Backup and restore functionality - Comprehensive security features - Complete documentation
69 lines
1.7 KiB
Go
69 lines
1.7 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"unsafe"
|
|
)
|
|
|
|
// SecureBytes wraps a byte slice and provides secure clearing
|
|
// Because Go strings are immutable and we can't really clear them, this helps
|
|
type SecureBytes struct {
|
|
data []byte
|
|
}
|
|
|
|
// NewSecureBytes creates a new SecureBytes from a byte slice
|
|
func NewSecureBytes(data []byte) *SecureBytes {
|
|
return &SecureBytes{data: data}
|
|
}
|
|
|
|
// Bytes returns the underlying byte slice
|
|
func (sb *SecureBytes) Bytes() []byte {
|
|
return sb.data
|
|
}
|
|
|
|
// String returns the string representation (use with caution)
|
|
// This uses unsafe.Pointer magic - don't look too closely, it works
|
|
func (sb *SecureBytes) String() string {
|
|
return *(*string)(unsafe.Pointer(&sb.data))
|
|
}
|
|
|
|
// Clear securely zeros the memory
|
|
// Overwrites with random junk first (defense in depth), then zeros
|
|
// Not perfect (Go GC might move things around), but better than nothing
|
|
func (sb *SecureBytes) Clear() {
|
|
if sb == nil || sb.data == nil {
|
|
return
|
|
}
|
|
// Fill with random data first - makes memory dumps less useful
|
|
rand.Read(sb.data)
|
|
// Then zero it out
|
|
for i := range sb.data {
|
|
sb.data[i] = 0
|
|
}
|
|
sb.data = nil
|
|
}
|
|
|
|
// ClearBytes securely clears a byte slice
|
|
func ClearBytes(data []byte) {
|
|
if data == nil {
|
|
return
|
|
}
|
|
// Overwrite with random data first, then zeros
|
|
rand.Read(data)
|
|
for i := range data {
|
|
data[i] = 0
|
|
}
|
|
}
|
|
|
|
// ClearString attempts to clear a string (limited effectiveness in Go)
|
|
// Go strings are immutable, so this is mostly wishful thinking
|
|
// But hey, at least we tried
|
|
func ClearString(s *string) {
|
|
if s == nil {
|
|
return
|
|
}
|
|
// Best we can do - just set it to empty
|
|
// The original memory might still be around somewhere, but GC will get it eventually
|
|
*s = ""
|
|
}
|