crypto

package
v0.0.0-...-31b1c06 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 11 Imported by: 0

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

View Source
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

View Source
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

func ComputeMagic(repoID string, derivedKey []byte) string

ComputeMagic computes the magic token for password verification. The magic token is HMAC-SHA256(derived_key, repo_id) for better security.

func ComputeMagicSeafile

func ComputeMagicSeafile(password string, repoID string, salt []byte, version int) string

ComputeMagicSeafile computes the Seafile-compatible magic token. Seafile just uses the derived key directly as the magic (not ideal, but compatible).

func DecryptBlock

func DecryptBlock(encrypted []byte, fileKey []byte) ([]byte, error)

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

func DecryptBlockSeafile(ciphertext []byte, fileKey []byte, fileIV []byte) ([]byte, error)

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

func DecryptFileKey(encryptedHex string, derivedKey []byte, iv []byte) ([]byte, error)

DecryptFileKey decrypts the file key using AES-256-CBC. Takes hex-encoded ciphertext, returns raw file key.

func DecryptLibraryBlock

func DecryptLibraryBlock(encrypted []byte, fileKey []byte, fileIV []byte) ([]byte, error)

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

func DeriveEncryptionKeyPBKDF2(password string, salt []byte, version int) (key []byte, iv []byte)

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

func DeriveFileEncryptionKey(secretKey []byte, version int) (key []byte, iv []byte)

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:

  1. Key = PBKDF2(secretKey, salt, 1000 iterations, 32 bytes)
  2. IV = PBKDF2(key, salt, 10 iterations, 16 bytes)

func DeriveKeyArgon2id

func DeriveKeyArgon2id(password string, repoID string, salt []byte) (key []byte, iv []byte)

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:

  1. Key = PBKDF2(repo_id + password, salt, 1000 iterations, 32 bytes)
  2. IV = PBKDF2(key, salt, 10 iterations, 16 bytes)

func EncryptBlock

func EncryptBlock(plaintext []byte, fileKey []byte) ([]byte, error)

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

func EncryptBlockSeafile(plaintext []byte, fileKey []byte, fileIV []byte) ([]byte, error)

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

func EncryptFileKey(fileKey []byte, derivedKey []byte, iv []byte) (string, error)

EncryptFileKey encrypts the file key with the derived key using AES-256-CBC. Returns hex-encoded ciphertext.

func GenerateFileKey

func GenerateFileKey() ([]byte, error)

GenerateFileKey creates a cryptographically random 32-byte file encryption key

func GenerateSalt

func GenerateSalt() ([]byte, error)

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

func VerifyPassword(computedMagic, storedMagic string) bool

VerifyPassword checks if a password is correct by comparing magic tokens. Uses constant-time comparison to prevent timing attacks.

func VerifyPasswordSeafile

func VerifyPasswordSeafile(password, repoID, storedMagic string, salt []byte, version int) bool

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

func VerifyPasswordStrong(password, repoID, storedMagicStrong string, salt []byte) bool

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL