lfcrypt

package module
v0.0.0-...-90df5f9 Latest Latest
Warning

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

Go to latest
Published: May 14, 2018 License: Apache-2.0 Imports: 16 Imported by: 0

README

lfcrypt

GoDoc Build Status

lfcrypt is a Go library for the symmetric encryption of large files. This includes streaming reading and writing, and a trailer section ensuring a complete file.

The file extension .lfenc is used for streams encrypted with this format.

Concepts

Encrypting streams by Adam Langley outlines many of the issues with encrypting streams or large files.

Avoiding Output without verification

GPG will decrypt a stream and output it before it has been validated, because the HMAC of the file is at the very end.

In lfcrypt, the stream is authenticated incrementally. Contents of the stream could be truncated by an attacker, and in this case an error is returned by the API, but no cleartext is ever emitted that was not authenticated.

Avoiding Chunking Issues

When designing a stream format, you must ensure that chunks in the stream are not reordered, dropped, or truncated. lfcrypt prevents this by requiring an incrementing .counter field for every data chunk.

Supporting Seeking

Because each data chunk in lfcrypt is it's own independent AEAD construct with a local IV determined by the .cipher_ident, seeking without necessarily storing the entire file in memory or incremental MACs is possible.

Stream Format

Header chunk

12 bytes for version and cipher identification:

  • .version: 8 byte string. Static string: lfcrypt0
  • .cipher_ident: 4 bytes encoded in big endian (BigEndian.PutUint32):
    • 1: AEAD_AES_256_CBC_HMAC_SHA_512
    • 2: AEAD_CHACHA20_POLY1305_HMAC_SHA512
Metadata chunk
  • .length: 2 bytes encoded in big endian (BigEndian.PutUint16)
  • .metadata: JSON data of .length. Example:
{
    key_id: 1234,
}

key_id can be used by readers to find a secret-key by unique ID. Other JSON fields are ignored at this time, and implementations should ignore any unknown fields.

Data chunk
  • .counter: 4 bytes encoded in big endian (BigEndian.PutUint32). Must start at zero and increment by 1 for each chunk in the stream.
  • .length: 2 bytes encoded in big endian (BigEndian.PutUint16). Must be >= 1, See trailing chunk for behavoir of a zero byte data chunk
  • .encrypted_data: Encrypted data of .length.

Based on .cipher_id, .encrypted_data may contain additional interior fields:

  • AEAD_AES_256_CBC_HMAC_SHA_512: Contains a draft-mcgrew-aead-aes-cbc-hmac-sha2-05.txt formatted block.

  • AEAD_CHACHA20_POLY1305_HMAC_SHA512:

    • .nonce: 12 bytes of random nonce. The 4 bytes of .counter has been XOR'ed into the random nonce.
    • .data: Remaining encrypted data.
Trailing MAC chunk:
  • .mac: Variable length mac based on .cipher_ident:
    • AEAD_AES_256_CBC_HMAC_SHA_512: []byte: 64 byte HMAC_SHA512(secret) of all previous chunks, excluding the HMAC block itself.
    • AEAD_CHACHA20_POLY1305_HMAC_SHA512: []byte: 64 byte HMAC_SHA512(secret) of all previous chunks, excluding the HMAC block itself.

License

lfcrypt is licensed under the Apache License Version 2.0. See the LICENSE file for details.

Documentation

Index

Constants

View Source
const (
	AEAD_AES_256_CBC_HMAC_SHA_512    = "AEAD_AES_256_CBC_HMAC_SHA_512"
	AEAD_AES_256_CBC_HMAC_SHA_512_ID = uint32(1)

	AEAD_CHACHA20_POLY1305_HMAC_SHA512    = "AEAD_CHACHA20_POLY1305_HMAC_SHA512"
	AEAD_CHACHA20_POLY1305_HMAC_SHA512_ID = uint32(2)
)

Variables

View Source
var ErrCounterMismatch = errors.New("lfcrypt: Counter mismatch in data block")
View Source
var ErrMetadataTooLarge = errors.New("lfcrypt: Metadata header is larger than 2^16")
View Source
var ErrNoMatchingKey = errors.New("lfcrypt: No valid key for decryption")
View Source
var ErrSealedBufferTooLarge = errors.New("lfcrypt: Sealed buffer came back larger than 2^16")
View Source
var ErrShortRandRead = errors.New("lfcrypt: rand.Read returned with less than the requested data")
View Source
var ErrShortRead = errors.New("lfcrypt: Short read")
View Source
var ErrShortWrite = errors.New("lfcrypt: Short write")
View Source
var ErrTrailingHMACMismatch = errors.New("lfcrypt: File trailing HMAC failed.")
View Source
var ErrUnknownCipher = errors.New("lfcrypt: Unknown cipher type in header")
View Source
var ErrUnknownHeader = errors.New("lfcrypt: Unknown header in encrypted file.")

Functions

func ComputeKeyId

func ComputeKeyId(key []byte) uint32

func ReadKeyId

func ReadKeyId(r io.Reader) (uint32, error)

ReadKeyId reads a KeyID block from a Reader. Note that the KeyID data is not authenticated or validated.

Types

type Cryptor

type Cryptor interface {
	KeyId() uint32

	Encrypt(r io.Reader, w io.Writer) error

	// Decrypts reader into writer.  May return error after writer is partially written, so be sure to discard
	// the writers data in this case.
	Decrypt(r io.Reader, w io.Writer) error

	// Verify source reader is authenticated and valid.  On success, seeks back to start of file.
	// Returns nil error if input is verified.
	Verify(r io.ReadSeeker) error
}

func NewAES256SHA512

func NewAES256SHA512(secret []byte) (Cryptor, error)

NewAES256SHA512 constructs a Cryptor with an AEAD construct with AES-256-CBC encryption and SHA-512 MACs using a 64-byte secret.

func NewCHACHA20POLY1305

func NewCHACHA20POLY1305(secret []byte) (Cryptor, error)

NewCHACHA20POLY1305 constructs a Cryptor with an AEAD construct with ChaCha20-Poly1305 AEAD encryption and SHA-512 MACs using a 32-byte secret.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store contains a set of Cryptor instances to be used for decrypting a stream

func NewStore

func NewStore() *Store

func (*Store) Add

func (ks *Store) Add(c Cryptor) error

Add adds a Cryptor to the Store based on its KeyId

func (*Store) AddKey

func (ks *Store) AddKey(secret []byte) error

AddKey adds a AEAD_AES_256_CBC_HMAC_SHA_512 based Cryptor to Store. (deprecated: use Store.Add())

func (*Store) ByKeyId

func (ks *Store) ByKeyId(kid uint32) (Cryptor, error)

ByKeyId returns a Cryptor instance based in the KeyID. Returns ErrNoMatchingKey when a key is not found by this ID.

Jump to

Keyboard shortcuts

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