Documentation
¶
Index ¶
- Constants
- Variables
- func CheckVaultPack(b []byte, id [16]byte, packLog2 int) error
- func DecryptContent(fmk, data []byte) ([]byte, error)
- func DecryptFileStream(w io.Writer, r io.Reader, fmk, previous []byte) error
- func DecryptFxe(w io.Writer, r io.Reader, h *FxeHeader, k *FxeKeys) error
- func DecryptStream(w io.Writer, r io.Reader, dek, prefix []byte, log2 int, expect int64) (int64, error)
- func DirIDOf(stored string) []byte
- func EncodeVaultBody(t *VaultTree, grave []VaultGrave) ([]byte, [][16]byte, error)
- func EncodedOf(stored string, readSidecar func(name string) ([]byte, bool)) (string, bool)
- func EncryptContent(fmk, plain []byte, rnd io.Reader) ([]byte, error)
- func EncryptFile(w io.Writer, r io.Reader, size int64, fmk []byte, rnd io.Reader) error
- func EncryptStream(w io.Writer, r io.Reader, dek, prefix []byte, log2 int, size int64) (int64, error)
- func EncryptedFileSize(size int64) int64
- func EscrowKID(spkiB64 string) string
- func FinishConversion(marker []byte) ([]byte, error)
- func FinishNames(marker []byte) ([]byte, error)
- func FormatRecoveryKey(raw []byte) string
- func HasFxeMagic(b []byte) bool
- func HasMagic(b []byte) bool
- func ItemPrefixForSidecar(sidecar string) (string, bool)
- func NameProblem(name string) string
- func NumberedName(name string, n int) string
- func ParseRecoveryKey(s string) ([]byte, bool)
- func PasswordProblem(pw string) string
- func PlanVaultRepack(latest *VaultIndex, packLog2 int) [][16]byte
- func RunConversion(root string, io ConvertIO, prog *ConvertProgress) error
- func RunNamePass(nk *NameKey, root string, io NamePassIO, prog *NamePassProgress) error
- func SealVaultIndex(k *VaultKeys, gen uint64, body []byte, sealID [16]byte) ([]byte, error)
- func SidecarNameFor(stored string) (string, bool)
- func StartConversion(marker []byte, when time.Time, cleanup *Cleanup) ([]byte, error)
- func StreamCiphertextSize(n int64, log2 int) int64
- func StreamFileHeader(fmk []byte, log2 int, rnd io.Reader) (header, dek, prefix []byte, err error)
- func ValidChunkLog2(n int) bool
- func VaultLiveBytes(latest *VaultIndex) map[[16]byte]int64
- func VaultPackDataArea(packLog2 int) int64
- func VaultWarning(entries int, indexSize int64) string
- type Cleanup
- type ConvertFailure
- type ConvertIO
- type ConvertProgress
- type ConvertRow
- type CorruptError
- type CreateOptions
- type Created
- type DirVaultSource
- func (s *DirVaultSource) ListIndexes(ctx context.Context) ([]VaultObject, error)
- func (s *DirVaultSource) ListPacks(ctx context.Context) ([]VaultObject, error)
- func (s *DirVaultSource) ReadIndex(ctx context.Context, gen uint64) ([]byte, error)
- func (s *DirVaultSource) ReadPack(ctx context.Context, id [16]byte, off, n int64) ([]byte, error)
- type EncryptTreeJob
- func (j *EncryptTreeJob) Create(password string) (string, error)
- func (j *EncryptTreeJob) Names() bool
- func (j *EncryptTreeJob) Out() string
- func (j *EncryptTreeJob) Resuming() bool
- func (j *EncryptTreeJob) Run(ctx context.Context, onFile func(rel string, size int64)) (*EncryptTreeResult, error)
- func (j *EncryptTreeJob) Unlock(secret string, recovery bool) error
- type EncryptTreeOptions
- type EncryptTreeResult
- type EncryptedName
- type FxeHeader
- type FxeKeys
- type Job
- type Keys
- type Marker
- type NameKey
- func (k *NameKey) DecryptEncoded(encoded string, parentID []byte) (string, bool)
- func (k *NameKey) DecryptStoredName(stored string, parentID []byte, readSidecar func(name string) ([]byte, bool)) (string, NameState)
- func (k *NameKey) DeriveDirID(parentID []byte, plain string) []byte
- func (k *NameKey) EffectiveDirID(parentID []byte, stored string) []byte
- func (k *NameKey) EncryptName(plain string, parentID, dirID []byte) (EncryptedName, error)
- func (k *NameKey) RecoverMoved(stored string, here []byte, ids [][]byte, ...) (string, bool)
- type NameKind
- type NamePassIO
- type NamePassProgress
- type NameState
- type NamesSlot
- type OpenOptions
- type RecoverySlot
- type RekeySlot
- type Result
- type StoredName
- type UnsupportedError
- type VaultCommit
- type VaultContent
- type VaultDecryptOptions
- type VaultExtent
- type VaultGCPlan
- type VaultGrave
- type VaultIndex
- type VaultKeys
- type VaultLatestSource
- type VaultLoadOptions
- type VaultNode
- type VaultObject
- type VaultPackReader
- type VaultPackSink
- type VaultReader
- type VaultSource
- type VaultState
- type VaultTree
- func (t *VaultTree) CheckMkdir(p string) error
- func (t *VaultTree) CheckMove(from, to string) error
- func (t *VaultTree) CheckPutFile(p string) (adds bool, err error)
- func (t *VaultTree) Clone() *VaultTree
- func (t *VaultTree) Len() int
- func (t *VaultTree) Lookup(p string) *VaultNode
- func (t *VaultTree) Mkdir(p string, mtime int64) (*VaultNode, error)
- func (t *VaultTree) Move(from, to string) (*VaultNode, error)
- func (t *VaultTree) PutFile(p string, mtime, size int64, c *VaultContent) (*VaultNode, error)
- func (t *VaultTree) Remove(p string) (*VaultNode, error)
- func (t *VaultTree) Root() *VaultNode
- func (t *VaultTree) Walk(fn func(n *VaultNode, depth int) error) error
- type VaultWriter
- func (w *VaultWriter) Commit(ctx context.Context) (*VaultCommit, error)
- func (w *VaultWriter) Delete(p string) error
- func (w *VaultWriter) ForgetGrave(ids [][16]byte)
- func (w *VaultWriter) Generation() uint64
- func (w *VaultWriter) Mkdir(p string, mtime int64) error
- func (w *VaultWriter) Move(from, to string) error
- func (w *VaultWriter) Repack(ctx context.Context, packs [][16]byte, read VaultPackReader) error
- func (w *VaultWriter) Tree() *VaultTree
- func (w *VaultWriter) Warning() string
- func (w *VaultWriter) Write(ctx context.Context, p string, mtime int64, r io.Reader, size int64) (*VaultNode, error)
- type VaultWriterConfig
Constants ¶
const ( NamesAlg = "AES-SIV-512" NamesEnc = "b64url" NameKeyBytes = 64 NameMaxBytes = 255 DirIDBytes = 16 LongSuffix = ".fxl" SidecarSuffix = ".fxl.name" )
Name encryption constants, identical to the browser's.
const FxeExtension = ".fxe"
FxeExtension is the stored-name suffix of a single encrypted file.
const MarkerName = ".filex-e2e.json"
MarkerName is the marker's file name at an encrypted folder's root.
const MaxOneShot = 200 * 1024 * 1024
MaxOneShot is the most content a 0x01 file carries. Writers use the one-shot format up to it and STREAM (0x02) above it, exactly as the browser does (E2E_MAX_FILE_BYTES), so every filex since the feature shipped reads the smaller files.
const MinIterations = 600_000
MinIterations is the fewest PBKDF2 iterations a writer uses. Readers accept any count from 1; a writer never goes below this (E2E_MIN_ITERATIONS).
const MinPasswordLen = 8
MinPasswordLen is the shortest folder password the writers accept, as the browser's dialog (E2E_MIN_PASSWORD_LEN).
const ( // NamesLongDefault is the shortening threshold a new names slot gets // (E2E_NAMES_LONG_DEFAULT). NamesLongDefault = 220 )
const (
// StreamChunkLog2 is the chunk size writers use (2^20 = 1 MiB).
StreamChunkLog2 = 20
)
const ( // VaultChunkLog2 is the STREAM chunk size vault writers use (2^20). VaultChunkLog2 = StreamChunkLog2 )
const VaultGCPassMax = 1000
VaultGCPassMax is the most a collection deletes in one pass (and one delete request).
const VaultRetention = 15 * time.Minute
VaultRetention is how long a replaced generation is kept for its readers.
Variables ¶
var ( // ErrWrongPassword: the password does not open the marker's verify blob. ErrWrongPassword = errors.New("wrong password") // ErrWrongRecoveryKey: malformed, wrong, or the folder has no recovery key. ErrWrongRecoveryKey = errors.New("wrong recovery key (or this folder has no recovery key)") // ErrNotMarker: the file is not a filex encrypted-folder marker. ErrNotMarker = errors.New("not a filex encrypted-folder marker (.filex-e2e.json)") )
var ( // ErrVaultNotFound: no entry at that path. ErrVaultNotFound = errors.New("no such file or folder in the vault") // ErrVaultExists: the name is taken in that folder. ErrVaultExists = errors.New("a file or folder with that name is already there") // ErrVaultNotDir: a path segment that should be a folder is a file. ErrVaultNotDir = errors.New("not a folder") // ErrVaultIsDir: a file operation on a folder. ErrVaultIsDir = errors.New("is a folder") // ErrVaultBadName: a name the format does not allow. ErrVaultBadName = errors.New("not a name a vault can hold") // ErrVaultFull: the change would pass the writer's entry limit. ErrVaultFull = fmt.Errorf("this vault already holds the most files and folders a vault may hold (%d)", e2e.VaultEntriesWriteMax) // ErrVaultTooDeep: the change would nest folders deeper than the format allows. ErrVaultTooDeep = fmt.Errorf("folders in a vault nest at most %d deep", e2e.VaultMaxDepth) // ErrVaultLoop: a folder moved into itself. ErrVaultLoop = errors.New("a folder cannot be moved into itself") )
var ErrAlreadyEncrypted = errors.New("this folder is already an encrypted folder (it holds " + MarkerName + ")")
ErrAlreadyEncrypted: the input is an encrypted folder already.
var ErrContent = errors.New("content failed authentication (damaged, tampered with, or from another folder)")
ErrContent: the content failed authentication — the file is damaged or was tampered with, or it belongs to another folder.
var ErrFileExists = errors.New("the output file already exists - pass another with -o")
ErrFileExists: the file a .fxe would decrypt to is already there.
var ErrNestedEncrypted = errors.New("this folder holds an encrypted folder, and encrypted folders cannot be nested")
ErrNestedEncrypted: the input holds an encrypted folder. Encrypted folders do not nest - the browser refuses the same.
var ErrNoMarker = errors.New("no " + MarkerName + " found in the input - pass the encrypted folder's root, or its marker with --marker")
ErrNoMarker: the input carries no .filex-e2e.json and none was given.
var ErrOutputExists = errors.New("the output directory already exists")
ErrOutputExists: the output directory is already there. Decrypting over it would mix old and new plaintext; pick another -o.
var ErrSizeMismatch = errors.New("the content is not the size it was said to be (changed while it was read?)")
ErrSizeMismatch: the plaintext a writer was given is not the length it was told. Nothing a writer produced from it is a valid file.
var ErrStopped = errors.New("stopped")
ErrStopped is a run that was asked to stop. What it did so far stands.
var ErrVaultDamaged = errors.New("damaged")
ErrVaultDamaged is wrapped by every error that says a vault file does not verify or breaks a rule of the format. Readers fall back to an older generation on it; nothing else is damage.
var ErrVaultIndexTooLarge = fmt.Errorf("the vault's index would pass %d MiB", e2e.VaultIndexWriteMax>>20)
ErrVaultIndexTooLarge: the change would make the index larger than a writer may write.
var ErrVaultObjectMissing = errors.New("not in the vault")
ErrVaultObjectMissing is wrapped by a source's error for an index file or a pack that is not there.
var ErrVaultPackUnknown = errors.New("the pack upload's outcome is unknown")
ErrVaultPackUnknown is what a Sink wraps when it cannot tell whether a pack was stored (a time-out): the writer sends the same data again under a new pack id.
var ErrVaultReadOnly = errors.New("this vault is read-only here")
ErrVaultReadOnly: this state of the vault must not be written.
var FxeMagic = []byte("filexfxe")
FxeMagic starts every single encrypted file.
var MagicPrefix = []byte("filexe2e")
MagicPrefix starts every encrypted file.
Functions ¶
func CheckVaultPack ¶ added in v0.54.0
CheckVaultPack checks a whole pack against its name and the vault's pack size - what a reader that holds the whole pack does (`filex decrypt` on a copy, `filex vault prune`). Any mismatch is damage.
func DecryptContent ¶
DecryptContent opens one encrypted file with the folder master key.
func DecryptFileStream ¶
DecryptFileStream decrypts one folder file — header version 0x01 or 0x02 — from r to w. previous is the prior folder key of a folder mid re-key, or nil. A 0x01 file is one AES-GCM message and is read whole (at most 200 MiB); a 0x02 file streams.
func DecryptFxe ¶
DecryptFxe writes the plaintext of a .fxe body (r positioned after the prefix) to w, checked end to end against the header's size.
func DecryptStream ¶
func DecryptStream(w io.Writer, r io.Reader, dek, prefix []byte, log2 int, expect int64) (int64, error)
DecryptStream writes the plaintext of the STREAM body read from r to w. expect is the plaintext length the header promised, or -1. Any tampering — a flipped bit, a truncated, reordered or extended body, a length that disagrees with expect — returns an error wrapping ErrContent.
⚠ w has received the plaintext of every chunk before the failing one. The caller writes into a temporary place and throws it away on error.
func EncodeVaultBody ¶ added in v0.54.0
func EncodeVaultBody(t *VaultTree, grave []VaultGrave) ([]byte, [][16]byte, error)
EncodeVaultBody writes a tree and its graveyard in the one canonical encoding, and returns the pack table it wrote.
func EncodedOf ¶
EncodedOf returns the encoded ciphertext a stored name carries — through its sidecar for a long one — or ok=false (a plain name, a sidecar, or a long name whose sidecar is missing or does not match).
func EncryptContent ¶ added in v0.50.0
EncryptContent encrypts a whole file held in memory, up to MaxOneShot, as a 0x01 file: the 97-byte header, then AES-GCM(DEK, dataIV, content). Byte-compatible with the browser's encryptFile.
func EncryptFile ¶ added in v0.50.0
EncryptFile encrypts a plaintext of exactly size bytes read from r into a folder file written to w, under the folder key: the one-shot format (0x01) up to MaxOneShot - read whole, at most 200 MiB - and STREAM (0x02, 1 MiB chunks) above it, read and written as a stream. The same choice, the same bytes, as an upload in the browser.
func EncryptStream ¶ added in v0.50.0
func EncryptStream(w io.Writer, r io.Reader, dek, prefix []byte, log2 int, size int64) (int64, error)
EncryptStream writes the STREAM body of a plaintext of exactly size bytes, read from r, under dek with the 7-byte nonce prefix. It refuses a reader that yields fewer or more bytes than size: the last chunk is the one the size says is last, and sealing a chunk as "last" that is not would make a body no reader accepts. Returns the bytes written.
func EncryptedFileSize ¶ added in v0.50.0
EncryptedFileSize is the length of the encrypted file a plaintext of size bytes becomes: 0x01 up to MaxOneShot, 0x02 (1 MiB chunks) above it.
func EscrowKID ¶ added in v0.50.0
EscrowKID is the short name of an escrow public key (base64 SPKI), the one its slots carry; "" when it is not one.
func FinishConversion ¶ added in v0.50.0
FinishConversion drops `conv`: every file carries the magic. Back to v2 when nothing else is required (finishConversion).
func FinishNames ¶ added in v0.50.0
FinishNames drops `names.pending`: every entry carries its encrypted name (finishNames). The rest of the names slot is kept as it is.
func FormatRecoveryKey ¶ added in v0.50.0
FormatRecoveryKey writes 20 raw bytes as the key a person writes down: Crockford base32, most significant bits first, 8 groups of 4 joined by "-" (formatRecoveryKey).
func HasFxeMagic ¶
HasFxeMagic reports whether b starts with the .fxe magic.
func ItemPrefixForSidecar ¶
ItemPrefixForSidecar returns the "<H>.fxl" an item next to this sidecar starts with (the item is "<H>.fxl" or "<H>.fxl.D").
func NameProblem ¶
NameProblem mirrors the browser's namePlainProblem: "" when the name is one a local disk can hold, else why not.
func NumberedName ¶ added in v0.50.0
NumberedName is "name (2).ext": a free plaintext name when the one needed is taken (numberedName).
func ParseRecoveryKey ¶
ParseRecoveryKey reads a typed recovery key back to its 20 bytes, forgiving case, dashes, spaces and the Crockford look-alikes (O→0, I/L→1).
func PasswordProblem ¶ added in v0.50.0
PasswordProblem is "" for a password the browser's dialog would take, and otherwise why not. The dialog counts a JavaScript string's length, UTF-16 code units, so this does too: the same password passes in both.
func PlanVaultRepack ¶ added in v0.54.0
func PlanVaultRepack(latest *VaultIndex, packLog2 int) [][16]byte
PlanVaultRepack returns the packs to repack after a commit, or nil. With S the packs with fewer live bytes than half a data area, it repacks when S has at least 2 packs, their live bytes fit in fewer packs than S has, and more than half of all the data areas in the table is dead.
func RunConversion ¶ added in v0.50.0
func RunConversion(root string, io ConvertIO, prog *ConvertProgress) error
RunConversion converts every plaintext file under root. It returns ErrStopped when Stopped said so; a file that failed is counted, not returned.
func RunNamePass ¶ added in v0.50.0
func RunNamePass(nk *NameKey, root string, io NamePassIO, prog *NamePassProgress) error
RunNamePass renames every entry under root whose name does not open where it is. It returns ErrStopped when Stopped said so.
func SealVaultIndex ¶ added in v0.54.0
SealVaultIndex makes the index file of generation gen from a body, sealed under sealID (16 random bytes, new for every sealing).
func SidecarNameFor ¶
SidecarNameFor returns the sidecar that belongs to a long stored name (file or folder).
func StartConversion ¶ added in v0.50.0
StartConversion marks an existing folder as being encrypted in place: v3, "conv" required (a filex that does not know it refuses a folder whose files are half plaintext), `conv: {pending, started, cleanup}`. Fields it does not know are kept (startConversion).
func StreamCiphertextSize ¶
StreamCiphertextSize is the body length for a plaintext of n bytes.
func StreamFileHeader ¶ added in v0.50.0
StreamFileHeader is the 97-byte header of a 0x02 folder file: the magic, the version, the wrapped file key (exactly as 0x01 wraps it), the STREAM nonce prefix and the chunk size. It returns the header and the DEK and prefix the body is to be sealed with; the caller zeroes the DEK.
func ValidChunkLog2 ¶
ValidChunkLog2 reports whether a reader accepts this chunk size.
func VaultLiveBytes ¶ added in v0.54.0
func VaultLiveBytes(latest *VaultIndex) map[[16]byte]int64
VaultLiveBytes is, for each pack of the latest table, the bytes the latest tree's extents use in it.
func VaultPackDataArea ¶ added in v0.54.0
VaultPackDataArea is how many bytes of a pack of 2^packLog2 bytes hold data.
func VaultWarning ¶ added in v0.54.0
VaultWarning is what a client says before a change to a vault that is close to its limits, or "" (docs/E2E-VAULT-FORMAT.md → "Limits").
Types ¶
type Cleanup ¶ added in v0.50.0
Cleanup is what to remove when a conversion finishes: the plaintext's old versions and the trash entries that came from the folder (the owner's choice, kept in the key file so a resumed run honours it).
func ConversionCleanup ¶ added in v0.50.0
ConversionCleanup is the cleanup a pending conversion asked for, or nil.
type ConvertFailure ¶ added in v0.50.0
ConvertFailure is one file the run could not convert, and why.
type ConvertIO ¶ added in v0.50.0
type ConvertIO interface {
// List is the raw listing of a folder.
List(dir string) ([]ConvertRow, error)
// Head is the first bytes of a file (at least 9 when it has them).
Head(path string) ([]byte, error)
// Convert encrypts the file `row` (in `dir`) under the folder key and
// writes it over itself as a conversion write, on condition that it is
// still the file listed (expect). Errors when the server refuses (a
// changed file: 412).
Convert(dir string, row ConvertRow, expect string) error
// Stopped is asked between files.
Stopped() bool
}
ConvertIO is what the conversion needs from wherever the folder is.
type ConvertProgress ¶ added in v0.50.0
type ConvertProgress struct {
// Total is the files found (everything but the key file and sidecars).
Total int
// Done is the files converted by this run; Large of them as STREAM.
Done, Large int
// Skipped is the files already encrypted (converted earlier, or written
// encrypted).
Skipped int
// Failed is the files that could not be read or written; Failures says
// which and why.
Failed int
Failures []ConvertFailure
// OnFile, when set, is told every file as its turn comes.
OnFile func(path string, size int64)
}
ConvertProgress counts a run.
type ConvertRow ¶ added in v0.50.0
type ConvertRow struct {
// Path is the entry's full path on the server (adapter://rel).
Path string
// Name is its stored name.
Name string
Dir bool
// Size in bytes and Modified in Unix milliseconds, as listed; -1 when the
// listing did not say. Together they are the write's precondition.
Size int64
Modified int64
}
ConvertRow is one entry of a folder's raw listing (stored names).
func (ConvertRow) Expect ¶ added in v0.50.0
func (r ConvertRow) Expect() string
Expect is the listing's own signature of a file, "<size>:<ms>", or "" when the listing did not give both.
type CorruptError ¶
type CorruptError struct {
Path string // plaintext path where known, with the stored name
Err error
}
CorruptError names the entry that stopped a run.
func (*CorruptError) Error ¶
func (e *CorruptError) Error() string
func (*CorruptError) Unwrap ¶
func (e *CorruptError) Unwrap() error
type CreateOptions ¶ added in v0.50.0
type CreateOptions struct {
// Iterations of PBKDF2. Never fewer than MinIterations; 0 means that.
Iterations int
// EscrowPublicKey is the installation's escrow key (base64 SPKI DER, as
// /api/capabilities publishes it), or "" for no escrow slot.
EscrowPublicKey string
// EncryptNames makes a level-2 folder (v3, feature "names").
EncryptNames bool
// NamesPending marks the names slot pending: an existing folder whose
// entries still carry their plaintext names (enableNames does the same).
NamesPending bool
// Rand is where every random byte comes from; nil is crypto/rand.
Rand io.Reader
}
CreateOptions configure CreateFolder.
type Created ¶ added in v0.50.0
type Created struct {
// Marker is the key file, ready to write as `.filex-e2e.json`.
Marker []byte
// Keys are the folder key (and the name key, at level 2).
Keys *Keys
// RecoveryKey is shown ONCE. filex never stores it.
RecoveryKey string
}
Created is a new folder's key file and the keys it hands back.
func CreateFolder ¶ added in v0.50.0
func CreateFolder(password string, opts CreateOptions) (*Created, error)
CreateFolder makes a new encrypted folder's key file: a random folder key wrapped under the password (PBKDF2-SHA-256), under a freshly minted recovery key (HKDF-SHA-256), and - when an escrow key is given - to the installation's escrow key. At level 2 (EncryptNames) it is v3 with a names slot. The password is checked as the browser checks it.
type DirVaultSource ¶ added in v0.54.0
DirVaultSource reads a copy of a vault folder: the folder (os.DirFS) or a zip of it, extracted. A pack is checked whole the first time it is read: size, magic, version, kind, size log2 and id against its name.
func NewDirVaultSource ¶ added in v0.54.0
func NewDirVaultSource(fsys fs.FS, packLog2 int) *DirVaultSource
NewDirVaultSource reads the vault folder at the root of fsys.
func (*DirVaultSource) ListIndexes ¶ added in v0.54.0
func (s *DirVaultSource) ListIndexes(ctx context.Context) ([]VaultObject, error)
ListIndexes lists v/idx.
func (*DirVaultSource) ListPacks ¶ added in v0.54.0
func (s *DirVaultSource) ListPacks(ctx context.Context) ([]VaultObject, error)
ListPacks lists v/p/XX.
type EncryptTreeJob ¶ added in v0.50.0
type EncryptTreeJob struct {
// contains filtered or unexported fields
}
EncryptTreeJob is one encryption of a local folder, between OpenEncrypt and Run.
func OpenEncrypt ¶ added in v0.50.0
func OpenEncrypt(in string, opts EncryptTreeOptions) (*EncryptTreeJob, error)
OpenEncrypt checks the input and the output before anyone types a password: the input is a folder, not encrypted already and holding no encrypted folder; the output does not exist and is not inside the input. When "<out>.partial" holds a key file, the job resumes it (Resuming).
func (*EncryptTreeJob) Create ¶ added in v0.50.0
func (j *EncryptTreeJob) Create(password string) (string, error)
Create mints the key file of a new run and writes it into the partial output, before any file. It returns the recovery key, to be shown once.
func (*EncryptTreeJob) Names ¶ added in v0.50.0
func (j *EncryptTreeJob) Names() bool
Names reports whether names are encrypted: what was asked for a new run, what the key file says for a resumed one.
func (*EncryptTreeJob) Out ¶ added in v0.50.0
func (j *EncryptTreeJob) Out() string
Out is where Run writes.
func (*EncryptTreeJob) Resuming ¶ added in v0.50.0
func (j *EncryptTreeJob) Resuming() bool
Resuming reports whether a stopped run is continued: its key file is unlocked (Unlock) rather than a new one created (Create).
func (*EncryptTreeJob) Run ¶ added in v0.50.0
func (j *EncryptTreeJob) Run(ctx context.Context, onFile func(rel string, size int64)) (*EncryptTreeResult, error)
Run encrypts every file of the input into the partial output and renames it into place. onFile, when set, is told each file as its turn comes. A cancelled ctx stops it at once (ErrStopped), the file in flight discarded. On an error the partial output stays, for the next run to continue.
type EncryptTreeOptions ¶ added in v0.50.0
type EncryptTreeOptions struct {
// Out is the output folder. Empty: "<input>-encrypted" next to the input.
Out string
// Names encrypts file and folder names too (level 2).
Names bool
// EscrowPublicKey is an installation's escrow key (base64 SPKI) to seal
// the folder key to, or "" for none.
EscrowPublicKey string
// Iterations and Rand are for tests; writers use MinIterations and
// crypto/rand.
Iterations int
Rand io.Reader
}
EncryptTreeOptions configure OpenEncrypt.
type EncryptTreeResult ¶ added in v0.50.0
type EncryptTreeResult struct {
Out string
Files int
Dirs int
// Kept is the files a resumed run found already written.
Kept int
// Large is the files written as STREAM (over 200 MB).
Large int
Warnings []string
}
EncryptTreeResult summarises a finished run.
type EncryptedName ¶
type EncryptedName struct {
Stored string // the entry's name on the server
Encoded string // the encoded ciphertext S (without a folder's ".D")
SidecarName string // set only for a long name
SidecarContent string
}
EncryptedName is what the browser writes for one plaintext name.
type FxeHeader ¶
type FxeHeader struct {
// contains filtered or unexported fields
}
FxeHeader is a parsed .fxe header.
func ParseFxeHeader ¶
ParseFxeHeader reads the JSON header with the browser's rules (parseFxeHeader). An unknown `req` entry returns an *UnsupportedError.
func ReadFxePrefix ¶
ReadFxePrefix reads magic, version, length and header from r, leaving r at the first byte of the body.
func (*FxeHeader) HasRecovery ¶
HasRecovery reports whether the file has a recovery key slot.
type Job ¶
type Job struct {
Marker *Marker
// contains filtered or unexported fields
}
Job is one decryption, between Open and Close.
func Open ¶
func Open(in string, opts OpenOptions) (*Job, error)
Open resolves the input and parses its marker. The returned Job must be closed. An *UnsupportedError comes back with a nil Job.
func (*Job) Out ¶
Out is where Run will write. For a .fxe without -o it is only known after Unlock (the original name comes out of the header); until then it is "".
type Keys ¶
Keys is what an unlock hands back: the FMK, for a names-encrypted folder the name key, and for a folder mid re-key the PREVIOUS FMK — what the files not re-wrapped yet are still under.
type Marker ¶
type Marker struct {
V int
Salt []byte
Iter int
Verify string
Fmk string // "" (v1), "kek" or "wrapped"
FmkPw string
Rk *RecoverySlot
Req []string
Names *NamesSlot
// Rekey is the previous FMK sealed under the current one, while a re-key
// (a password change that replaced the folder key) is re-wrapping the
// files' keys. Feature "rekey"; nil otherwise.
Rekey *RekeySlot
// ConvPending: an existing folder is being encrypted in place (feature
// "conv"); files it has not reached yet are still plaintext.
ConvPending bool
// Vault is the `vault` block of a vault's key file (level 3, feature
// "vault"; docs/E2E-VAULT-FORMAT.md); nil for levels 1 and 2.
Vault *e2e.VaultInfo
}
Marker is a parsed `.filex-e2e.json`.
func ParseMarker ¶
ParseMarker reads a marker with the browser's rules (parseMarkerDetailed). A well-formed v3 marker that requires an unknown feature returns an *UnsupportedError; anything malformed returns ErrNotMarker.
func (*Marker) UnlockPassword ¶
UnlockPassword derives the KEK (PBKDF2-SHA256), proves it against the verify blob, and returns the FMK (+ name key).
type NameKey ¶
type NameKey struct {
Long int // shortening threshold the folder was created with
RootID []byte // the encrypted root's own folder id
// contains filtered or unexported fields
}
NameKey is a folder's unwrapped name key.
func EnableNames ¶ added in v0.50.0
EnableNames raises a v2 folder to level 2: a new name key sealed under the folder key, v3 with "names" required and the slot pending until every entry is renamed (enableNames). Needs the folder key, not the password.
func NewNameKey ¶
NewNameKey imports a raw 64-byte name key and the root's 16-byte id.
func (*NameKey) DecryptEncoded ¶
DecryptEncoded decrypts an encoded ciphertext name sealed for the folder with id parentID. ok is false when it is not one.
func (*NameKey) DecryptStoredName ¶
func (k *NameKey) DecryptStoredName(stored string, parentID []byte, readSidecar func(name string) ([]byte, bool)) (string, NameState)
DecryptStoredName reads one stored name found in the folder with id parentID. readSidecar returns a sibling sidecar's content, or ok=false when there is no such file; it is only called for a long name.
func (*NameKey) DeriveDirID ¶
DeriveDirID is the id of a folder whose name was never encrypted: a keyed PRF of its parent's id and its name.
func (*NameKey) EffectiveDirID ¶
EffectiveDirID is the id the CHILDREN of a folder are sealed under: the one its stored name carries, or — a plaintext-named folder — the derived one.
func (*NameKey) EncryptName ¶
func (k *NameKey) EncryptName(plain string, parentID, dirID []byte) (EncryptedName, error)
EncryptName encrypts a plaintext name for the folder with id parentID, exactly as the browser does; dirID is the entry's own id when it is a folder, nil for a file. The decryptor does not need it; tests use it to build folders.
func (*NameKey) RecoverMoved ¶
func (k *NameKey) RecoverMoved(stored string, here []byte, ids [][]byte, readSidecar func(name string) ([]byte, bool)) (string, bool)
RecoverMoved tries a name sealed for ANOTHER folder of this encrypted folder (an entry moved outside filex): every id in ids but here. ok=false when none opens it.
type NamePassIO ¶ added in v0.50.0
type NamePassIO interface {
// List is the raw listing of a folder (stored names).
List(dir string) ([]ConvertRow, error)
// ReadSidecar is a sibling sidecar's content; ok is false when there is
// none.
ReadSidecar(dir, name string) ([]byte, bool)
WriteSidecar(dir, name, content string) error
// Rename gives row (in dir) the stored name `to`.
Rename(dir string, row ConvertRow, to string) error
// Stopped is asked between entries.
Stopped() bool
}
NamePassIO is what the name pass needs from wherever the folder is.
type NamePassProgress ¶ added in v0.50.0
type NamePassProgress struct {
// Seen is the entries found needing a name; Renamed of them were given
// one, Repaired of those had been moved without being re-sealed.
Seen, Renamed, Repaired int
// Failed is the entries that could not be renamed (no permission, a name
// a disk cannot hold, a name that cannot be read at all).
Failed int
Failures []ConvertFailure
}
NamePassProgress counts a pass.
type NamesSlot ¶
type NamesSlot struct {
Alg string `json:"alg"`
Enc string `json:"enc"`
Long int `json:"long"`
Key string `json:"key"`
// RootID is the encrypted root's own folder id (16 bytes, base64url):
// the associated data of every name directly inside the root.
RootID string `json:"root_id"`
Pending bool `json:"pending,omitempty"`
}
NamesSlot is the marker's encrypted-names slot (v3, feature "names").
type OpenOptions ¶
type OpenOptions struct {
// Out is the output directory. Empty: "<input>-decrypted" next to it
// (".zip" dropped).
Out string
// MarkerPath is an explicit .filex-e2e.json, for an input that does not
// carry its own (a subfolder, a single file, a zip made below the root).
MarkerPath string
// GOOS overrides runtime.GOOS for the output-name rules (tests).
GOOS string
// Generation, for a vault, decrypts that generation (one still kept)
// instead of the latest. 0: the latest that verifies.
Generation uint64
}
OpenOptions configure Open.
type RecoverySlot ¶
RecoverySlot is the marker's user-recovery-key slot.
type Result ¶
Result summarises a finished run.
func DecryptTree ¶
DecryptTree is Open + Unlock + Run + Close.
func DecryptVault ¶ added in v0.54.0
func DecryptVault(ctx context.Context, src VaultSource, k *VaultKeys, packLog2 int, opts VaultDecryptOptions) (*Result, error)
DecryptVault writes the whole tree of a vault - the latest generation that verifies, or the one asked for - into a new directory, all or nothing: into "<out>.partial-*" first, renamed into place when every file decrypted.
type StoredName ¶
type StoredName struct {
Kind NameKind
Hash string // long, longdir, sidecar: the 43-character hash they share
Encoded string // file, dir: the encoded ciphertext S
DirID []byte // dir, longdir: the folder's id
}
StoredName is a classified stored name.
func ClassifyStoredName ¶
func ClassifyStoredName(stored string) StoredName
ClassifyStoredName reports what a stored name is, without a key.
type UnsupportedError ¶
type UnsupportedError struct{ Features []string }
UnsupportedError: the folder requires a feature this build does not know. Opening it anyway is how an old client breaks a folder, so it is refused.
func (*UnsupportedError) Error ¶
func (e *UnsupportedError) Error() string
type VaultCommit ¶ added in v0.54.0
type VaultCommit struct {
// Index is the new generation as readers will decode it.
Index *VaultIndex
// File is the index file to store as v/idx/<generation>.fxi.
File []byte
// Written are the packs this writer stored (orphans if the index is
// never stored).
Written [][16]byte
}
VaultCommit is a sealed generation, ready to store.
type VaultContent ¶ added in v0.54.0
type VaultContent struct {
ID [16]byte
ChunkLog2 int
Extents []VaultExtent
}
VaultContent is where one version of a file is stored. A VaultContent is never changed once it is in a tree: an operation that moves bytes builds a new one, so trees can share them.
func (*VaultContent) BodyLen ¶ added in v0.54.0
func (c *VaultContent) BodyLen() int64
BodyLen is the length of the encrypted body: the extents joined.
type VaultDecryptOptions ¶ added in v0.54.0
type VaultDecryptOptions struct {
// Out is the directory to write; it must not exist.
Out string
// Generation, when not 0, decrypts that kept generation instead of the
// latest.
Generation uint64
// GOOS overrides runtime.GOOS for the output-name rules (tests).
GOOS string
// Sleep is VaultLoadOptions.Sleep.
Sleep func(ctx context.Context, d time.Duration) error
}
VaultDecryptOptions configure DecryptVault.
type VaultExtent ¶ added in v0.54.0
VaultExtent is a run of a file's encrypted body inside one pack.
type VaultGCPlan ¶ added in v0.54.0
type VaultGCPlan struct {
// Indexes are the expired generations whose index files go.
Indexes []uint64
// Packs go: graveyard packs whose last user expired, and orphans.
Packs [][16]byte
// Forget are the graveyard packs this pass deletes or finds gone: the
// next commit drops them from the graveyard (VaultWriter.ForgetGrave).
Forget [][16]byte
}
VaultGCPlan is one collection pass.
func PlanVaultGC ¶ added in v0.54.0
func PlanVaultGC(latest *VaultIndex, indexes, packs []VaultObject, mine map[[16]byte]bool, now time.Time, limit int) VaultGCPlan
PlanVaultGC works out one collection pass of at most limit deletions. latest is the latest generation, verified; indexes and packs are the listings; mine are the packs this writer stored since it took the lock (not orphans: its commit may still name them). Nothing is planned for a vault whose latest is damaged, carries extension bytes, or is missing.
func (VaultGCPlan) Empty ¶ added in v0.54.0
func (p VaultGCPlan) Empty() bool
Empty reports whether the pass deletes nothing.
type VaultGrave ¶ added in v0.54.0
VaultGrave is one graveyard entry: a pack the latest tree no longer uses, which an older generation still kept may use.
type VaultIndex ¶ added in v0.54.0
type VaultIndex struct {
Generation uint64
Tree *VaultTree
// Packs is the pack table: every pack the tree uses, ascending.
Packs [][16]byte
// Grave is the graveyard, ascending by pack id.
Grave []VaultGrave
// ReadOnly, when not "", is why a writer must not write this vault
// (extension bytes a newer filex wrote).
ReadOnly string
// BodyLen is the length of the body; Size the index file's (0 for an
// index that was not read from a file).
BodyLen int
Size int64
// ModTime is when the index file was written, where the source says.
ModTime time.Time
}
VaultIndex is one generation of a vault, decoded and checked.
func DecodeVaultBody ¶ added in v0.54.0
func DecodeVaultBody(plaintext []byte, packLog2 int, gen uint64) (*VaultIndex, error)
DecodeVaultBody reads and checks an index body - plaintext is the body followed by its zero padding - as the index of generation gen of a vault with packs of 2^packLog2 bytes. A body this build cannot read (another version, a flag it does not know) is an *UnsupportedError; anything that breaks a rule of the format wraps ErrVaultDamaged.
func OpenVaultIndex ¶ added in v0.54.0
OpenVaultIndex opens and checks the index file of generation gen. A file that is too large is refused before anything is decrypted.
type VaultKeys ¶ added in v0.54.0
type VaultKeys struct {
// contains filtered or unexported fields
}
VaultKeys derives the keys of one vault from its folder master key.
func NewVaultKeys ¶ added in v0.54.0
NewVaultKeys keeps a copy of fmk; Wipe zeroes it.
func (*VaultKeys) ContentKey ¶ added in v0.54.0
ContentKey is the key of the file version whose content id is contentID.
type VaultLatestSource ¶ added in v0.54.0
VaultLatestSource is a source that names its latest generation without a listing - a server answers `state`.
type VaultLoadOptions ¶ added in v0.54.0
type VaultLoadOptions struct {
// Generation, when not 0, loads that generation instead of the latest
// (`--generation N`): an older one that is still kept.
Generation uint64
// Seen is the highest generation this session has seen of the vault; a
// lower latest is a rollback (read-only). 0: none.
Seen uint64
// Sleep waits before a damaged latest is fetched again; nil sleeps for
// real (and stops with ctx).
Sleep func(ctx context.Context, d time.Duration) error
}
VaultLoadOptions configure LoadVault.
type VaultNode ¶ added in v0.54.0
type VaultNode struct {
Name string
Dir bool
MTime int64 // milliseconds since 1970
Size int64 // a file's plaintext bytes
// Content is where a file's bytes are; nil for a folder, a 0-byte file,
// or a file whose bytes are not stored yet (Local).
Content *VaultContent
// Local is the caller's own (`filex vault mount` keeps a pending file's
// spool here). It is never encoded.
Local any
// contains filtered or unexported fields
}
VaultNode is one entry of a vault tree.
func (*VaultNode) Child ¶ added in v0.54.0
Child is the entry called name directly inside n, or nil.
func (*VaultNode) Children ¶ added in v0.54.0
Children are the entries directly inside n, in canonical order (by the bytes of their names).
func (*VaultNode) HasExt ¶ added in v0.54.0
HasExt reports whether the entry carries extension bytes a newer filex wrote.
type VaultObject ¶ added in v0.54.0
type VaultObject struct {
Generation uint64 // an index file
Pack [16]byte // a pack
Size int64
ModTime time.Time // zero: the source does not say
}
VaultObject is one index file or pack, as a listing shows it.
type VaultPackReader ¶ added in v0.54.0
VaultPackReader reads n bytes of a stored pack from off (repacking).
type VaultPackSink ¶ added in v0.54.0
VaultPackSink stores one closed pack: its id and its 2^pack bytes.
type VaultReader ¶ added in v0.54.0
type VaultReader struct {
// contains filtered or unexported fields
}
VaultReader reads files of one vault.
func NewVaultReader ¶ added in v0.54.0
func NewVaultReader(src VaultSource, keys *VaultKeys) *VaultReader
NewVaultReader reads through src with keys.
func (*VaultReader) ReadChunk ¶ added in v0.54.0
ReadChunk returns plaintext chunk i of a file (the mount's block cache holds these).
type VaultSource ¶ added in v0.54.0
type VaultSource interface {
// ListIndexes lists the index files (well-formed names only).
ListIndexes(ctx context.Context) ([]VaultObject, error)
// ListPacks lists the packs (well-formed names only).
ListPacks(ctx context.Context) ([]VaultObject, error)
// ReadIndex reads one index file whole. More than e2e.VaultIndexReadMax
// bytes is refused before they are read (a damage error).
ReadIndex(ctx context.Context, generation uint64) ([]byte, error)
// ReadPack reads n bytes of a pack from off.
ReadPack(ctx context.Context, id [16]byte, off, n int64) ([]byte, error)
}
VaultSource is where a vault's files come from.
type VaultState ¶ added in v0.54.0
type VaultState struct {
// Index is the generation shown: the latest that verifies, or the one
// asked for. An empty vault at generation 0 has an empty one.
Index *VaultIndex
// Latest is the newest generation present (Index.Generation unless it
// is damaged or an older one was asked for).
Latest uint64
// DamagedLatest: the newest generation does not verify; Index is an
// older one, read-only, until its owner continues from it.
DamagedLatest bool
// RolledBack: the latest is older than one this session saw.
RolledBack bool
}
VaultState is what a reader has loaded.
func LoadVault ¶ added in v0.54.0
func LoadVault(ctx context.Context, src VaultSource, k *VaultKeys, packLog2 int, opt VaultLoadOptions) (*VaultState, error)
LoadVault finds and opens the generation to show.
func (*VaultState) ReadOnly ¶ added in v0.54.0
func (s *VaultState) ReadOnly() string
ReadOnly is why a writer must not write from this state, or "".
func (*VaultState) Writable ¶ added in v0.54.0
func (s *VaultState) Writable() error
Writable is ErrVaultReadOnly, with the reason, when a writer must not write from this state; nil when it may.
type VaultTree ¶ added in v0.54.0
type VaultTree struct {
// contains filtered or unexported fields
}
VaultTree is a vault's tree of files and folders.
func (*VaultTree) CheckMkdir ¶ added in v0.54.0
CheckMkdir reports whether Mkdir(p) would succeed, without changing anything.
func (*VaultTree) CheckMove ¶ added in v0.54.0
CheckMove reports whether Move(from, to) would succeed.
func (*VaultTree) CheckPutFile ¶ added in v0.54.0
CheckPutFile reports whether PutFile(p) would succeed, and whether it would add an entry (false: it replaces a file).
func (*VaultTree) Clone ¶ added in v0.54.0
Clone copies the tree. Contents are shared (they never change in place); Local is copied as it is.
func (*VaultTree) Len ¶ added in v0.54.0
Len is the number of entries (files and folders), the root not counted.
func (*VaultTree) Lookup ¶ added in v0.54.0
Lookup finds the entry at p; nil when there is none. "" is the root.
func (*VaultTree) Move ¶ added in v0.54.0
Move gives the entry at from a new folder or name; its mtime, its contents and (a folder) everything in it are kept.
func (*VaultTree) PutFile ¶ added in v0.54.0
PutFile makes a new file, or gives the file at p new contents: nothing of the old version is kept but its place in the tree. Local is cleared.
func (*VaultTree) Remove ¶ added in v0.54.0
Remove takes the entry at p out of the tree, a folder with everything in it.
type VaultWriter ¶ added in v0.54.0
type VaultWriter struct {
// contains filtered or unexported fields
}
VaultWriter builds the next generation of a vault.
func NewVaultWriter ¶ added in v0.54.0
func NewVaultWriter(cfg VaultWriterConfig) (*VaultWriter, error)
NewVaultWriter starts the generation after cfg.Base.
func (*VaultWriter) Commit ¶ added in v0.54.0
func (w *VaultWriter) Commit(ctx context.Context) (*VaultCommit, error)
Commit closes the open pack and seals the new generation. The caller stores Commit.File as the index of Commit.Index.Generation; until that succeeded nothing of the change is visible, and the writer is spent either way.
func (*VaultWriter) Delete ¶ added in v0.54.0
func (w *VaultWriter) Delete(p string) error
Delete removes a file, or a folder with everything in it.
func (*VaultWriter) ForgetGrave ¶ added in v0.54.0
func (w *VaultWriter) ForgetGrave(ids [][16]byte)
ForgetGrave drops packs a collection deleted from the graveyard this commit writes.
func (*VaultWriter) Generation ¶ added in v0.54.0
func (w *VaultWriter) Generation() uint64
Generation is the generation this writer commits.
func (*VaultWriter) Mkdir ¶ added in v0.54.0
func (w *VaultWriter) Mkdir(p string, mtime int64) error
Mkdir makes a new folder.
func (*VaultWriter) Move ¶ added in v0.54.0
func (w *VaultWriter) Move(from, to string) error
Move gives an entry a new folder or name; mtime and contents are kept.
func (*VaultWriter) Repack ¶ added in v0.54.0
func (w *VaultWriter) Repack(ctx context.Context, packs [][16]byte, read VaultPackReader) error
Repack copies the live extents in packs - entry by entry in index order, each entry's extents in order, the bytes as they are, nothing encrypted again - into new packs by the canonical layout. Those packs go to the graveyard when this generation commits.
func (*VaultWriter) Tree ¶ added in v0.54.0
func (w *VaultWriter) Tree() *VaultTree
Tree is the tree as the operations so far left it. Do not change it.
func (*VaultWriter) Warning ¶ added in v0.54.0
func (w *VaultWriter) Warning() string
Warning is what to say before a change to this vault, or "".
func (*VaultWriter) Write ¶ added in v0.54.0
func (w *VaultWriter) Write(ctx context.Context, p string, mtime int64, r io.Reader, size int64) (*VaultNode, error)
Write stores new contents for the file at p - a new file, or a new version of one: always a new content id, even for the same bytes. r must hold exactly size bytes.
type VaultWriterConfig ¶ added in v0.54.0
type VaultWriterConfig struct {
Keys *VaultKeys
PackLog2 int
// Base is the latest generation, which the commit follows; nil is an
// empty vault at generation 0 (the creation commit writes generation 1).
Base *VaultIndex
// Rand is where every random byte comes from; nil is crypto/rand.
Rand io.Reader
// Sink stores packs as they close.
Sink VaultPackSink
}
VaultWriterConfig configures NewVaultWriter.