Documentation
¶
Index ¶
- Constants
- Variables
- func AesGcmNonceSize() int
- func AesGcmOverhead() int
- func AesGcmTagSize() int
- func CalculateFileHash(data []byte) string
- func CalculateFileHashFromPath(filePath string) (string, error)
- func CreateAAD(shareID, fileID string) []byte
- func CreateEnvelope(keyType string) []byte
- func CreateShareEnvelope(fek, downloadToken []byte, filename string, sizeBytes int64, sha256hex string) ([]byte, error)
- func DecodeBase64(s string) ([]byte, error)
- func DecryptFEK(encryptedFEK []byte, password []byte, username string) ([]byte, string, error)
- func DecryptFile(encryptedData []byte, fek []byte) ([]byte, error)
- func DecryptFileMetadata(filenameNonce, encryptedFilename, sha256Nonce, encryptedSHA256 []byte, ...) (string, string, error)
- func DecryptGCM(data, key []byte) ([]byte, error)
- func DecryptGCMWithAAD(data, key, aad []byte) ([]byte, error)
- func DecryptMetadataWithDerivedKey(derivedKey []byte, nonce, encryptedData []byte) ([]byte, error)
- func DecryptWithNonce(ciphertext, key, nonce []byte) ([]byte, error)
- func DeriveAccountPasswordKey(password []byte, username string) []byte
- func DeriveArgon2IDKey(password, salt []byte, keyLen uint32, memory, time uint32, threads uint8) ([]byte, error)
- func DeriveCustomPasswordKey(password []byte, username string) []byte
- func DeriveJWTSigningMaterial(sessionKey []byte, username string) ([]byte, error)
- func DeriveSessionKey(opaqueExportKey []byte, context string) ([]byte, error)
- func DeriveShareKey(password string, saltBase64 string) ([]byte, error)
- func DeriveTOTPUserKey(username string) ([]byte, error)
- func EncodeBase64(data []byte) string
- func EncryptFEK(fek []byte, password []byte, username, keyType string) ([]byte, error)
- func EncryptFile(data []byte, fek []byte, keyType string) ([]byte, error)
- func EncryptGCM(data, key []byte) ([]byte, error)
- func EncryptGCMWithAAD(data, key, aad []byte) ([]byte, error)
- func EnvelopeHeaderSize() int
- func FormatFileSize(bytes int64) string
- func GenerateAESKey() ([]byte, error)
- func GenerateDownloadToken() ([]byte, error)
- func GenerateFEK() ([]byte, error)
- func GenerateRandomBytes(n int) []byte
- func GenerateShareSalt() (string, error)
- func GenerateTestFileContent(size int64, pattern FilePattern) ([]byte, error)
- func GenerateTestFileToPath(filePath string, size int64, pattern FilePattern) (string, error)
- func GenerateUserKeySalt(username, keyType string) []byte
- func GetEmbeddedArgon2ParamsJSON() []byte
- func GetEmbeddedChunkingParamsJSON() []byte
- func GetEmbeddedPasswordRequirementsJSON() []byte
- func GetTOTPMasterKeyStatus() (bool, int)
- func HashDownloadToken(downloadTokenBase64 string) (string, error)
- func InitKeyManager(db *sql.DB) error
- func InitializeTOTPMasterKey() error
- func KeyTypeForContext(passwordType string) (byte, error)
- func ParseEnvelope(envelope []byte) (version byte, keyType string, err error)
- func ParseSizeString(sizeStr string) (int64, error)
- func PlaintextChunkSize() int64
- func SecureClear(data []byte)
- func SecureCompare(a, b []byte) bool
- func SecureZeroSessionKey(sessionKey []byte)
- func SecureZeroTOTPKey(key []byte)
- func ValidateSessionKey(sessionKey []byte) error
- func VerifyDownloadToken(downloadTokenBase64 string, expectedHashBase64 string) (bool, error)
- func VerifyFileIntegrity(filePath string, expectedHash string, expectedSize int64) error
- type AesGcmParams
- type ChunkInfo
- type ChunkManifest
- type ChunkingParams
- type DecryptedFileMetadata
- type EnvelopeParams
- type FilePattern
- type KeyManager
- func (km *KeyManager) DecryptSystemKey(encryptedKey, nonce []byte, keyType string) ([]byte, error)
- func (km *KeyManager) DeleteKey(keyID string) error
- func (km *KeyManager) EncryptSystemKey(rawKey []byte, keyType string) ([]byte, []byte, error)
- func (km *KeyManager) GetKey(keyID string, keyType string) ([]byte, error)
- func (km *KeyManager) GetOrGenerateKey(keyID string, keyType string, keySize int) ([]byte, error)
- func (km *KeyManager) StoreKey(keyID string, keyType string, rawKey []byte) error
- type KeyTypeMapping
- type PasswordRequirements
- type PasswordValidationResult
- func ValidateAccountPassword(password string) *PasswordValidationResult
- func ValidateCustomPassword(password string) *PasswordValidationResult
- func ValidatePassword(password string, minLength int, maxLength int, minClasses int, ...) *PasswordValidationResult
- func ValidateSharePassword(password string) *PasswordValidationResult
- type RequirementChecks
- type RequirementStatus
- type SessionKeyInfo
- type ShareEnvelope
- type UnifiedArgonProfile
Constants ¶
const ( SessionKeyContext = "ARKFILE_SESSION_KEY" JWTSigningContext = "ARKFILE_JWT_SIGNING" TOTPEncryptionContext = "ARKFILE_TOTP_ENCRYPTION" )
Session key contexts for domain separation
const ( // TOTP key contexts for domain separation TOTPMasterKeyContext = "ARKFILE_TOTP_MASTER_KEY" TOTPUserKeyContext = "ARKFILE_TOTP_USER_KEY" )
const MaxPasswordBytes = 1024
MaxPasswordBytes is the defense-in-depth limit for password inputs to Argon2id. This prevents absurdly long inputs from wasting memory on string allocation. The primary enforcement is in the validation layer (password_validation.go); this is a safety net in case validation is bypassed.
Variables ¶
Memory uint32 Iterations uint32 Parallelism uint8 SaltLength uint32 KeyLength uint32 }{}
ShareKDFParams defines the Argon2id parameters for share key derivation These MUST match the client-side parameters in share-crypto.ts Loaded from crypto/argon2id-params.json
Functions ¶
func AesGcmNonceSize ¶
func AesGcmNonceSize() int
AesGcmNonceSize returns the AES-GCM nonce size in bytes
func AesGcmOverhead ¶
func AesGcmOverhead() int
AesGcmOverhead returns the per-chunk AES-GCM overhead (nonce + tag) in bytes
func AesGcmTagSize ¶
func AesGcmTagSize() int
AesGcmTagSize returns the AES-GCM authentication tag size in bytes
func CalculateFileHash ¶
CalculateFileHash computes SHA-256 hash of file content
func CalculateFileHashFromPath ¶
CalculateFileHashFromPath computes SHA-256 hash of a file on disk
func CreateAAD ¶
CreateAAD creates the Additional Authenticated Data for envelope encryption AAD = share_id + file_id (UTF-8 encoded concatenation) This binds the encrypted envelope to specific share_id and file_id
func CreateEnvelope ¶
CreateEnvelope creates an envelope header for FEK-based encryption keyType: "account" or "custom"
func CreateShareEnvelope ¶
func CreateShareEnvelope(fek, downloadToken []byte, filename string, sizeBytes int64, sha256hex string) ([]byte, error)
CreateShareEnvelope creates a Share Envelope JSON payload with file metadata. The metadata (filename, sizeBytes, sha256) allows share recipients to preview file info before downloading and verify integrity after decryption.
func DecodeBase64 ¶
DecodeBase64 decodes base64 string to bytes
func DecryptFEK ¶
DecryptFEK decrypts a File Encryption Key (FEK) using a key derived from the user's password via Argon2ID. Returns the decrypted FEK and the key type.
func DecryptFile ¶
DecryptFile decrypts file data using a FEK (File Encryption Key)
func DecryptFileMetadata ¶
func DecryptFileMetadata(filenameNonce, encryptedFilename, sha256Nonce, encryptedSHA256 []byte, password string, username string) (string, string, error)
DecryptFileMetadata decrypts encrypted filename and SHA256 metadata using stored password This function works with separate nonce and encrypted data fields as stored in the database The server stores nonces and encrypted data separately, so we need to combine them for DecryptGCM
func DecryptGCM ¶
DecryptGCM decrypts data using AES-256-GCM Expects: nonce + ciphertext + tag (all concatenated)
func DecryptGCMWithAAD ¶
DecryptGCMWithAAD decrypts data using AES-256-GCM with Additional Authenticated Data AAD must match the value used during encryption or decryption will fail Expects: nonce + ciphertext + tag (all concatenated)
func DecryptMetadataWithDerivedKey ¶
DecryptMetadataWithDerivedKey decrypts file metadata using a pre-derived key Expects separate nonce and encrypted data parameters (split from GCM output).
func DecryptWithNonce ¶
DecryptWithNonce decrypts data using AES-256-GCM with a provided nonce This is used when the nonce is stored separately (e.g., in database)
func DeriveAccountPasswordKey ¶
DeriveAccountPasswordKey derives a key from an account password
func DeriveArgon2IDKey ¶
func DeriveArgon2IDKey(password, salt []byte, keyLen uint32, memory, time uint32, threads uint8) ([]byte, error)
DeriveArgon2IDKey derives a key using Argon2ID with specified parameters
func DeriveCustomPasswordKey ¶
DeriveCustomPasswordKey derives a key from a custom file password
func DeriveJWTSigningMaterial ¶
DeriveJWTSigningMaterial derives JWT signing material from session key This provides domain separation for JWT tokens
func DeriveSessionKey ¶
DeriveSessionKey derives a session key from OPAQUE export key with domain separation
func DeriveShareKey ¶
DeriveShareKey derives a 256-bit key from a password and salt using Argon2id. This function is used by the CLI client (cmd/arkfile-client) and tests only. It is NEVER called from server handlers -- all share key derivation for clients happens client-side in TypeScript or Go CLI client utils.
func DeriveTOTPUserKey ¶
DeriveTOTPUserKey derives a user-specific TOTP encryption key from the master key This key remains consistent for the user across all sessions
func EncodeBase64 ¶
EncodeBase64 encodes bytes to base64 string
func EncryptFEK ¶
EncryptFEK encrypts a File Encryption Key (FEK) using a key derived from the user's password via Argon2ID. This creates the "Owner Envelope".
func EncryptFile ¶
EncryptFile encrypts file data using a FEK (File Encryption Key) The keyType parameter indicates what password type will be used to encrypt the FEK
func EncryptGCM ¶
EncryptGCM encrypts data using AES-256-GCM Returns: nonce + ciphertext + tag (all concatenated)
func EncryptGCMWithAAD ¶
EncryptGCMWithAAD encrypts data using AES-256-GCM with Additional Authenticated Data AAD is authenticated but not encrypted - used to bind ciphertext to context Returns: nonce + ciphertext + tag (all concatenated)
func EnvelopeHeaderSize ¶
func EnvelopeHeaderSize() int
EnvelopeHeaderSize returns the envelope header size in bytes (chunk 0 only)
func FormatFileSize ¶
FormatFileSize converts bytes to human-readable format
func GenerateAESKey ¶
GenerateAESKey generates a cryptographically secure 256-bit AES key
func GenerateDownloadToken ¶
GenerateDownloadToken generates a cryptographically secure 32-byte Download Token
func GenerateFEK ¶
GenerateFEK generates a cryptographically secure 32-byte File Encryption Key
func GenerateRandomBytes ¶
GenerateRandomBytes generates cryptographically secure random bytes
func GenerateShareSalt ¶
GenerateShareSalt generates a random 32-byte salt for share key derivation
func GenerateTestFileContent ¶
func GenerateTestFileContent(size int64, pattern FilePattern) ([]byte, error)
GenerateTestFileContent creates deterministic test file content
func GenerateTestFileToPath ¶
func GenerateTestFileToPath(filePath string, size int64, pattern FilePattern) (string, error)
GenerateTestFileToPath creates a test file directly to disk for memory efficiency
func GenerateUserKeySalt ¶
GenerateUserKeySalt generates a deterministic salt based on username and key type
func GetEmbeddedArgon2ParamsJSON ¶
func GetEmbeddedArgon2ParamsJSON() []byte
GetEmbeddedArgon2ParamsJSON returns the raw embedded JSON for API serving
func GetEmbeddedChunkingParamsJSON ¶
func GetEmbeddedChunkingParamsJSON() []byte
GetEmbeddedChunkingParamsJSON returns the raw embedded JSON for API serving
func GetEmbeddedPasswordRequirementsJSON ¶
func GetEmbeddedPasswordRequirementsJSON() []byte
GetEmbeddedPasswordRequirementsJSON returns the raw embedded JSON for API serving
func GetTOTPMasterKeyStatus ¶
GetTOTPMasterKeyStatus returns information about the TOTP master key
func HashDownloadToken ¶
HashDownloadToken creates a SHA-256 hash of the download token The download token is derived from the share key: HKDF(share_key, "download_token", 32)
func InitKeyManager ¶
InitKeyManager initializes the global KeyManager. It expects ARKFILE_MASTER_KEY to be set in the environment.
func InitializeTOTPMasterKey ¶
func InitializeTOTPMasterKey() error
InitializeTOTPMasterKey loads or generates the TOTP master key using KeyManager
func KeyTypeForContext ¶
KeyTypeForContext returns the envelope key type byte for a given password context
func ParseEnvelope ¶
ParseEnvelope parses an envelope header and returns the key type
func ParseSizeString ¶
ParseSizeString converts human-readable size strings to bytes
func PlaintextChunkSize ¶
func PlaintextChunkSize() int64
PlaintextChunkSize returns the plaintext chunk size in bytes from the embedded config
func SecureClear ¶
func SecureClear(data []byte)
SecureClear securely clears sensitive data from memory
func SecureCompare ¶
SecureCompare performs constant-time comparison of two byte slices
func SecureZeroSessionKey ¶
func SecureZeroSessionKey(sessionKey []byte)
SecureZeroSessionKey securely clears session key material
func SecureZeroTOTPKey ¶
func SecureZeroTOTPKey(key []byte)
SecureZeroTOTPKey clears a TOTP key from memory
func ValidateSessionKey ¶
ValidateSessionKey checks if a session key has the expected properties
func VerifyDownloadToken ¶
VerifyDownloadToken verifies a download token against its hash
Types ¶
type AesGcmParams ¶
type AesGcmParams struct {
NonceSizeBytes int `json:"nonceSizeBytes"`
TagSizeBytes int `json:"tagSizeBytes"`
KeySizeBytes int `json:"keySizeBytes"`
}
AesGcmParams represents AES-GCM configuration
type ChunkInfo ¶
type ChunkInfo struct {
Index int `json:"index"`
File string `json:"file"`
Hash string `json:"hash"`
Size int `json:"size"`
}
ChunkInfo represents metadata for a single encrypted chunk
type ChunkManifest ¶
type ChunkManifest struct {
Envelope string `json:"envelope"`
TotalChunks int `json:"total_chunks"`
ChunkSize int `json:"chunk_size"`
Chunks []ChunkInfo `json:"chunks"`
}
ChunkManifest represents metadata for chunked encryption
func (*ChunkManifest) ToJSON ¶
func (m *ChunkManifest) ToJSON() ([]byte, error)
ToJSON serializes the manifest to JSON
type ChunkingParams ¶
type ChunkingParams struct {
PlaintextChunkSizeBytes int64 `json:"plaintextChunkSizeBytes"`
Envelope EnvelopeParams `json:"envelope"`
AesGcm AesGcmParams `json:"aesGcm"`
}
ChunkingParams represents the unified chunking configuration
func GetChunkingParams ¶
func GetChunkingParams() (*ChunkingParams, error)
GetChunkingParams returns the parsed chunking parameters from the embedded JSON
func MustGetChunkingParams ¶
func MustGetChunkingParams() *ChunkingParams
MustGetChunkingParams returns the parsed chunking parameters or panics on error. Use this only during initialization where failure should be fatal.
type DecryptedFileMetadata ¶
type DecryptedFileMetadata struct {
FileID string `json:"file_id"`
StorageID string `json:"storage_id"`
PasswordHint string `json:"password_hint"`
PasswordType string `json:"password_type"`
Filename string `json:"filename"`
SHA256 string `json:"sha256"`
SizeBytes int64 `json:"size_bytes"`
SizeReadable string `json:"size_readable"`
UploadDate string `json:"upload_date"`
}
DecryptedFileMetadata represents decrypted file metadata
type EnvelopeParams ¶
type EnvelopeParams struct {
Version int `json:"version"`
HeaderSizeBytes int `json:"headerSizeBytes"`
KeyTypes KeyTypeMapping `json:"keyTypes"`
}
EnvelopeParams represents envelope header configuration
type FilePattern ¶
type FilePattern string
FilePattern represents different test file content patterns
const ( PatternSequential FilePattern = "sequential" PatternRepeated FilePattern = "repeated" PatternRandom FilePattern = "random" PatternZeros FilePattern = "zeros" )
type KeyManager ¶
type KeyManager struct {
// contains filtered or unexported fields
}
KeyManager handles the lifecycle of system secrets using Envelope Encryption.
func GetKeyManager ¶
func GetKeyManager() (*KeyManager, error)
GetKeyManager returns the global KeyManager instance.
func (*KeyManager) DecryptSystemKey ¶
func (km *KeyManager) DecryptSystemKey(encryptedKey, nonce []byte, keyType string) ([]byte, error)
DecryptSystemKey decrypts an encrypted key using the Master Key.
func (*KeyManager) DeleteKey ¶
func (km *KeyManager) DeleteKey(keyID string) error
DeleteKey removes a key from the database.
func (*KeyManager) EncryptSystemKey ¶
EncryptSystemKey encrypts a raw key using the Master Key (via a derived wrapping key).
func (*KeyManager) GetKey ¶
func (km *KeyManager) GetKey(keyID string, keyType string) ([]byte, error)
GetKey retrieves and decrypts a key from the database. Returns error if key not found.
func (*KeyManager) GetOrGenerateKey ¶
GetOrGenerateKey retrieves a key from the DB or generates/stores it if missing. This function is safe for concurrent access across multiple instances. It uses database transactions to ensure only one instance generates a key during initial deployment, preventing race conditions in multi-instance scenarios.
keyID: Unique identifier for the key (e.g., "jwt_signing_key_v1") keyType: Type of key for derivation context (e.g., "jwt", "totp") keySize: Size of key to generate if missing
type KeyTypeMapping ¶
KeyTypeMapping maps password context names to envelope key type bytes
type PasswordRequirements ¶
type PasswordRequirements struct {
MinAccountPasswordLength int `json:"minAccountPasswordLength"`
MinCustomPasswordLength int `json:"minCustomPasswordLength"`
MaxPasswordLength int `json:"maxPasswordLength"`
MinCharacterClassesRequired int `json:"minCharacterClassesRequired"`
SpecialCharacters string `json:"specialCharacters"`
}
PasswordRequirements holds password validation configuration
func GetPasswordRequirements ¶
func GetPasswordRequirements() *PasswordRequirements
GetPasswordRequirements returns the loaded password requirements (panics if not loaded)
func LoadPasswordRequirements ¶
func LoadPasswordRequirements() (*PasswordRequirements, error)
LoadPasswordRequirements loads password requirements from embedded config The JSON is embedded at build time from crypto/password-requirements.json.
type PasswordValidationResult ¶
type PasswordValidationResult struct {
MeetsRequirement bool `json:"meets_requirements"`
Requirements RequirementChecks `json:"requirements"`
Reasons []string `json:"reasons,omitempty"`
}
PasswordValidationResult represents the result of password validation
func ValidateAccountPassword ¶
func ValidateAccountPassword(password string) *PasswordValidationResult
ValidateAccountPassword validates account passwords using config requirements
func ValidateCustomPassword ¶
func ValidateCustomPassword(password string) *PasswordValidationResult
ValidateCustomPassword validates custom passwords using config requirements
func ValidatePassword ¶
func ValidatePassword(password string, minLength int, maxLength int, minClasses int, specialChars string) *PasswordValidationResult
ValidatePassword performs deterministic password validation. Pass = (length >= minLength) AND (length <= maxLength) AND (character classes met >= minCharacterClassesRequired) maxLength of 0 means no maximum is enforced.
func ValidateSharePassword ¶
func ValidateSharePassword(password string) *PasswordValidationResult
ValidateSharePassword validates share passwords using config requirements
type RequirementChecks ¶
type RequirementChecks struct {
Length RequirementStatus `json:"length"`
Uppercase RequirementStatus `json:"uppercase"`
Lowercase RequirementStatus `json:"lowercase"`
Number RequirementStatus `json:"number"`
Special RequirementStatus `json:"special"`
ClassCount int `json:"class_count"`
ClassesRequired int `json:"classes_required"`
}
RequirementChecks tracks individual password requirements
type RequirementStatus ¶
type RequirementStatus struct {
Met bool `json:"met"`
Current int `json:"current,omitempty"`
Needed int `json:"needed,omitempty"`
Message string `json:"message"`
}
RequirementStatus represents the status of a single requirement
type SessionKeyInfo ¶
type SessionKeyInfo struct {
Username string
DerivedAt int64 // Unix timestamp
Context string // The context used for derivation
KeyLength int // Length in bytes
IsValid bool // Whether the key passed validation
}
SessionKeyInfo contains metadata about a session key
func CreateSessionKeyInfo ¶
func CreateSessionKeyInfo(username, context string, sessionKey []byte) SessionKeyInfo
CreateSessionKeyInfo creates metadata for a session key
type ShareEnvelope ¶
type ShareEnvelope struct {
}
ShareEnvelope represents the decrypted content of a Share Envelope This is a JSON structure containing the FEK, Download Token, and file metadata. File metadata (filename, size, sha256) is included so share recipients can:
- Preview the file before downloading (filename, size)
- Verify integrity after decryption (sha256)
The metadata is protected by the same AES-GCM-AAD encryption as the FEK, so only someone with the share password can access it.
func ParseShareEnvelope ¶
func ParseShareEnvelope(envelopeJSON []byte) (*ShareEnvelope, error)
ParseShareEnvelope parses a Share Envelope JSON payload
type UnifiedArgonProfile ¶
type UnifiedArgonProfile struct {
Time uint32 // iterations
Memory uint32 // KB
Threads uint8 // parallelism
KeyLen uint32 // output length in bytes
}
UnifiedArgonProfile defines Argon2ID parameters for all file encryption contexts
var ( // UnifiedArgonSecure is the profile for all file encryption contexts // SINGLE SOURCE OF TRUTH: Embedded from crypto/argon2id-params.json at build time UnifiedArgonSecure UnifiedArgonProfile )