Documentation
¶
Overview ¶
Package cryptoutil provides secure cryptographic operations.
This package uses only secure, modern cryptographic primitives. Specifically, it uses AES-GCM for authenticated encryption, which provides both confidentiality and integrity protection.
Key Points ¶
- Uses AES-GCM (Galois/Counter Mode) - authenticated encryption
- Keys must be 16, 24, or 32 bytes (AES-128, AES-192, AES-256)
- Nonces are generated automatically using crypto/rand
- Output is base64-encoded for safe transport
Why AES-GCM? ¶
The original library used AES-ECB mode which has serious weaknesses:
- Identical plaintext blocks produce identical ciphertext
- No authentication (ciphertext can be modified undetected)
AES-GCM solves both problems:
- Each message is unique due to random nonce
- Authentication tag prevents tampering
Usage ¶
key := make([]byte, 32) // 256-bit key
rand.Read(key)
ciphertext, err := cryptoutil.Encrypt(plaintext, key)
if err != nil { ... }
plaintext, err := cryptoutil.Decrypt(ciphertext, key)
if err != nil { ... }
Key Management ¶
This package does not handle key management. It is the caller's responsibility to:
- Generate keys securely (use crypto/rand)
- Store keys securely (use secret management systems)
- Rotate keys periodically
Security Considerations ¶
- Never reuse a key with the same nonce
- Use at least 128-bit keys (32 bytes for AES-256)
- Do not use this for password hashing (use bcrypt/argon2)
Index ¶
- Variables
- func CompareHash(data, expectedHash []byte) bool
- func Decrypt(ciphertextB64 string, key []byte) ([]byte, error)
- func DecryptString(ciphertextB64 string, key []byte) (string, error)
- func DeriveKey(password, salt string) []byte
- func Encrypt(plaintext, key []byte) (string, error)
- func EncryptString(plaintext string, key []byte) (string, error)
- func GenerateKey(size int) ([]byte, error)
- func GenerateNonce(size int) ([]byte, error)
- func Hash(data []byte) []byte
- func HashString(s string) string
- func RandomBytes(n int) ([]byte, error)
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidKeySize = errors.New("key must be 16, 24, or 32 bytes") ErrInvalidCiphertext = errors.New("invalid ciphertext") ErrDecryptFailed = errors.New("decryption failed: authentication error") )
Common errors.
Functions ¶
func CompareHash ¶
CompareHash compares a hash with a computed hash of data in constant time. This prevents timing attacks.
func Decrypt ¶
Decrypt decrypts base64-encoded ciphertext using AES-GCM with the given key. Returns ErrDecryptFailed if authentication fails (tampered or wrong key).
Example:
plaintext, err := Decrypt(ciphertext, key)
if errors.Is(err, ErrDecryptFailed) {
// Wrong key or tampered data
}
func DecryptString ¶
DecryptString decrypts base64-encoded ciphertext and returns the plaintext string.
func DeriveKey ¶
DeriveKey derives a key from a password using SHA-256. This is a simple key derivation for non-security-critical applications. For password storage or high-security applications, use argon2 or bcrypt.
Example:
key := DeriveKey("mypassword", "mysalt")
ciphertext, err := Encrypt(data, key)
func Encrypt ¶
Encrypt encrypts plaintext using AES-GCM with the given key. The key must be 16, 24, or 32 bytes (AES-128, AES-192, AES-256). Returns base64-encoded ciphertext containing nonce + encrypted data + auth tag.
Example:
key := make([]byte, 32) // Generate a proper key
io.ReadFull(rand.Reader, key)
ciphertext, err := Encrypt([]byte("secret message"), key)
func EncryptString ¶
EncryptString encrypts a string and returns base64-encoded ciphertext.
func GenerateKey ¶
GenerateKey generates a cryptographically secure random key of the specified size. Size must be 16, 24, or 32 bytes.
Example:
key, err := GenerateKey(32) // AES-256
if err != nil { ... }
func GenerateNonce ¶
GenerateNonce generates a random nonce of the specified size. For AES-GCM, the standard nonce size is 12 bytes.
func HashString ¶
HashString returns the SHA-256 hash of a string as a hex-encoded string.
func RandomBytes ¶
RandomBytes returns n cryptographically secure random bytes.
Types ¶
This section is empty.