1 | ![logo](https://raw.githubusercontent.com/carlos8f/salty-gui/master/public/salt-shaker-inverse.png) salty
|
2 | =====
|
3 |
|
4 | Alternative public key encryption
|
5 |
|
6 | ## Description
|
7 |
|
8 | Salty is a [nodejs](https://nodejs.org/)-powered CLI-based alternative to PGP/GPG using [NaCl](https://en.wikipedia.org/wiki/NaCl_(software)) instead of RSA/DSA.
|
9 |
|
10 | Commits and tags in this repo are signed with GPG key [5FBB 2F98 3862 1AFF](https://keybase.io/carlos8f).
|
11 |
|
12 | ### Upcoming GUI
|
13 |
|
14 | A GUI is being developed as a node HTTP server you can host locally or remotely to access your wallet. Follow its development [here](https://github.com/carlos8f/salty-gui).
|
15 |
|
16 | ### Features
|
17 |
|
18 | - NO [3rd parties](https://peerio.com/pricing.html), NO [p2p network](https://en.wikipedia.org/wiki/PRISM_(surveillance_program)), NO [browser js](https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/), NO [exotic/compiled deps](https://www.openssl.org/news/vulnerabilities.html), no [Comodo SSL](https://www.reddit.com/r/programming/comments/4pj89t/support_lets_encrypt_get_cloudflare_cdn_et_al_to/), and NO [shady corporations](https://github.com/VirgilSecurity). PERIOD.
|
19 | - general purpose CLI, lightweight library attached
|
20 | - audited, bundled dependencies - no install scripts or backdoors
|
21 | - supports anonymous-sender or signed/verified messaging
|
22 | - sharable pubkey string that can fit in a single tweet
|
23 | - does NOT use your ssh keys, pgp keys, or anything RSA
|
24 | - encrypt public key is always ephemeral - does NOT leak metadata
|
25 | - sender identity is deniable, unless they explicitly commit to sign the message
|
26 | - file length hidden with padding
|
27 | - public signing/verifying with detached signatures
|
28 | - binary or "ascii armor" PEM output
|
29 | - import/export your wallet folder - PEM encoded and secretboxed with Scrypt KDF
|
30 | - (new in 3.1) can use anonymous private [Github gists](https://gist.github.com/) to remotely store salty messages
|
31 | - (new in 3.1) full tar/gz support for encrypting/decrypting directories (supports symmetric or asymmetric cipher)
|
32 | - MIT-licensed
|
33 |
|
34 | ## Install (Mac OSX)
|
35 |
|
36 | ```
|
37 | $ brew tap carlos8f/tap
|
38 | $ brew install salty
|
39 | ```
|
40 |
|
41 | ## Other UNIX-based platforms:
|
42 |
|
43 | Install first: [nodejs](https://nodejs.org/)
|
44 |
|
45 | ```
|
46 | $ wget https://github.com/carlos8f/salty/archive/v4.0.0.tar.gz
|
47 | $ shasum -a 256 v4.0.0.tar.gz
|
48 | 98d9b9a5bb6e11e1292a8153a4c8b0741bb53cefce826783297aa7df55c2f903 v4.0.0.tar.gz
|
49 | $ tar -xf v4.0.0.tar.gz
|
50 | $ sudo ln -sf `pwd`/salty-4.0.0/bin/salty /usr/local/bin/salty
|
51 | ```
|
52 |
|
53 | ## Useful links
|
54 |
|
55 | - [S8F Console: How to use Salty](https://s8f.org/1465282150/) - Basic demonstration of the Salty CLI
|
56 | - [Salty: PGP Evolved](https://s8f.org/1465262642/) - How Salty improves on the PGP model
|
57 |
|
58 | ## Format
|
59 |
|
60 | Byte counts are in `()` parenthesis.
|
61 |
|
62 | ### Salty wallet
|
63 |
|
64 | Designed to allow both decryption and signing.
|
65 |
|
66 | ```
|
67 | decryption signing
|
68 | -------------- + -----------
|
69 | decryptSk (32) signSk (64)
|
70 | ```
|
71 |
|
72 | Example (wallets are stored as encrypted PEM on disk)
|
73 |
|
74 | ```
|
75 | -----BEGIN SALTY WALLET-----
|
76 | Proc-Type: 4,ENCRYPTED
|
77 | DEK-Info: NACL-SCRYPT,IP3NRMw15AGYyU56xwYPVJFa4Xx0aock
|
78 |
|
79 | OjCNhUvjNml3bebBVsIBpTBdvWSRkUG6vVZkdpzFZf9Ak/Bh0ghaXsEhuAiElEMy
|
80 | 2ghCEF5oQVO3dAWdflcvuVH3CSXlPlBfXWr6Y0EEOST3jYwaRS8Qfa2786YNBYCm
|
81 | NBm4au6wbuVp8dL41jhLeQ==
|
82 | -----END SALTY WALLET-----
|
83 | ```
|
84 |
|
85 | ### Salty pubkey
|
86 |
|
87 | Designed to be sharable, human-readable, and unique.
|
88 |
|
89 | ```
|
90 | public keys optional meta
|
91 | ----------------------------------------- [space] -------- --------
|
92 | base58(encryptPk (32) + verifyPk (32)) "{name}" <{email}>
|
93 |
|
94 | ```
|
95 |
|
96 | Example:
|
97 |
|
98 | ```
|
99 | 2ZuU37oJ1erD85AzVohXq6Y74GHv2hjNYB9fu3P5o9rsGSvRo19HK2wTL4MLma3N6gVFqXN81VTqQ6apBhc5Kezq "Carlos" <carlos@s8f.org>
|
100 | ```
|
101 |
|
102 | ### Salty file
|
103 |
|
104 | Designed to allow anonymous or signed messages, and verify message integrity.
|
105 |
|
106 | ```
|
107 | required meta ciphertext
|
108 | -------------- + ----------
|
109 | ephemeral (80) plaintext
|
110 | ```
|
111 |
|
112 | ### Ephemeral
|
113 |
|
114 | Designed to hide the message and header inside an anonymously encrypted/authenticated payload.
|
115 |
|
116 | ```
|
117 | random random message length (encrypted, 24 bytes)
|
118 | -------------- + ---------- + ---------------------------------------
|
119 | encryptPk (32) nonce (24) totalSize (8 bytes, big endian)
|
120 | ```
|
121 |
|
122 | ### Plaintext
|
123 |
|
124 | Appends a header to the message for verification, and pads the plaintext with null bytes.
|
125 |
|
126 | ```
|
127 | --------- + ------- + -------------------
|
128 | message header null bytes (?)
|
129 | ```
|
130 |
|
131 | ### Header
|
132 |
|
133 | Always contains a sha256 HMAC to authenticate the message, and optionally contains a signature from the sender.
|
134 |
|
135 | ```
|
136 | hash: hex( sha256_hmac( shared_secret ) of message )
|
137 | [from-salty-id]: base58(encryptPk (32) + verifyPk (32))
|
138 | [to-salty-id]: base58(encryptPk (32) + verifyPk (32))
|
139 | [signature]: base58( detached sig of previous headers )
|
140 | ```
|
141 |
|
142 | Example:
|
143 |
|
144 | ```
|
145 | hash: 3a5a42ad3cadea1ac4abd5169a7a1c2b2017404e00b9f08c5dee6c205f7a197a
|
146 | from-salty-id: 2ZuU37oJ1erD85AzVohXq6Y74GHv2hjNYB9fu3P5o9rsGSvRo19HK2wTL4MLma3N6gVFqXN81VTqQ6apBhc5Kezq
|
147 | to-salty-id: self
|
148 | signature: 5V1c1P5a8dqDVMPhwqnDF39ZrHpaw7jhetEgHyPUkjM8tYvugPzDJ3xyhD9WdJQ4AjwYkN2XdWhnTB3GTRMJuAEd
|
149 | ```
|
150 |
|
151 | ### Signature
|
152 |
|
153 | Always contains the signer's public keys, a sha256 HMAC to authenticate the file, keyed with a 32-byte random nonce, and a signature.
|
154 |
|
155 | ```
|
156 | from-salty-id: base58(encryptPk (32) + verifyPk (32))
|
157 | hash-algorithm: algorithm
|
158 | hash: hex( algorithm( file ) )
|
159 | signature: base58( detached sig of previous headers )
|
160 | ```
|
161 |
|
162 | Example:
|
163 |
|
164 | ```
|
165 | from-salty-id: 2ZuU37oJ1erD85AzVohXq6Y74GHv2hjNYB9fu3P5o9rsGSvRo19HK2wTL4MLma3N6gVFqXN81VTqQ6apBhc5Kezq
|
166 | hash-algorithm: sha256
|
167 | hash: 19e406822f9eac2c19f0a0d59c1ab1f554e354fadbc1836f9e10858ce227ed2c
|
168 | signature: 49VPoEqf3iNrpaWCjEejfe2vqT8ZHHkb68U6JRzxCEqWSoVoe7AjPEN2c3XYXgCuW7P3htsWbXZdF6LAsoyXoE3v
|
169 | ```
|
170 |
|
171 | ## Usage
|
172 |
|
173 | ```
|
174 | Usage: salty [options] [command]
|
175 |
|
176 |
|
177 | Commands:
|
178 |
|
179 | init [options] initialize or update a wallet
|
180 | id|pubkey output your shareable pubkey string
|
181 | import|i <pubkey|url|file> import a pubkey
|
182 | ls|l list imported keys
|
183 | rm <pubkey|email> remove pubkey
|
184 | encrypt|e [options] [infile|indir] [outfile] encrypt a file
|
185 | decrypt|d [options] <infile|gist> [outfile] decrypt and verify a file
|
186 | sign|s [options] <infile> [outfile] create a signature
|
187 | verify|v [options] <insig> [infile] verify a signature
|
188 | save [indir] [outfile] save an encrypted backup of your wallet
|
189 | restore [infile] [outdir] restore your wallet from a backup
|
190 | encode [infile] output base58-encoded data to STDOUT
|
191 | decode [infile] output base58-decoded data to STDOUT
|
192 | *
|
193 |
|
194 | Options:
|
195 |
|
196 | -h, --help output usage information
|
197 | -V, --version output the version number
|
198 | -w, --wallet <dir> wallet location (default: ~/.salty)
|
199 | -F, --force do it anyway
|
200 | ```
|
201 |
|
202 | ### salty encrypt
|
203 |
|
204 | ```
|
205 | Usage: encrypt|e [options] [infile|indir] [outfile]
|
206 |
|
207 | encrypt a file
|
208 |
|
209 | Options:
|
210 |
|
211 | -h, --help output usage information
|
212 | -t, --to <email> email address to encrypt for. (must be imported first. default: self)
|
213 | -m, --message compose a message instead of using [infile] (implies -a)
|
214 | -s, --sign sign the message to reveal/prove our identity
|
215 | -H, --header <key: value> add a custom header (repeatable)
|
216 | -a, --armor output ASCII armor to STDOUT
|
217 | -g, --gist upload encrypted result as a gist
|
218 | -F, --force ignore warnings and do it
|
219 | -D, --delete delete the original file after encryption
|
220 | ```
|
221 |
|
222 | ### salty decrypt
|
223 |
|
224 | ```
|
225 | Usage: decrypt|d [options] <infile|gist> [outfile]
|
226 |
|
227 | decrypt and verify a file
|
228 |
|
229 | Options:
|
230 |
|
231 | -h, --help output usage information
|
232 | -s, --sig require a signature
|
233 | -a, --armor expect ASCII armor, output to STDOUT
|
234 | -g, --gist download the encrypted input from a gist
|
235 | -F, --force ignore warnings and do it
|
236 | -D, --delete delete the salty file after verification
|
237 |
|
238 | ```
|
239 |
|
240 | ### salty sign
|
241 |
|
242 | ```
|
243 | Usage: sign|s [options] <infile> [outfile]
|
244 |
|
245 | create a signature
|
246 |
|
247 | Options:
|
248 |
|
249 | -h, --help output usage information
|
250 | -H, --header <key: value> add a custom header (repeatable)
|
251 | -h, --hash <alg> hash algorithm (default: sha256)
|
252 | -a, --armor output ASCII armor to STDOUT
|
253 | -F, --force ignore warnings and do it
|
254 | ```
|
255 |
|
256 | ### salty verify
|
257 |
|
258 | ```
|
259 | Usage: verify|v [options] <insig> [infile]
|
260 |
|
261 | verify a signature
|
262 |
|
263 | Options:
|
264 |
|
265 | -h, --help output usage information
|
266 | -a, --armor expect ASCII armor, output to STDOUT
|
267 | ```
|
268 |
|
269 | ## Log
|
270 |
|
271 | ### release 4.0
|
272 |
|
273 | - now you can regenerate your decryption key with `salty init --regen`
|
274 | - switch to base58-encoding for everything but hashes
|
275 | - hashes are now hex-encoded
|
276 | - `\r\n` newlines in header/PEM changed to `\n`
|
277 | - Custom header support for encryption or signing
|
278 | - import now dedupes on verifyPk/email
|
279 | - key removal by pubkey/email now supported
|
280 | - "attached" signatures now available with ASCII armor flag
|
281 | - signatures can be verified without previous setup (wallet creation)
|
282 | - signatures support arbitrary hash algorithms
|
283 | - added `--no-translate` flag to output raw header
|
284 |
|
285 | ### release v3.1.0
|
286 |
|
287 | - Added anonymous gist support
|
288 | - Added tar/gz support for encrypting directories
|
289 |
|
290 | - - -
|
291 |
|
292 | ### License: MIT
|
293 |
|
294 | - Copyright (C) 2016 Carlos Rodriguez (http://s8f.org/)
|
295 | - Copyright (C) 2016 Terra Eclipse, Inc. (http://www.terraeclipse.com/)
|
296 |
|
297 | Permission is hereby granted, free of charge, to any person obtaining a copy
|
298 | of this software and associated documentation files (the "Software"), to deal
|
299 | in the Software without restriction, including without limitation the rights
|
300 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
301 | copies of the Software, and to permit persons to whom the Software is furnished
|
302 | to do so, subject to the following conditions:
|
303 |
|
304 | The above copyright notice and this permission notice shall be included in
|
305 | all copies or substantial portions of the Software.
|
306 |
|
307 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
308 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
309 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
310 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
311 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
312 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
313 | SOFTWARE. |
\ | No newline at end of file |