grump

package module
v0.0.0-...-e71ae9c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 6, 2015 License: MIT Imports: 23 Imported by: 0

README

Grump

Build Status

For documentation, please see Godoc.

Documentation

Overview

Package grump implements a grumpy cryptosystem for asynchronous messages.

Grump is an experiment in building a post-PGP, post-Snowden cryptosystem for asynchronously sending confidential and authentic messages of arbitrary size. It is an experiment, and should literally never be used in a context where the confidentiality or authenticity of a message has any value whatsoever. It is intended to be a conversation piece, and has not been vetted, analyzed, reviewed, or even heard of by a security professional. You are better off CC'ing a copy of your communications to the FBI than using this. No touchy.

It was on display in the bottom of a locked filing cabinet stuck in a
disused lavatory with a sign on the door saying "Beware of the Leopard".

I swear, I will slap you.

Threat Model

The threat model is defined in terms of what each possible attacker can achieve. The list is intended to be exhaustive, i.e. if an entity can do something that is not listed here then that should count as a break of Grump.

Assumptions About The User

The user must act reasonably and in their best interest. They must not reveal their passphrase or share unencrypted copies of messages.

The user must run a copy of Grump which has not been suborned.

Assumptions About The User's Computer

The user's computer computer must function correctly and not be compromised by malware.

Assumptions About The User's Friends

The user's friends must also act reasonably.

The user's friends must also run copies of Grump which have not been suborned.

Assumptions About The World

The security assumptions and proofs of Curve25519 (http://cr.yp.to/ecdh.html), Ed25519 (http://ed25519.cr.yp.to/), ChaCha20 (http://cr.yp.to/chacha.html), Poly1305 (http://cr.yp.to/mac.html), their combination (http://eprint.iacr.org/2014/613.pdf), SHA-512 (http://csrc.nist.gov/publications/nistpubs/800-107-rev1/sp800-107-rev1.pdf), HKDF (https://tools.ietf.org/html/rfc5869), and scrypt (http://www.tarsnap.com/scrypt/scrypt.pdf) must be valid.

Threats From Global Passive Adversaries

A Global Passive Adversary is an attacker who can eavesdrop on internet traffic globally. A GPA can:

  • Identify Grump messages as Grump messages.
  • Observe when Grump messages are sent, and to whom they are sent.
  • Learn the upper bound of the size of a Grump message.
  • Learn the upper bound of the number of recipients of a Grump message.
  • Identify Grump keys, both public and private, as such.
  • Observe when Grump keys are sent or exchanged, and with whom.

Threats From Active Network Adversaries

An attacker with a privileged network position to the user can:

  • Identify Grump messages as Grump messages.
  • Observe when Grump messages are sent, and to whom they are sent if the message is sent directly (e.g., via email).
  • Learn the upper bound of the size of a Grump message.
  • Learn the upper bound of the number of recipients of a Grump message.
  • Identify Grump keys, both public and private, as such.
  • Observe when Grump keys are sent or exchanged, and with whom if the keys are sent directly.
  • Modify messages such that they are no longer valid.
  • Block messages from being sent.
  • Replay previously recorded messages.

Seizure Of The User's Computer

An attacker who physically seizes the user's computer (or compromises the user's backups) can:

  • Attempt an offline dictionary/brute force attack on the user's passphrase. If successful, the attacker will be able to decrypt all messages encrypted with the user's public key as well as forge arbitrary messages from the user.
  • Analyze the user's collection of other people's public keys, which may potentially aide traffic analysis and de-anonymization efforts.

Compromise Of The User's Computer

An attacker who physically compromises the user's computer can:

  • Recover the user's passphrase, allowing them to decrypt all existing messages encrypted with the user's public key as well as forge arbitrary messages from the user.
  • Analyze the user's public keys of other people's public keys, which may potentially aide traffic analysis and de-anonymization efforts.

Recipients Of A Message

A valid recipient of a message can:

  • Prove, to some degree, that a particular message came from a particular user.

Thirsty Randos

A thirsty rando can:

  • Stop playing in my mentions.

If A Non-Recipient Attempts To Read A Message

Without their public key being used to encrypt a copy of the message key, a non-recipient would have to brute force the 256-bit ChaCha20Poly1305 key used to encrypt a message key copy.

If A Non-Recipient Attempts To Modify A Message

A more crafty attacker may attempt to modify an existing message.

If they modify the header, either by adding junk recipients or by removing valid recipients, the resulting message will be considered invalid when the first packet fails to decrypt due to the SHA-512 hash of the header being different.

If they modify either the nonce or the ciphertext of a packet in the message, ChaCha20Poly1305 will fail to authenticate and decryption will halt.

If they duplicate a packet or modify the order of the packets, the SHA-512 hash will change and that packet and all following packets will fail to decrypt.

Finally, the Ed25519 signature will fail to verify if any non-signature bytes in the message change.

If A Recipient Attempts To Modify A Message

A recipient has the message key, which allows them to forge packets for a message. While this would allow them to copy the header from a message and replace all the contents with valid ChaCha20Poly1305 ciphertexts, the Ed25519 signature will fail to verify and decryption will halt.

If A Rando Plays With Protobufs

The sole aspect of a message which is unauthenticated is the Protocol Buffer and framing metadata. An attacker can craft a message which has protobuf frames which are up to 4GiB. Grump implementations should perform hygiene checks on these values, and Protocol Buffer implementations should be checked for robustness to these types of attacks.

If a packet's frame is changed to, for example, elide data, the SHA-512 hash will change and the packet will become invalid.

Design

The general design is largely informed by ECIES (http://en.wikipedia.org/wiki/Integrated_Encryption_Scheme), in that it combines a key exchange algorithm, a key derivation algorithm, and an IND-CCA2 AEAD scheme.

Protocol Buffers

X.509 is better than nothing, but it's horrible. Grump uses Protocol Buffers, which has extremely broad language support (https://code.google.com/p/protobuf/wiki/ThirdPartyAddOns).

Curve25519 And Ed25519

These algorithms were selected because they're both fast, constant-time, require entropy for key generation only, use small keys, and use safe elliptic curves (http://safecurves.cr.yp.to).

ChaCha20Poly1305

The ChaChaPoly1305 AEAD construction was chosen because it's fast and constant-time.

Scrypt

scrypt was chosen as a PBKDF algorithm because it's resistant to CPU-, GPU-, FPGA-, and ASIC-optimized dictionary attacks.

SHA-512 and HKDF

These were selected as a KDF because Ed25519 already uses SHA-512.

Keys

A Grump private key is the combination of a Curve25519 decryption key and a Ed25519 signing key. Both are stored on disk encrypted with ChaCha20Poly1305, using a key derived from your passphrase via scrypt.

A Grump public key is the combination of a Curve25519 encryption key and a Ed25519 verifying key.

No, there isn't any way to keep track of whose keys are whose.

Messages

Grump messages are a sequence of framed protobufs (little-endian, 32-bit frame value, then that many bytes of protobuf).

A message starts with a header, which is contains the message key (a random 256-bit key) encrypted with the shared secret for each recipient (the Curve25519 ECDH shared secret, run through HKDF-SHA-512) using ChaCha20Poly1305. There is no meta-data, so random values can be added here to obscure the actual number of recipients.

(To decrypt a message, one simply iterates through the recipients, trying each.)

After the header comes a series of packets of arbitrary sizes, which are portions of the plaintext encrypted with ChaCha20Poly1305, using the SHA-512 hash of all previously written bytes as the authenticated data. The last packet in a message is flagged as such.

The final element of a message is an Ed25519 signature of the SHA-512 hash of every byte in the message which precedes the signature's frame. Any attempt to modify the message will fail this verification.

Synchronous Communications

Grump also provides a system for secure, synchronous communication. It uses a simple, two-round handshake.

First, Alice and Bob send each other random 256-bit nonces.

Second, Alice generates a random Curve25519 point, and multiplies it by the curve's base to produce her ECDH presecret. She also creates an Ed25519 signature of Bob's nonce and her ECDH presecret. She sends both the ECDH presecret and the signature. Bob does the same.

They both verify each other's signatures, and if the signature is valid, calculate the final ECDH shared secret. They each derive two keys using HKDF-SHA512: one for sending data (using a null salt and the peer's public key as the info), and one for receiving data (using a null salt and their own public key as the info).

Data is then transmitted back and forth using standard Grump encrypted data packets, each encrypted with ChaCha20Poly1305 and a random nonce. If any of the packets fail to decrypt, the connection is closed.

Index

Constants

View Source
const (
	// MaxFrameSize is the maximum allowable size for a protobuf frame.
	MaxFrameSize = 1024 * 1024 * 10
)

Variables

View Source
var (
	// ErrBadPassphrase is returned when the passphrase provided cannot decrypt
	// the given private key.
	ErrBadPassphrase = errors.New("bad passphrase")

	// ErrBadSignature is returned when the message has been tampered with.
	ErrBadSignature = errors.New("bad signature")

	// ErrNotDecryptable is returned when the given private key cannot be used
	// to decrypt the message key.
	ErrNotDecryptable = errors.New("not decryptable with the given key")

	// ErrFrameTooLarge is returned when a protobuf's frame is too large.
	ErrFrameTooLarge = errors.New("frame too large")
)

Functions

func ChangePassphrase

func ChangePassphrase(privateKey, oldPassphrase, newPassphrase []byte, n, r, p uint) ([]byte, error)

ChangePassphrase decrypts the given private key with the old passphrase and re-encrypts it with the new passphrase.

func Decrypt

func Decrypt(privateKey, passphrase, sender []byte, r io.Reader, w io.Writer) error

Decrypt first decrypts the given private key with the given passphrase and then decrypts the data, verifying that it came from the given sender.

func Dial

func Dial(network, address string, privateKey, passphrase, publicKey, peerKey []byte) (net.Conn, error)

Dial connects to the address on the named network, using the given key pair and expecting to connect to the owner of the given peer key.

func Encrypt

func Encrypt(privateKey, passphrase []byte, recipients [][]byte, r io.Reader, w io.Writer, packetSize int) error

Encrypt first decrypts the given private key with the given passphrase, then uses it to encrypt all of the data in the given reader so that only the given recipients can decrypt it.

func GenerateKeyPair

func GenerateKeyPair(passphrase []byte, n, r, p uint) ([]byte, []byte, error)

GenerateKeyPair creates a new Ed25519 key pair and encrypts the private key with the given passphrase and scrypt parameters.

func Listen

func Listen(network, address string, privateKey, passphrase, publicKey, peerKey []byte) (net.Listener, error)

Listen announces on the local network address laddr, using the given key pair and expecting connections from the owner of the given peer key.

The network net must be a stream-oriented network: "tcp", "tcp4", "tcp6", "unix" or "unixpacket".

See net.Dial for the syntax of laddr.

func ReadPassphrase

func ReadPassphrase(interactive bool, prefix string) ([]byte, error)

ReadPassphrase either prompts interactively for the passphrase or reads it from stdin.

func Sign

func Sign(privateKey, passphrase []byte, r io.Reader, w io.Writer) error

Sign first decrypts the private key with the given passphrase, then uses it to create a Ed25519 signature of the given data.

func Verify

func Verify(publicKey, signature []byte, r io.Reader) error

Verify returns an error if the given signature for the given data was not created by the owner of the given public key.

Types

This section is empty.

Directories

Path Synopsis
Godeps
_workspace/src/code.google.com/p/go.crypto/pbkdf2
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC 2898 / PKCS #5 v2.0.
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC 2898 / PKCS #5 v2.0.
_workspace/src/github.com/Bowery/prompt
Package prompt implements a cross platform line-editing prompt.
Package prompt implements a cross platform line-editing prompt.
_workspace/src/github.com/agl/ed25519
Package ed25519 implements the Ed25519 signature algorithm.
Package ed25519 implements the Ed25519 signature algorithm.
_workspace/src/github.com/agl/ed25519/edwards25519
Package edwards25519 implements operations in GF(2**255-19) and on an Edwards curve that is isomorphic to curve25519.
Package edwards25519 implements operations in GF(2**255-19) and on an Edwards curve that is isomorphic to curve25519.
_workspace/src/github.com/codahale/chacha20
Package chacha20 provides a pure Go implementation of ChaCha20, a fast, secure stream cipher.
Package chacha20 provides a pure Go implementation of ChaCha20, a fast, secure stream cipher.
_workspace/src/github.com/codahale/chacha20poly1305
Package chacha20poly1305 implements the AEAD_CHACHA20_POLY1305 algorithm, which combines ChaCha20, a secure stream cipher, with Poly1305, a secure MAC function.
Package chacha20poly1305 implements the AEAD_CHACHA20_POLY1305 algorithm, which combines ChaCha20, a secure stream cipher, with Poly1305, a secure MAC function.
_workspace/src/github.com/docopt/docopt-go
Package docopt parses command-line arguments based on a help message.
Package docopt parses command-line arguments based on a help message.
_workspace/src/github.com/golang/protobuf/proto
Package proto converts data structures to and from the wire format of protocol buffers.
Package proto converts data structures to and from the wire format of protocol buffers.
_workspace/src/golang.org/x/crypto/curve25519
Package curve25519 provides an implementation of scalar multiplication on the elliptic curve known as curve25519.
Package curve25519 provides an implementation of scalar multiplication on the elliptic curve known as curve25519.
_workspace/src/golang.org/x/crypto/hkdf
Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as defined in RFC 5869.
Package hkdf implements the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as defined in RFC 5869.
_workspace/src/golang.org/x/crypto/poly1305
Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf.
Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf.
_workspace/src/golang.org/x/crypto/scrypt
Package scrypt implements the scrypt key derivation function as defined in Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf).
Package scrypt implements the scrypt key derivation function as defined in Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf).
cmd
grump
Grump is a grumpy cryptosystem for asynchronous messages.
Grump is a grumpy cryptosystem for asynchronous messages.
Package pb is a generated protocol buffer package.
Package pb is a generated protocol buffer package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL