a modern crypto messaging format

saltpack

a modern crypto messaging format

https://saltpack.org/

Build Status Coverage Status GoDoc

saltpack is a streamlined, modern solution, designed with simplicity in mind. It is easy to implement & integrate. We've made few crypto decisions and instead leave almost all of the heavy lifting to the NaCl library.

saltpack is a binary message format, encoded using the MessagePack format. Messages are broken up into reasonable (1MB) chunks, over which regular NaCl operations are performed. We have taken pains to address many of the shortcomings of current message formats: (1) only authenticated data is output; (2) repudiable authentication is used wherever possible; (3) chunks cannot be reordered or combined with other transmissions; (4) the public keys of senders and recipients can be hidden; and (5) message truncation is detectable.

Visually speaking, a saltpack ASCII output looks a lot like PGP's.

saltpack

BEGIN SALTPACK SIGNED MESSAGE. kXR7VktZdyH7rvq v5wcIkHbs7XwHpb
nPtLcF6vE5yY63t aHF62jiEC1zHGqD inx5YqK0nf5W9Lp TvUmM2zBwxgd3Nw
kvzZ96W7ZfDdTVg F5Y99c2l5EsCy1I xVNl0nY1TP25vsX 2cRXXPUrM2UKtWq
UK2HG2ifBSOED4w xArcORHfFeiEZxF CqestMqLSCCE6lT HFcdvt1QX9JjmWL
o5AAqPiECnoHiSA bPHhz2JnSCyDIOz ZET1BWzttbMDL4N pcyQLmsGqYpxhG6
uvdBxdt55w9xQvQ hDPuOsKF05Hsml6 z7h9TS2msJcNwtz vxGIQR7sbB19UOt
boM1hlolmMB3loP 0KexlROFBTDC6MR nBvd9sZUxA8Z7i5 a6Dk5yFU3WEYQAo
DqqjXcp0yBoHO5O KEMqkZlyMf1PKiB 2n9wE6jwxAN1xws ccthT6X3iRYk0Br
gHW6QRXzAHLy6Ib LgY6b3UcQAoDo8b XyaExxinVuM5Ftk 75BJOWoyLGFhZS7
EfKR8jQQexvyjDM rJLxYtjvaLX7joS 2q1VcUlqGfZDhAa 4vxJQAyu57beOux
oobLhI47iZf9bxK PmYrVQ5PsC6pY1J KTQQexvlvp2yicx K4su2AFCjihbzNI
yZgKM4NHN1KZapS O3iB9SlhVfTfFcR FoQoSViTkbtDtTt 6I0jrTRHkv9XVQQ
eeeuzR7qYu1Grm3 zDPyj7JgK2mDidw HchOZnfOn59QLnM nH7ErnPRXgHuWHG
DBidjQPakJHuWsk 2ftpIyZd2NLYEFS Mqcbo6QeCdk7LA1 uobl4NXzpvi8amO
Pe8xAl1OzUCoD34 MbCwtTAe1JNymvs okufV8lHU0jVnbj u4no9QB9aP2Wkjx
PfeqIH2fEtOjmFP gPMhGWslkU0M7FL QP77gPHbgjPLSD8 yIRTrbgzpAPut5R
QhIdqVlHbUOa9sI v7gSqOi0GbUlhSM 183LxZI8pIlvgn9 Ms1WNzt5Xkv0W1Q
Qf419ZmuQVPQDOk 0hffDmUk71TlfVx XZCF3voC2ysgl3g YdLz4rDRzMJgd2m
01HIbfdsoZpAMty O27WtUNRLV1iyC9 tK5ApCyekI4nWcf 2OvTHnC8ma7bloW
XAG. END SALTPACK SIGNED MESSAGE.

PGP

-----BEGIN PGP MESSAGE-----
Comment: GPGTools - https://gpgtools.org

owEBUAKv/ZANAwAKAdIkQTsc+mSQAcsgYgBWZ0C0SSBhbSBzbyBzaWNrIG9mIHRo
aXMgc2hpdAqJAhwEAAEKAAYFAlZnQLQACgkQ0iRBOxz6ZJBS9Q/+MSfWiOz5OvRt
lHTncX8Ifo7+wSKYH039vEQAUvj+rnEdlBzcJPoHDE1yZxAZT5ek5S+cxQ5bx55K
WRLvw/sAz+OU0OPHSDsqI2LjU6D+s1EvwCISkXoWlMVx5vJsEz2XGlQ8DzgBC2Jy
wPanQf1lUz0c7k0ySdCTdZ0qG1YuaYnCXsS6g/E8E7TIO++2v5EbkgYZl3Io2LcI
C9TqTHdrIc7WGTSFjwq9JIgvwfuShpccNSFQ262gSJh8rUOzzY37q81pKxDnBvEV
TMrQYY0e/JK7KMMcHDSQSeWnMxf4/v5Qex7WI55CW4++qbNvDylDi9fTpkYfXl3B
L8pbBAxMUjcJX4qVVzWcxTwSXYO29Bi4osn2klNyZHnO35kuI9XGziWCGqhVx1MW
ptNHoVjk7/Uo7k39hY0Vjltnl/SqXHq/H7YTRSgLebuhn6zqMbmFXtyHYSHGgAQ4
rcdSBta+I9tmYCnp1GmfeXff2wzsFYPUune2Hve4VghjmeU0x7OWMEl93gpznSwu
NvzyOCqFCyfEmt/R2QCXAkxwPU/Mdsd5vzEHSMkcZgW4CTr+j5YG/C3kMy7UJAGZ
ZzFAh3/Z8fCtfREF3zH48XbNh3dQXNl40bUF/AgPvLqPf35L7TCchcUAC7oiASa/
Ph/Hao4ZzCQDM76Jr/aCUJIbxyc2zco=
=eyef
-----END PGP MESSAGE-----

The changes here are small: we've reduced our characters to base62 plus some period markers, and only at the ends of words. PGP messages often get mangled by different apps, websites, and smart text processors.

Of course, saltpack can output binary, too. Either way, it's what's inside the format that matters. You can read the spec for the details.

Comments
  • Add isFinal flag for encryption V2 packets

    Add isFinal flag for encryption V2 packets

    Also replace stored header in encryptStream with just the version.

    Added tests to make sure truncating a message while leaving the footer alone still produced errors.

    Moved signature calculation in signcryption inside if statement so as to not be misleading.

  • Mix ephemeral-static DH output into MAC keys for v2

    Mix ephemeral-static DH output into MAC keys for v2

    Also mix in index into MAC nonce.

    This prevents tampering of previously produced message ciphertexts, even if the sender's private key is compromised.

  • Refactor read loops

    Refactor read loops

    Make them read multiple chunks if possible. Also fix a possible infinite loop if the input buffer is zero-length.

    Unify all the check*State functions into one for encoders, and another for decoders.

    Error if an empty block is encountered in V2, except if the entire message is empty.

    Also add comment for assertEndOfStream().

  • update the encryption and signing specs to reflect the field order we shipped

    update the encryption and signing specs to reflect the field order we shipped

    The Go msgpack encoder we're using has a counterintuitive order for struct fields when serializing as arrays. We meant to put the final flag at the end, but it's actually at the beginning (though not for signcryption mode). Update the v2 specs to reflect this unfortunate reality.

    r? @mlsteele @akalin-keybase

  • Better handle whitespace in frame

    Better handle whitespace in frame

    frame.go now handles arbitrary amounts and combinations of whitespace in between words in either the header or the footer. It doesn't work with whitespace in the middle of a word (e.g. 'KEY BASE'), so the spec has been updated as we decided we don't want it to do that.

  • Website broken

    Website broken

    Hi, the saltpack.org website appears to be broken in its current state. The homepage and pages listed under the "Basics" menu all work, but the spec details (e.g: Encryption, Signing) display "Error: Couldn't load /home/keybase/src/keybase/saltpack.org/views/doc_symlink/saltpack_signing_v2.md" (or whatever page should be shown).

  • Fix two bugs in basex decoder

    Fix two bugs in basex decoder

    First bug: io.ReadAtLeast drops errors if it reads enough characters.

    Second bug: both io.ReadAtLeast and punctuatedReader (among other) things return io.ErrUnexpectedEOF, so we were dropping errors from the latter.

    The solution to both is to not use io.ReadAtLeast, and instead refill the buffer manually.

    Reenable a test (which was hitting the second bug!).

    Fix a few typos.

  • Pre-commit hook with gometalinter

    Pre-commit hook with gometalinter

    To install, run pre-commit install.

    After running, to view all gometalinter warnings: pre-commit run -a.

    The current output is:

    verify_stream.go:103:5:warning: should omit nil check; len() for nil slices is defined as zero (gosimple)
    encrypt_test.go:317::warning: declaration of err shadows declaration at encrypt_test.go:313: (vetshadow)
    encrypt_test.go:406::warning: declaration of err shadows declaration at encrypt_test.go:401: (vetshadow)
    encrypt_test.go:428::warning: declaration of err shadows declaration at encrypt_test.go:423: (vetshadow)
    encoding/basex/encoding.go:275:2:warning: should use 'return <expr>' instead of 'if <expr> { return <bool> }; return <bool>' (gosimple)
    armor_test.go:164:11:warning: ftr assigned and not used (ineffassign)
    armor_test.go:164:3:warning: m assigned and not used (ineffassign)
    armor_test.go:164:16:warning: err assigned and not used (ineffassign)
    armor_test.go:164:6:warning: hdr assigned and not used (ineffassign)
    frame.go:37:3:warning: brand assigned and not used (ineffassign)
    encoding/basex/go_base64_test.go:146:4:warning: count assigned and not used (ineffassign)
    encoding/basex/bases.go:17:1:warning: comment on exported var Base58StdEncodingStrict should be of the form "Base58StdEncodingStrict ..." (golint)
    encoding/basex/bases.go:28:1:warning: comment on exported var Base62StdEncodingStrict should be of the form "Base62StdEncodingStrict ..." (golint)
    encoding/basex/basex_test.go:102:11:warning: error return value not checked (rand.Read(r)) (errcheck)
    encoding/basex/basex_test.go:107:33:warning: error return value not checked (Base62StdEncoding.DecodeString(data)) (errcheck)
    encoding/basex/go_base64_test.go:92:16:warning: error return value not checked (encoder.Write([]byte(p.decoded))) (errcheck)
    encoding/basex/go_base64_test.go:93:16:warning: error return value not checked (encoder.Close()) (errcheck)
    encoding/basex/go_base64_test.go:358:33:warning: error return value not checked (Base58StdEncoding.DecodeString(data)) (errcheck)
    common.go:68:1:warning: detachedSignatureInput is unused (deadcode)
    packets.go:64:25:warning: sender can be BasePublicKey (interfacer)
    armor.go:75:37:warning: unnecessary conversion (unconvert)
    packets.go:104:2:warning: unused struct field github.com/keybase/saltpack.signatureBlock._struct (structcheck)
    packets.go:16:2:warning: unused struct field github.com/keybase/saltpack.Version._struct (structcheck)
    encrypt.go:27:2:warning: unused struct field github.com/keybase/saltpack.encryptStream.didHeader (structcheck)
    encrypt.go:28:2:warning: unused struct field github.com/keybase/saltpack.encryptStream.eof (structcheck)
    packets.go:56:2:warning: unused struct field github.com/keybase/saltpack.SignatureHeader._struct (structcheck)
    packets.go:25:2:warning: unused struct field github.com/keybase/saltpack.EncryptionHeader._struct (structcheck)
    packets.go:38:2:warning: unused struct field github.com/keybase/saltpack.encryptionBlock._struct (structcheck)
    packets.go:9:2:warning: unused struct field github.com/keybase/saltpack.receiverKeys._struct (structcheck)
    decrypt.go:31:6:warning: struct MessageKeyInfo could have size 72 (currently 80) (aligncheck)
    
  • Clarify MessagePack encoding in spec

    Clarify MessagePack encoding in spec

    MessagePack has some ambiguity in encoding numbers, so clarify that the version numbers and mode should be encoded as positive fixnums.

    Also clarify ambiguity re. encoding strings, bytes arrays, and arrays.

    Also add tests.

  • Dep-inject functions involving randomness

    Dep-inject functions involving randomness

    This is in preparation for adding more hardcoded tests.

    Separate out ephemeral key generation into its own interface separate from keys and keyrings.

    Make signcryption return an error if there are no receivers.

    Better upper bound for receiver count.

  • Mix in index into payload nonce

    Mix in index into payload nonce

    This prevents leaking whether two recipient public keys are identical, which can then be used to confirm guesses of other recipients (by presenting their public keys as ours).

  • saltpack website has invalid saltpack ciphertext example

    saltpack website has invalid saltpack ciphertext example

    The sample cipher text found at the following website is invalid when used in the latest version of the Keybase client for macOS (Version 5.3.0-20200310172631+4f2689009b (5.3.0-20200310172631+4f2689009b)):

    Website:

    https://saltpack.org/in-the-wild

    Ciphertext Sample

    BEGIN KEYBASE SALTPACK ENCRYPTED MESSAGE. ZUHRHckf9VJ6ich bKthcfFYyHcFs9n NI27ndpDFCqUnXj allzG097b3s5NfZ GYqoBPt7GnyCccB i0UhaCcVmbF55ms SYpOCl7tkjUJd40 DO6iR0dJpW60EKj 1K5x2hclL9hZb7V DRObuimxmStmqqs 7yWy26mVOa5Z5RM S7NeocvOyNlgBUp fhsPaNFrYuI3D4H Ku217LIW3V2wniP 7XkayWcyAfH8jWj ETF0WJPn2Aa1aOI Jz5olg5vyxIpofL FIuerimZ6n5qI3p NZr3pfBVjVLbYDO N3VgqUd5r2F85LE vWH3Qg8aK0aFkVw q1ZVVWbOm5ucueX 9RkRpkb2tZOenqu Ik7RAQEbcW5JIlv EFY8c5WjUYMONiM H0DQtdKsdZRjfTm ajt71qa33pffsSE rYDTXFBtGudM9FX SHXAMCGDHVH2sSF yb23QJVJuyGAHuO XpHP06EXRCHj23y GOk77q23cYVd01X 08U6bsPmweu5jvS 7SLTg0OsJpqTsUB NfrZyJ2gSppcPlL bZaTgtoL8U9ZzBV sHKMD5vGiUgb74u llrukVSRcTqk2bO 5wdQ57EmY8IjJSn Lznnv9PhY8xnsTT EVPQcAH0CszKDQN LskpyRGDhsCbuzH 6YSFe2grnjccVAK uvaqEELV4Fnf90s cLxe65hn8918oz6 8BNj30RaMiEJbpq wXfb7vHPfrd1vVe raU4tfG5MZD34s7 xfvLCKSlctVLO7O q1MAgPtT73CGVU8 c4gkvmFWANwUC7g YivwSxNkn5PWiL2 NsaE8UfQDptjGDN hR96GQfuWJ63JTE gGa19OrSzgIErLK IAexacwBNiAXbPb ViAIrl0w6BL4aSa j5p5GZi5PPNlJ2Q OPo67OkcmweyfwE vNGrC7y3PxAemOU GRxeHbQ3FI77C2Y 9OyFG0LT3Qo04iK BVbp0r7xAX0i26O mybjcCqn4eBLKcy 87YiDgQRSa4n2fk c1Q0plK9e2U8rk6 6D0kx3bkxdG8Boy s6kTH9moQzAuKoG yLnoq9cmjCKfrOt 2K4vlJiAqJglyeu rm2lZEHIPW9sELw 06cowGDsmfcGN7h T6j9fbMgNGo9eIs s4YQd5tIKzoWsXl SSPNrVjaNMxtJsI IIjSCrPdjL2oSv6 eHDWXWmPJW6XIBI Ar7ZE8vAFRQSvr8 v9vAB7kALQpHdMv SiRbM1bQ6or7r0l P2QHXfA2lRykA9y 6kX8n0CCWZPO8Qo V4mhJCSF3snj9RK kwZosJw2AyvqDLs OAZ8OPdyYGx3FTg 7PaOijY9fQxcBVM 3omDhcawPWdA7jN 3ZQMvd9FKwIbu7H sF1YJixcN6OLzCp tbCKIi7xwUK0oGw XrO7QaFsHYEXNg9 RbMpaYtGfewhkUj 6LFRs9zfq8K13ni dV8d6V8eApAmgTp 8x3DtGdazE8F0ZG cSAwjiKLJVzYmpj jUiWtx0xcx0J6Hn VeSxuHKKYa7NASA BBzX454HGK3OXvt hPJua8eygXO9Ucp 2nNT12FOfkozrYM M4CkXaBQzYMkYzY sGO1c2plDJaEbV9 9guG5XJg3iJO23K CB7WtsJypxmkMoy eQYuNQMlKk4MU8b NuZhauMnqqQQfNG 1tJLhLyzyHfkBBL rnQo9cstcFLZAd0 md5lpy0X. END KEYBASE SALTPACK ENCRYPTED MESSAGE.
    

    Error Message in macOS client Decrypt tab:

    This ciphertext is not in a valid Saltpack format. Please enter Saltpack ciphertext.
    

    It was expected that the client would say the following for a message encrypted to max that I don't have the key for:

    Your message couldn't be decrypted, because no suitable key was found.
    
  • Spaces should be allowed in brands

    Spaces should be allowed in brands

    ... or user should not be allowed to generate unparseable messages.

    	smsg, err := saltpack.SignArmor62(
    		saltpack.CurrentVersion(),
    		[]byte("message here"),
    		secretKey,
    		"TWO PART",
    	)
    	if err != nil {
    		panic(err)
    	}
    
    	skey, msg, brand, err := saltpack.Dearmor62Verify(
    		saltpack.CheckKnownMajorVersion,
    		smsg,
    		kr,
    	)
    	if err != nil {
    		panic(err) // will panic here, unable to parse the header
    	}
    
  • How does this compare with D.A.R.E?

    How does this compare with D.A.R.E?

    https://github.com/minio/sio (D.A.R.E. v2) seems very similar to NaCL providing an stream of GCM encrypted chunks + Salsa20 and Poly1305. It looks like this project improves on the "Armor" / display part of things for binary chunks.

  • Is saltpack suitable for low size messages in a streaming like environment?

    Is saltpack suitable for low size messages in a streaming like environment?

    I was looking for an encrypted messagepack library and found this project. My goal is to add encryption to a location based app which uses websockets to stream in real time the position of its users. As such, I would expect to send less than 100bytes per user every 5 or 10 seconds at most, which is far away from the readme description of breaking up messages in sizes of 1MB sizes.

    Is there anything bad in saltpack for short messages? Will each of them pad to 1MB chunks of gibberish or this is this sentence just aimed at developers willing to implement multimedia communications (sending pictures, audio, video, which weight much more)?

  • saltpack.org makes it difficult to understand how to decrypt messages

    saltpack.org makes it difficult to understand how to decrypt messages

    My friend send me a message on Slack with a BEGIN KEYBASE SALTPACK ENCRYPTED MESSAGE prelude. I typed this phrase into Google, landed on saltpack.org and have been trying to figure out how to decrypt the message.

    I've scanned the sidebar, read the intro, read the homepage, read https://saltpack.org/signing-format, read https://saltpack.org/implementations. I ran go get github.com/keybase/saltpack and expected to find a saltpack binary on my $PATH - I could then call saltpack -h and maybe learn about decryption options, but that also failed. I'd rather not write a Go main function to decrypt the message.

    I expected to find something like this:

    Decrypting messages with Saltpack

    To decrypt messages, save the encrypted message to a file, then run keybase decrypt foo.bar or call saltpack decrypt file.name

    or whatever other instructions I need.

    Or a list item in the sidebar that says "decrypting messages", or something.

A command line Crypto-currency ticker made using golang and WazirX Api
A command line Crypto-currency ticker made using golang and WazirX Api

░█████╗░██████╗░██╗░░░██╗██████╗░████████╗███████╗██╗░░██╗ ██╔══██╗██╔══██╗╚██╗░██╔╝██╔══██╗╚══██╔══╝██╔════╝╚██╗██╔╝ ██║░░╚═╝██████╔╝░╚████╔╝░██████╔

Feb 6, 2022
An easy to setup local crypto wallet based on Geth

CryptoWallet An easy to setup local crypto wallet based on Geth To run. go run CrytoWallet This will expose a set a api's. To Create new Wallet curl

Oct 15, 2021
A terminal application to watch crypto prices!
A terminal application to watch crypto prices!

cryptgo Latest Stable Version: Crytpgo is a TUI based application written purely in Go to monitor and observe cryptocurrency prices in real time! Inst

Dec 21, 2022
Real time crypto VWAP calculator
Real time crypto VWAP calculator

VWAP calculator A realtime VWAP calculator of crypto currencies. It uses coinbase as its default provider for real time data over websocket. Design Th

Oct 31, 2022
ECIES implementation forked of the `crypto/ecies` package from Ethereum

# NOTE This implementation is direct fork of Kylom's implementation. I claim no authorship over this code apart from some minor modifications. Please

Dec 7, 2021
A tiny Crypto Project with REST API

Goal ⚽ Golang으로 아무 쓸모 없는 블록체인을 한땀 한땀 만들어보면서 BTC나 ETH에 적용된 블록체인 기법 이해해보기! Special Thanks to Nico! Current... ??️ Work ?? 자세한 내용은 issue와 PR을 확인하세요. Now

Dec 30, 2021
Xk6-crypto-x509 - A k6 extension to encrypt data with a PEM Public Key

xk6-crypto-x509 A k6 extension to encrypt data with a PEM Public Key This is a k

Jan 5, 2022
InductiveDifferentiation - A Trading Experiment With The Crypto Market

A Trading Experiment With The Crypto Market The program was proposed and owned b

Apr 10, 2022
Easy to use crypto library with multiple algorithms

crypka Crypka is library, which abstracts away crypto, so one can easily do: Swap cryptosystems by swapping algorithm object in one place Easily and s

Mar 6, 2022
Coinbase - You can use this to retrieve the current price for an crypto currency

whats-this You can use this to retrieve the current price for an crypto currency

Sep 29, 2022
Crypto-project - Personal project for learning TLS

crypto-project My personal attempt to implement this cipher suite using the Go l

Feb 14, 2022
Feb 14, 2022
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Jan 9, 2023
An end-to-end encrypted secret messaging service.

Nimie An End-to-end encrypted Anonymous Messaging Service. In a nutshell This service basically empowers you to have short anonymous conversations wit

Dec 17, 2021
TLS/SSL Tunnel - A modern STunnel replacement written in golang
TLS/SSL Tunnel - A modern STunnel replacement written in golang

go-tunnel - Robust Quic/TLS Tunnel (Stunnel replacement) What is it? A supercharged Stunnel replacement written in golang. is in a sense a proxy enabl

Jan 1, 2023
A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.
A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.

A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.

Jan 7, 2023
Go implementation of the Data At Rest Encryption (DARE) format.

Secure IO Go implementation of the Data At Rest Encryption (DARE) format. Introduction It is a common problem to store data securely - especially on u

Dec 18, 2022