Password Protection
SkySend supports optional password protection using Argon2id (WASM, memory-hard, GPU-resistant).
How It Works
Password protection adds an extra layer on top of the encryption secret. The secret is XOR'd with a password-derived key, making it unrecoverable without the password.
Upload: protectedSecret = secret XOR passwordKey
Download: secret = protectedSecret XOR passwordKeyThe XOR operation is reversible, so the original secret can be recovered by applying the same password key.
Key Derivation Function
Argon2id
Argon2id is a memory-hard KDF that is resistant to GPU and ASIC attacks. SkySend uses it via a WASM implementation in the browser.
| Parameter | Value |
|---|---|
| Memory | 65,536 KiB (64 MiB) |
| Iterations | 3 |
| Parallelism | 1 |
| Hash Length | 32 bytes |
These parameters follow the OWASP strong recommendation for Argon2id.
typescript
const { key, algorithm } = await deriveKeyFromPassword(password, salt, argon2id)
// algorithm = "argon2id-v2"Password Salt
A 16-byte random salt is generated per upload:
typescript
const passwordSalt = randomBytes(16) // PASSWORD_SALT_LENGTH = 16The salt and the algorithm identifier are stored on the server so that the downloader can derive the same password key.
Upload Flow
- User sets a password during upload
- Client generates a password salt
- Client derives
passwordKeyfrom the password - Client computes
protectedSecret = secret XOR passwordKey - Client sends
X-Has-Password: true,X-Password-Salt, andX-Password-Algoheaders - The share link now contains the
protectedSecretinstead of the raw secret
Download Flow
- Client fetches upload info, sees
hasPassword: truewithpasswordAlgoandpasswordSalt - User enters the password
- Client derives
passwordKeyusing the stored algorithm and salt - Client recovers
secret = protectedSecret XOR passwordKey - Client derives keys and computes
authToken - Client verifies the password via
POST /api/password/:idwith the derived auth token - If the token matches, the password is correct and the download proceeds
Constants
| Constant | Value |
|---|---|
PASSWORD_SALT_LENGTH | 16 bytes |
DERIVED_KEY_LENGTH | 32 bytes |
ARGON2_PARAMS.memory | 65,536 KiB |
ARGON2_PARAMS.iterations | 3 |
ARGON2_PARAMS.parallelism | 1 |
ARGON2_PARAMS.hashLength | 32 bytes |
Security Considerations
- Unique salt per upload - Prevents rainbow table attacks
- Memory-hard KDF - Argon2id is resistant to GPU/ASIC brute-force
- Server never sees the password - Only verifies the derived auth token
- UTF-8 encoding - Passwords are consistently encoded as UTF-8 before hashing