Documentation
¶
Index ¶
- Constants
- Variables
- 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 EncodedOf(stored string, readSidecar func(name string) ([]byte, bool)) (string, bool)
- func HasFxeMagic(b []byte) bool
- func HasMagic(b []byte) bool
- func ItemPrefixForSidecar(sidecar string) (string, bool)
- func NameProblem(name string) string
- func ParseRecoveryKey(s string) ([]byte, bool)
- func SidecarNameFor(stored string) (string, bool)
- func StreamCiphertextSize(n int64, log2 int) int64
- func ValidChunkLog2(n int) bool
- type CorruptError
- 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 NameState
- type NamesSlot
- type OpenOptions
- type RecoverySlot
- type RekeySlot
- type Result
- type StoredName
- type UnsupportedError
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 (
// StreamChunkLog2 is the chunk size writers use (2^20 = 1 MiB).
StreamChunkLog2 = 20
)
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 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 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 FxeMagic = []byte("filexfxe")
FxeMagic starts every single encrypted file.
var MagicPrefix = []byte("filexe2e")
MagicPrefix starts every encrypted file.
Functions ¶
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 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 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 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 SidecarNameFor ¶
SidecarNameFor returns the sidecar that belongs to a long stored name (file or folder).
func StreamCiphertextSize ¶
StreamCiphertextSize is the body length for a plaintext of n bytes.
func ValidChunkLog2 ¶
ValidChunkLog2 reports whether a reader accepts this chunk size.
Types ¶
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 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
}
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 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 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
}
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.
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