sefy-cli 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +212 -0
  2. package/package.json +43 -27
package/README.md ADDED
@@ -0,0 +1,212 @@
1
+ <p align="center"><img src="https://github.com/lacodda/sefy/raw/main/assets/banner.svg" alt="sefy - an inconspicuous encrypted vault" width="720"></p>
2
+
3
+ <p align="center">
4
+ <a href="https://crates.io/crates/sefy"><img src="https://img.shields.io/crates/v/sefy?style=flat-square" alt="crates.io"></a>
5
+ <a href="https://www.npmjs.com/package/sefy-cli"><img src="https://img.shields.io/npm/v/sefy-cli?style=flat-square" alt="npm"></a>
6
+ <a href="https://github.com/lacodda/sefy/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/lacodda/sefy/ci.yml?branch=main&style=flat-square" alt="CI"></a>
7
+ <a href="https://github.com/lacodda/sefy/blob/main/LICENSE"><img src="https://img.shields.io/crates/l/sefy?style=flat-square" alt="MIT"></a>
8
+ </p>
9
+
10
+ # sefy
11
+
12
+ Every way of storing secrets announces itself. A `.kdbx` file says "password
13
+ database". age and gpg write a header. VeraCrypt wants a container and a mount.
14
+ Whoever looks at your disk, your backup drive or your cloud folder can tell
15
+ exactly where the interesting file is.
16
+
17
+ **sefy is a secret store whose file looks like nothing.** Notes, credentials and
18
+ files live in an encrypted SQLite database sealed into a single blob with no
19
+ magic bytes, no header and no extension convention. Call it `notes.bak`, leave
20
+ it among your other backups, and there is nothing to notice.
21
+
22
+ ```
23
+ $ head -c 32 notes.bak | xxd
24
+ 00000000: 65b0 1375 a933 361d 89e2 9338 1b8d cb76 e..u.36....8...v
25
+ 00000010: 0749 7515 ad12 dd40 1c3e 3e93 9282 4b5a .Iu....@.>>...KZ
26
+ ```
27
+
28
+ ## Threat model, honestly
29
+
30
+ - **Protects against:** a passing glance, a curious file listing, a cloud-side
31
+ scanner looking for known formats, anyone who does not already know the file
32
+ is a vault.
33
+ - **Does not protect against:** forensic analysis - a high-entropy headerless
34
+ file is recognizable as *some* container to an examiner - or anyone who can
35
+ compel you to give up the password.
36
+
37
+ sefy is **inconspicuous, not deniable**, and it will not pretend otherwise.
38
+
39
+ ## A day with it
40
+
41
+ Point sefy at a file. There is no default location: a vault at a predictable
42
+ path would undo the whole point.
43
+
44
+ ```
45
+ $ export SEFY_VAULT=~/backups/notes.bak
46
+
47
+ $ sefy init
48
+ Master password:
49
+ created /home/you/backups/notes.bak
50
+ ```
51
+
52
+ Put things in. Notes, logins, and files kept byte for byte.
53
+
54
+ ```
55
+ $ sefy add note "bank card" --text "PIN 4815" --tag money
56
+ added "bank card" as 1
57
+
58
+ $ sefy add credential mail --login someone@example.com --url https://mail.example.com --tag mail
59
+ Password for this item:
60
+ added "mail" as 2
61
+
62
+ $ sefy add file ~/.ssh/id_ed25519 --tag keys
63
+ added "id_ed25519" as 3
64
+ ```
65
+
66
+ Look around.
67
+
68
+ ```
69
+ $ sefy ls
70
+ 3 id_ed25519 file [keys]
71
+ 2 mail credential [mail]
72
+ 1 bank card note [money]
73
+
74
+ $ sefy show mail
75
+ id: 2
76
+ title: mail
77
+ kind: credential
78
+ tags: mail
79
+ login: someone@example.com
80
+ password: <hidden — use sefy get>
81
+ url: https://mail.example.com
82
+ ```
83
+
84
+ Take a secret out. It goes to the clipboard and is taken back off after 45
85
+ seconds - sefy clears it only if the secret is still what is sitting there, so
86
+ anything you copied meanwhile is left alone.
87
+
88
+ ```
89
+ $ sefy get mail
90
+ copied password of "mail" to the clipboard; clearing in 45s
91
+ clipboard cleared
92
+
93
+ $ sefy get "bank card" --stdout
94
+ PIN 4815
95
+ ```
96
+
97
+ Items are addressed by title, by an exact id, or by text to search for. When
98
+ your words could mean more than one thing, sefy shows what they could mean
99
+ instead of guessing:
100
+
101
+ ```
102
+ $ sefy get ma
103
+ error: 2 items match "ma":
104
+ 4 mailing list note
105
+ 2 mail credential
106
+ narrow the text, or use an id
107
+ ```
108
+
109
+ Two machines, two copies, both edited? Fold one into the other. Where they
110
+ disagree about the same item, sefy keeps both versions rather than letting a
111
+ timestamp decide which password you get to keep:
112
+
113
+ ```
114
+ $ sefy merge ~/from-laptop.bak
115
+ Password for /home/you/from-laptop.bak:
116
+ merged: 1 added, 1 updated, 1 unchanged
117
+
118
+ 1 item changed on both sides and could not be resolved here.
119
+ This vault's version was kept; the incoming one is beside it:
120
+ "mail" → also kept as "mail (conflicted copy)"
121
+ Compare them, keep the right one, and remove the other.
122
+ ```
123
+
124
+ A vault is never a trap. `sefy export` writes everything back out as plain
125
+ JSON - which is exactly as sensitive as the vault and protects nothing, so the
126
+ command makes you say so out loud:
127
+
128
+ ```
129
+ $ sefy export -o backup.json
130
+ error: export writes every secret in this vault in the clear
131
+ the resulting file protects nothing — encrypt it, or delete it when done
132
+ pass --i-know-this-writes-plaintext to go ahead
133
+ ```
134
+
135
+ Full command reference: **[lacodda.github.io/sefy](https://lacodda.github.io/sefy/)**.
136
+
137
+ ## How it works
138
+
139
+ - The master password is stretched into a key with **Argon2id**.
140
+ - The whole SQLite database is sealed with **XChaCha20-Poly1305** (AEAD).
141
+ - The file on disk is `salt ‖ nonce ‖ ciphertext`. Salt and nonce are fresh on
142
+ every save, so two saves of identical content share no prefix - and the
143
+ format version lives *inside* the ciphertext, because a version byte in the
144
+ clear would be the signature the format exists to avoid.
145
+ - The decrypted database exists **only in memory**. SQLite is never given a
146
+ path, so no page, journal or temporary file lands on disk.
147
+ - Saves are atomic: ciphertext goes to a temporary file, is synced, and is
148
+ renamed over the vault. A crash leaves either the old vault or the new one,
149
+ and never plaintext.
150
+
151
+ Details and rationale: [ADR-0001](https://github.com/lacodda/sefy/blob/main/docs/adr/0001-vault-file-format-and-cryptography.md).
152
+
153
+ ## Install
154
+
155
+ **One-line installers.** Windows (PowerShell):
156
+
157
+ ```powershell
158
+ irm https://raw.githubusercontent.com/lacodda/sefy/main/tools/install.ps1 | iex
159
+ ```
160
+
161
+ macOS / Linux:
162
+
163
+ ```bash
164
+ curl -fsSL https://raw.githubusercontent.com/lacodda/sefy/main/tools/install.sh | sh
165
+ ```
166
+
167
+ **cargo** - `cargo install sefy`
168
+
169
+ **npm** - `npm install -g sefy-cli`
170
+
171
+ **Binary releases** - grab the archive for your platform from [Releases](https://github.com/lacodda/sefy/releases/latest)
172
+ (Windows x86_64, Linux x86_64, macOS arm64), unpack and put `sefy` on your
173
+ `PATH`.
174
+
175
+ Both installers take the newest release by default; set `SEFY_VERSION` to a tag
176
+ to pin one, and `SEFY_INSTALL_DIR` to choose where the binary lands.
177
+
178
+ Shell completions: `sefy completions bash` (also `zsh`, `fish`, `powershell`,
179
+ `elvish`).
180
+
181
+ ## Stability
182
+
183
+ The **vault file format is stable at version 1**. Files written by this release
184
+ will stay readable: any future change to the format arrives as version 2, able
185
+ to read version 1 and migrate it. The Argon2 parameters are part of that
186
+ promise, not a tuning knob.
187
+
188
+ The database inside the ciphertext is versioned separately, and it does move:
189
+ 0.2.0 added an identity to items so two copies of a vault can be merged. A vault
190
+ from 0.1.x opens, is migrated on the way in, and is still readable by 0.1.x
191
+ afterwards - the file on disk did not change shape.
192
+
193
+ Released versions and what landed in each: [CHANGELOG on the Releases page](https://github.com/lacodda/sefy/releases).
194
+
195
+ ## Building
196
+
197
+ ```
198
+ cargo build --release # workspace: sefy-core (library) + sefy (CLI)
199
+ cargo test # unit, integration and doc tests
200
+ ```
201
+
202
+ Use a release build for daily work: Argon2id is deliberately expensive, and an
203
+ unoptimized build makes it several times slower still.
204
+
205
+ The library is published separately as [`sefy-core`](https://crates.io/crates/sefy-core)
206
+ if you want vaults from your own code. The documentation site lives in
207
+ [`docs/`](https://github.com/lacodda/sefy/tree/main/docs); architecture decision
208
+ records are in [`docs/adr/`](https://github.com/lacodda/sefy/tree/main/docs/adr).
209
+
210
+ ## License
211
+
212
+ [MIT](https://github.com/lacodda/sefy/blob/main/LICENSE)
package/package.json CHANGED
@@ -1,27 +1,43 @@
1
- {
2
- "name": "sefy-cli",
3
- "version": "0.1.1",
4
- "sefy": {
5
- "binary": "v0.1.1"
6
- },
7
- "description": "An inconspicuous encrypted store for notes, credentials and files",
8
- "license": "MIT",
9
- "author": "Kirill Lakhtachev <lahtachev@gmail.com> (https://lacodda.com)",
10
- "homepage": "https://lacodda.github.io/sefy/",
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/lacodda/sefy.git"
14
- },
15
- "keywords": ["cli", "secrets", "password-manager", "encryption", "vault"],
16
- "bin": {
17
- "sefy": "run.js"
18
- },
19
- "files": ["download.js", "install.js", "run.js"],
20
- "scripts": {
21
- "postinstall": "node install.js"
22
- },
23
- "os": ["win32", "darwin", "linux"],
24
- "engines": {
25
- "node": ">=18"
26
- }
27
- }
1
+ {
2
+ "name": "sefy-cli",
3
+ "version": "0.2.0",
4
+ "sefy": {
5
+ "binary": "v0.2.0"
6
+ },
7
+ "description": "An inconspicuous encrypted store for notes, credentials and files",
8
+ "license": "MIT",
9
+ "author": "Kirill Lakhtachev <lahtachev@gmail.com> (https://lacodda.com)",
10
+ "homepage": "https://lacodda.github.io/sefy/",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/lacodda/sefy.git"
14
+ },
15
+ "keywords": [
16
+ "cli",
17
+ "secrets",
18
+ "password-manager",
19
+ "encryption",
20
+ "vault"
21
+ ],
22
+ "bin": {
23
+ "sefy": "run.js"
24
+ },
25
+ "files": [
26
+ "download.js",
27
+ "install.js",
28
+ "run.js",
29
+ "README.md"
30
+ ],
31
+ "scripts": {
32
+ "prepack": "node -e \"require('fs').copyFileSync('../README.md','README.md')\"",
33
+ "postinstall": "node install.js"
34
+ },
35
+ "os": [
36
+ "win32",
37
+ "darwin",
38
+ "linux"
39
+ ],
40
+ "engines": {
41
+ "node": ">=18"
42
+ }
43
+ }