Security
articwake is designed with security in mind. This page covers the security features and recommended practices.
Security Features
Section titled “Security Features”PIN Hashing
Section titled “PIN Hashing”PINs are never stored in plaintext. articwake uses Argon2id, the winner of the Password Hashing Competition:
- Memory-hard (resistant to GPU attacks)
- Configurable parameters
- Random salt per hash
# Generate a hashecho -n "your-pin" | articwake hash-pinSession Tokens
Section titled “Session Tokens”After successful authentication:
- Format: 32 random bytes (64 hex characters)
- Generation: Cryptographically secure random number generator
- Expiry: 15 minutes from creation
- Storage: In-memory only (cleared on restart)
Rate Limiting
Section titled “Rate Limiting”Brute-force protection on the /api/auth endpoint:
- Limit: 10 attempts per minute per IP
- Window: Sliding 60-second window
- Scope: Per IP address
- Response:
429 Too Many Requests
Network Binding
Section titled “Network Binding”By default, articwake binds to 127.0.0.1 (localhost only):
- Not accessible from the network
- Must be explicitly configured to listen on other interfaces
- Recommended: Expose via Tailscale VPN
Security Best Practices
Section titled “Security Best Practices”Use Tailscale
Section titled “Use Tailscale”Instead of exposing articwake directly to the internet:
- Keep the default
127.0.0.1binding - Install Tailscale on the Pi
- Access via Tailscale IP/hostname
Benefits:
- End-to-end encryption
- No open ports on your network
- Identity-based access control
Strong PIN
Section titled “Strong PIN”Choose a PIN that is:
- At least 6 characters
- Not easily guessable (not
1234or0000) - Unique to articwake
The rate limiting helps, but a strong PIN is your first defense.
Protect the SSH Key
Section titled “Protect the SSH Key”The SSH private key is sensitive:
# Correct permissionschmod 600 /etc/secrets/articwake-keychown root:root /etc/secrets/articwake-keyAnyone with this key can unlock your LUKS-encrypted server.
Secure the Pi
Section titled “Secure the Pi”The Raspberry Pi running articwake should be:
- Physically secured (not easily accessible)
- On a trusted network segment
- Kept updated with security patches
First-Boot Security
Section titled “First-Boot Security”The SD card image implements secure first-boot handling:
- PIN file is read and hashed
- Original plaintext PIN is securely deleted
- SSH key is moved to secure location
- Tailscale auth key is deleted after use
Threat Model
Section titled “Threat Model”Protected Against
Section titled “Protected Against”- Brute-force attacks: Rate limiting + Argon2
- Token theft: Short expiry (15 min)
- Network sniffing: Use Tailscale for encryption
- PIN file exposure: Deleted after first boot
Not Protected Against
Section titled “Not Protected Against”- Physical access: Someone with physical access to the Pi
- Compromised network: If attacker is on your Tailscale network
- Key theft: If SSH key is stolen
- Client-side attacks: Keyloggers, compromised browsers
Trust Boundaries
Section titled “Trust Boundaries”articwake trusts:
- The local Pi filesystem
- The configured SSH key
- The Tailscale network (if used)
- Dropbear in the server’s initrd
Security Constants
Section titled “Security Constants”From the source code (src/auth.rs):
| Constant | Value | Purpose |
|---|---|---|
TOKEN_EXPIRY | 15 minutes | Session token lifetime |
RATE_LIMIT_WINDOW | 60 seconds | Rate limit time window |
MAX_ATTEMPTS_PER_WINDOW | 10 | Max auth attempts per IP |
From src/api/unlock.rs:
| Constant | Value | Purpose |
|---|---|---|
MAX_PASSPHRASE_LEN | 1024 | Max LUKS passphrase length |
Passphrase Handling
Section titled “Passphrase Handling”The LUKS passphrase:
- Is never stored by articwake
- Is validated for dangerous characters
- Is transmitted over SSH (encrypted)
- Is sent to
cryptsetup-askpassvia stdin
Control characters are blocked to prevent shell injection:
- Null bytes
- Newlines
- Tabs
- Escape sequences
Audit Logging
Section titled “Audit Logging”articwake logs authentication events:
INFO articwake::api::auth: Authentication attempt ip=192.168.1.100INFO articwake::api::auth: Authentication successfulWARN articwake::api::auth: Authentication failed ip=192.168.1.100WARN articwake::api::auth: Rate limited ip=192.168.1.100Review logs at /var/log/articwake.log on the SD card image.
Reporting Security Issues
Section titled “Reporting Security Issues”If you discover a security vulnerability, please report it responsibly:
- Do not open a public GitHub issue
- Email the maintainer directly
- Allow time for a fix before disclosure
See the repository for contact information.