Documentation
¶
Overview ¶
Package crypto provides encryption support for SesameFS encrypted libraries. It implements a dual-mode system:
- Compat mode: PBKDF2-SHA256 (for Seafile desktop/mobile client compatibility)
- Strong mode: Argon2id (for web/API clients with modern security)
This mirrors the SHA-1→SHA-256 translation we do for block storage: Seafile clients use weak encryption, but we add server-side protection.
Index ¶
- Constants
- func ComputeMagic(repoID string, derivedKey []byte) string
- func ComputeMagicSeafile(password string, repoID string, salt []byte, version int) string
- func DecryptBlock(encrypted []byte, fileKey []byte) ([]byte, error)
- func DecryptBlockSeafile(ciphertext []byte, fileKey []byte, fileIV []byte) ([]byte, error)
- func DecryptFileKey(encryptedHex string, derivedKey []byte, iv []byte) ([]byte, error)
- func DecryptLibraryBlock(encrypted []byte, fileKey []byte, fileIV []byte) ([]byte, error)
- func DeriveEncryptionKeyPBKDF2(password string, salt []byte, version int) (key []byte, iv []byte)
- func DeriveFileEncryptionKey(secretKey []byte, version int) (key []byte, iv []byte)
- func DeriveKeyArgon2id(password string, repoID string, salt []byte) (key []byte, iv []byte)
- func DeriveKeyPBKDF2(password string, repoID string, salt []byte, version int) (key []byte, iv []byte)
- func EncryptBlock(plaintext []byte, fileKey []byte) ([]byte, error)
- func EncryptBlockSeafile(plaintext []byte, fileKey []byte, fileIV []byte) ([]byte, error)
- func EncryptFileKey(fileKey []byte, derivedKey []byte, iv []byte) (string, error)
- func GenerateFileKey() ([]byte, error)
- func GenerateSalt() ([]byte, error)
- func GetFileKeyAndIVFromPassword(password, repoID string, salt []byte, randomKey string, version int) ([]byte, []byte, error)
- func GetFileKeyFromPassword(password, repoID string, salt []byte, randomKey string, version int) ([]byte, error)
- func VerifyPassword(computedMagic, storedMagic string) bool
- func VerifyPasswordSeafile(password, repoID, storedMagic string, salt []byte, version int) bool
- func VerifyPasswordStrong(password, repoID, storedMagicStrong string, salt []byte) bool
- type EncryptionParams
Constants ¶
const ( // EncVersionSeafileV2 is the standard Seafile encryption (weak PBKDF2) EncVersionSeafileV2 = 2 // EncVersionSeafileV4 is Seafile with per-repo salt EncVersionSeafileV4 = 4 // EncVersionSesameFS is our strong Argon2id encryption (web/API only) EncVersionSesameFS = 10 // EncVersionDual is dual-mode: stores both weak (compat) and strong (security) EncVersionDual = 12 )
Encryption versions
const ( SaltSize = 32 // 256-bit random salt per library FileKeySize = 32 // 256-bit file encryption key IVSize = 16 // 128-bit IV for AES-CBC )
Salt and key sizes
Variables ¶
This section is empty.
Functions ¶
func ComputeMagic ¶
ComputeMagic computes the magic token for password verification. The magic token is HMAC-SHA256(derived_key, repo_id) for better security.
func ComputeMagicSeafile ¶
ComputeMagicSeafile computes the Seafile-compatible magic token. Seafile just uses the derived key directly as the magic (not ideal, but compatible).
func DecryptBlock ¶
DecryptBlock decrypts a block of file content using AES-256-CBC. Expects Seafile format: 16-byte IV prepended to ciphertext. If the block doesn't appear to be encrypted (wrong size), it returns the data as-is. This handles legacy blocks that were stored before encryption was implemented.
func DecryptBlockSeafile ¶
DecryptBlockSeafile decrypts a block of file content using AES-256-CBC with a derived IV. This is the Seafile v2 compatible format: NO prepended IV (IV is derived from password). Use this for files in encrypted libraries that were synced with Seafile clients.
func DecryptFileKey ¶
DecryptFileKey decrypts the file key using AES-256-CBC. Takes hex-encoded ciphertext, returns raw file key.
func DecryptLibraryBlock ¶
DecryptLibraryBlock decrypts an encrypted library block.
When the library IV is available, the block must be in the current Seafile-compatible derived-IV format. Callers without a library IV fall back to the legacy/random-IV reader for older or unencrypted blocks.
func DeriveEncryptionKeyPBKDF2 ¶
DeriveEncryptionKeyPBKDF2 derives a key for encrypting/decrypting the random_key. CRITICAL: This uses PASSWORD ONLY as input (NOT repo_id + password). This is different from DeriveKeyPBKDF2 which is used for magic generation. From seafile-crypt.c: seafile_generate_random_key uses passwd alone.
func DeriveFileEncryptionKey ¶
DeriveFileEncryptionKey derives the final file encryption key and IV from the secret key. Seafile does a SECOND PBKDF2 derivation on the decrypted random_key to get the actual key and IV used for file encryption. This function implements that second derivation. secretKey is the 32-byte key obtained by decrypting random_key. CRITICAL: Uses the same two-step derivation as DeriveKeyPBKDF2:
- Key = PBKDF2(secretKey, salt, 1000 iterations, 32 bytes)
- IV = PBKDF2(key, salt, 10 iterations, 16 bytes)
func DeriveKeyArgon2id ¶
DeriveKeyArgon2id derives a key using Argon2id (strong, memory-hard) This is our preferred method for web/API clients.
func DeriveKeyPBKDF2 ¶
func DeriveKeyPBKDF2(password string, repoID string, salt []byte, version int) (key []byte, iv []byte)
DeriveKeyPBKDF2 derives a key using PBKDF2-HMAC-SHA256 (Seafile v2 compatible) This is used for MAGIC generation (password verification). CRITICAL: Magic uses repo_id + password as input. Uses TWO separate PBKDF2 calls:
- Key = PBKDF2(repo_id + password, salt, 1000 iterations, 32 bytes)
- IV = PBKDF2(key, salt, 10 iterations, 16 bytes)
func EncryptBlock ¶
EncryptBlock encrypts a block of file content using AES-256-CBC. Uses random IV prepended to ciphertext format. NOTE: For Seafile v2 client compatibility, use EncryptBlockSeafile instead.
func EncryptBlockSeafile ¶
EncryptBlockSeafile encrypts a block of file content using AES-256-CBC with a derived IV. This is the Seafile v2 compatible format: NO prepended IV (IV is derived from password). Use this for files in encrypted libraries that will be synced with Seafile clients.
func EncryptFileKey ¶
EncryptFileKey encrypts the file key with the derived key using AES-256-CBC. Returns hex-encoded ciphertext.
func GenerateFileKey ¶
GenerateFileKey creates a cryptographically random 32-byte file encryption key
func GenerateSalt ¶
GenerateSalt creates a cryptographically random 32-byte salt
func GetFileKeyAndIVFromPassword ¶
func GetFileKeyAndIVFromPassword(password, repoID string, salt []byte, randomKey string, version int) ([]byte, []byte, error)
GetFileKeyAndIVFromPassword derives both the file key AND IV from a password. For Seafile v2 encrypted libraries, the IV is derived (not random per-block). Returns: (32-byte key, 16-byte IV, error)
func GetFileKeyFromPassword ¶
func GetFileKeyFromPassword(password, repoID string, salt []byte, randomKey string, version int) ([]byte, error)
GetFileKeyFromPassword derives the file key from a password for an encrypted library. This decrypts the random_key using the password-derived key, then performs a SECOND PBKDF2 derivation to get the final file encryption key (as required by Seafile protocol).
CRITICAL: random_key encryption uses PASSWORD ONLY (not repo_id + password). This is different from magic which uses repo_id + password.
func VerifyPassword ¶
VerifyPassword checks if a password is correct by comparing magic tokens. Uses constant-time comparison to prevent timing attacks.
func VerifyPasswordSeafile ¶
VerifyPasswordSeafile verifies a password using Seafile-compatible PBKDF2. Use this for Seafile desktop/mobile clients. NOTE: For dual-mode (v12) libraries, the Seafile magic is computed with repo_id-derived salt, so we pass nil salt and EncVersionSeafileV2 to use the correct algorithm.
func VerifyPasswordStrong ¶
VerifyPasswordStrong verifies a password using Argon2id. Use this for web/API clients.
Types ¶
type EncryptionParams ¶
type EncryptionParams struct {
EncVersion int `json:"enc_version"`
Salt string `json:"salt"` // Hex-encoded 32-byte random salt
Magic string `json:"magic"` // PBKDF2-derived (Seafile compat)
MagicStrong string `json:"magic_strong,omitempty"` // Argon2id-derived (SesameFS)
RandomKey string `json:"random_key"` // Encrypted file key (PBKDF2)
RandomKeyStrong string `json:"random_key_strong,omitempty"` // Encrypted file key (Argon2id)
}
EncryptionParams holds the encryption metadata for a library
func ChangePassword ¶
func ChangePassword(oldPassword, newPassword, repoID string, params *EncryptionParams) (*EncryptionParams, error)
ChangePassword re-encrypts the file key with a new password. Returns updated encryption parameters.
func CreateEncryptedLibrary ¶
func CreateEncryptedLibrary(password string, repoID string) (*EncryptionParams, error)
CreateEncryptedLibrary generates all encryption parameters for a new encrypted library. Returns both Seafile-compatible (weak) and SesameFS (strong) parameters.