salty

Alternative public key encryption

Description

Salty is a nodejs-powered CLI-based alternative to PGP/GPG using NaCl instead of RSA/DSA.

Commits and tags in this repo are signed with GPG key 5FBB 2F98 3862 1AFF.

Upcoming GUI

A GUI is being developed as a node HTTP server you can host locally or remotely to access your wallet. Follow its development here.

Features

NO 3rd parties, NO p2p network, NO browser js, NO exotic/compiled deps, no Comodo SSL, and NO shady corporations. PERIOD.

general purpose CLI, lightweight library attached

audited, bundled dependencies - no install scripts or backdoors

supports anonymous-sender or signed/verified messaging

sharable pubkey string that can fit in a single tweet

does NOT use your ssh keys, pgp keys, or anything RSA

encrypt public key is always ephemeral - does NOT leak metadata

sender identity is deniable, unless they explicitly commit to sign the message

file length hidden with padding

public signing/verifying with detached signatures

binary or "ascii armor" PEM output

import/export your wallet folder - PEM encoded and secretboxed with Scrypt KDF

(new in 3.1) can use anonymous private Github gists to remotely store salty messages

(new in 3.1) full tar/gz support for encrypting/decrypting directories (supports symmetric or asymmetric cipher)

MIT-licensed

Install (Mac OSX)

$ brew tap carlos8f/tap $ brew install salty

Other UNIX-based platforms:

Install first: nodejs

$ wget https://github.com/carlos8f/salty/archive/v4.1.0.tar.gz $ shasum -a 256 v4.1.0.tar.gz 3eb6e0bcb1461af2aa88d81c9be5c69b1b0069e40a30abb90c11420c88504126 v4.1.0.tar.gz $ tar -xf v4.1.0.tar.gz $ sudo ln -sf `pwd`/salty-4.1.0/bin/salty /usr/local/bin/salty

Useful links

S8F Console: How to use Salty - Basic demonstration of the Salty CLI

Salty: PGP Evolved - How Salty improves on the PGP model

Format

Byte counts are in () parenthesis.

Salty wallet

Designed to allow both decryption and signing.

decryption signing -------------- + ----------- decryptSk (32) signSk (64)

Example (wallets are stored as encrypted PEM on disk)

-----BEGIN SALTY WALLET----- Proc-Type: 4,ENCRYPTED DEK-Info: NACL-SCRYPT,IP3NRMw15AGYyU56xwYPVJFa4Xx0aock OjCNhUvjNml3bebBVsIBpTBdvWSRkUG6vVZkdpzFZf9Ak/Bh0ghaXsEhuAiElEMy 2ghCEF5oQVO3dAWdflcvuVH3CSXlPlBfXWr6Y0EEOST3jYwaRS8Qfa2786YNBYCm NBm4au6wbuVp8dL41jhLeQ== -----END SALTY WALLET-----

Salty pubkey

Designed to be sharable, human-readable, and unique.

public keys optional meta ----------------------------------------- [space] -------- -------- base58(encryptPk (32) + verifyPk (32)) "{name}" <{email}>

Example:

2ZuU37oJ1erD85AzVohXq6Y74GHv2hjNYB9fu3P5o9rsGSvRo19HK2wTL4MLma3N6gVFqXN81VTqQ6apBhc5Kezq

Salty file

Designed to allow anonymous or signed messages, and verify message integrity.

required meta ciphertext -------------- + ---------- ephemeral (80) plaintext

Ephemeral

Designed to hide the message and header inside an anonymously encrypted/authenticated payload.

random random message length (encrypted, 24 bytes) -------------- + ---------- + --------------------------------------- encryptPk (32) nonce (24) totalSize (8 bytes, big endian)

Plaintext

Appends a header to the message for verification, and pads the plaintext with null bytes.

--------- + ------- + ------------------- message header null bytes (?)

Header

Always contains a sha256 HMAC to authenticate the message, and optionally contains a signature from the sender.

hash: hex( sha256_hmac( shared_secret ) of message ) [from-salty-id]: base58(encryptPk (32) + verifyPk (32)) [to-salty-id]: base58(encryptPk (32) + verifyPk (32)) [signature]: base58( detached sig of previous headers )

Example:

hash: 3a5a42ad3cadea1ac4abd5169a7a1c2b2017404e00b9f08c5dee6c205f7a197a from-salty-id: 2ZuU37oJ1erD85AzVohXq6Y74GHv2hjNYB9fu3P5o9rsGSvRo19HK2wTL4MLma3N6gVFqXN81VTqQ6apBhc5Kezq to-salty-id: self signature: 5V1c1P5a8dqDVMPhwqnDF39ZrHpaw7jhetEgHyPUkjM8tYvugPzDJ3xyhD9WdJQ4AjwYkN2XdWhnTB3GTRMJuAEd

Signature

Always contains the signer's public keys, a hash to authenticate the file, and a signature.

from-salty-id: base58(encryptPk (32) + verifyPk (32)) hash-algorithm: algorithm hash: hex( algorithm( file ) ) signature: base58( detached sig of previous headers )

Example:

from-salty-id: 2ZuU37oJ1erD85AzVohXq6Y74GHv2hjNYB9fu3P5o9rsGSvRo19HK2wTL4MLma3N6gVFqXN81VTqQ6apBhc5Kezq hash-algorithm: sha256 hash: 19e406822f9eac2c19f0a0d59c1ab1f554e354fadbc1836f9e10858ce227ed2c signature: 49VPoEqf3iNrpaWCjEejfe2vqT8ZHHkb68U6JRzxCEqWSoVoe7AjPEN2c3XYXgCuW7P3htsWbXZdF6LAsoyXoE3v

Usage

Usage: salty [options] [command] Commands: init [options] initialize or update a wallet id|pubkey output your shareable pubkey string import|i <pubkey|url|file> import a pubkey ls|l list imported keys rm <pubkey|email> remove pubkey encrypt|e [options] [infile|indir] [outfile] encrypt a file decrypt|d [options] <infile|gist> [outfile] decrypt and verify a file sign|s [options] <infile> [outfile] create a signature verify|v [options] <insig> [infile] verify a signature save [indir] [outfile] save an encrypted backup of your wallet restore [infile] [outdir] restore your wallet from a backup encode [infile] output base58-encoded data to STDOUT decode [infile] output base58-decoded data to STDOUT * Options: -h, --help output usage information -V, --version output the version number -w, --wallet <dir> wallet location (default: ~/.salty) -F, --force do it anyway

salty encrypt

Usage: encrypt|e [options] [infile|indir] [outfile] encrypt a file Options: -h, --help output usage information -t, --to <pubkey|email> email address to encrypt for. (must be imported first. default: self) -m, --message compose a message instead of using [infile] (implies -a) -s, --sign sign the message to reveal/prove our identity -H, --header <key: value> add a custom header (repeatable) -a, --armor output ASCII armor to STDOUT -g, --gist upload encrypted result as a gist -F, --force ignore warnings and do it -D, --delete delete the original file after encryption

salty decrypt

Usage: decrypt|d [options] <infile|gist> [outfile] decrypt and verify a file Options: -h, --help output usage information -s, --sig require a signature -a, --armor expect ASCII armor, output to STDOUT -g, --gist download the encrypted input from a gist -F, --force ignore warnings and do it -D, --delete delete the salty file after verification

salty sign

Usage: sign|s [options] <infile> [outfile] create a signature Options: -h, --help output usage information -H, --header <key: value> add a custom header (repeatable) -h, --hash <alg> hash algorithm (default: sha256) -a, --armor output ASCII armor to STDOUT -F, --force ignore warnings and do it

salty verify

Usage: verify|v [options] <insig> [infile] verify a signature Options: -h, --help output usage information -a, --armor expect ASCII armor, output to STDOUT

Log

no longer asks for name/email for wallet

release 4.0.3

fix translateHeader if no name/email

release 4.0.2

fix ascii armor signature headers not wrapped

add signing examples

release 4.0.1

updated generic install example to use wget instead of git

release 4.0.0

now you can regenerate your decryption key with salty init --regen

switch to base58-encoding for everything but hashes

hashes are now hex-encoded

\r

newlines in header/PEM changed to



newlines in header/PEM changed to Custom header support for encryption or signing

import now dedupes on verifyPk/email

key removal by pubkey/email now supported

"attached" signatures now available with ASCII armor flag

signatures can be verified without previous setup (wallet creation)

signatures support arbitrary hash algorithms

added --no-translate flag to output raw header

release 3.1.0

Added anonymous gist support

Added tar/gz support for encrypting directories

Example signed message (text)

$ salty sign -a -h ripemd160 -H 'content-type: text/markdown' -H 'filename: README.md' README.md

-----BEGIN SALTY SIGNED MESSAGE----- from-salty-id: 2ZuU37oJ1erD85AzVohXq6Y74GHv2hjNYB9fu3P5o9rsGSvRo 19HK2wTL4MLma3N6gVFqXN81VTqQ6apBhc5Kezq content-type: text/markdown filename: README.md hash-algorithm: ripemd160 content-transfer-encoding: 8bit hash: dcde04cff759a9e38ee4683b09355c857053ee80 signature: 2U135BFHiKYDKxiXMYiQbhDZMxD2imrXYJFVMZezKiTZmfLhtbYUb wxnhsQL4rdc6MfeGsGoxAhEZ1aYYs5tgia5 This is the jekyll source of my personal website, [s8f.org](http://s8f.org/). -----END SALTY SIGNED MESSAGE-----

Example signed message (image)

$ salty sign -a -h sha512 -H 'content-type: image/vnd.microsoft.icon' -H 'filename: favicon.ico' favicon.ico

-----BEGIN SALTY SIGNED MESSAGE----- from-salty-id: 2ZuU37oJ1erD85AzVohXq6Y74GHv2hjNYB9fu3P5o9rsGSvRo 19HK2wTL4MLma3N6gVFqXN81VTqQ6apBhc5Kezq content-type: image/vnd.microsoft.icon filename: favicon.ico hash-algorithm: sha512 content-transfer-encoding: base64 hash: 628b42749e7b007f13c2aa858210e5a5411cedfff93ebb1c758f8a2b2d 5a13f4ccded598aa096b6f824a81e00ddfbd6fd30894eae24530b218158c98e 7e3a16f signature: Kw7dZiBKZNwj4kejF2HevVPoni2mZry5VEKStKQYDeP6H61EWdD2s yod6FJv5JJwXWyaSpBhXjHqSrasHJF2QEx AAABAAEADxAAAAEAIAAoBAAAFgAAACgAAAAPAAAAIAAAAAEAIAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAQAA AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAeAAAAAAAAAABAAAAAAAA ABgAAAC0AAAAAgAAALMAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAcAAAAqAAAA1wAA ABMAAAAAAAAAAAAAADoAAABgAAAAAAAAAIIAAAAmAAAAAAAAAAAAAAAAAAAAJgAA AN8AAAC+AAAAmAAAAP8AAAAmAAAAAAAAAI8AAAAeAAAAAAAAACoAAACCAAAAAAAA AAAAAAAAAAAACgAAAF8AAAAAAAAAAAAAAOYAAABhAAAAEwAAAPMAAAAEAAAAAAAA AAsAAADeAAAACgAAAAAAAAAAAAAAAAAAABsAAACxAAAAwQAAAM4AAAAGAAAACQAA ALIAAAAHAAAAAAAAABgAAAC+AAAAAAAAAAAAAAAAAAAAAAAAALkAAABtAAAAAgAA AC0AAAAHAAAAAAAAAJUAAAA3AAAAAAAAADcAAAB/AAAAAAAAAAAAAAAAAAAAAAAA AF4AAADPAAAAkAAAANEAAAAgAAAAAAAAAC0AAAB5AAAAAAAAAKcAAAAHAAAAAwAA AAAAAAAAAAAAAAAAAAAAAAATAAAAqQAAADkAAAAHAAAAAAAAAAAAAAB1AAAADQAA AF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAABAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAD//gAA//4AAP/+AAD//gAA/64AAPfuAADDdgAA+3YAAON2 AADffgAA4+4AAPf+AAD//gAA//4AAP/+AAD//gAA -----END SALTY SIGNED MESSAGE-----

License: MIT

Copyright (C) 2016 Carlos Rodriguez (http://s8f.org/)

Copyright (C) 2016 Terra Eclipse, Inc. (http://www.terraeclipse.com/)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.