chacha20poly1305

package module
v0.0.0-...-1a5aba2 Latest Latest
Warning

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

Go to latest
Published: Nov 24, 2020 License: MIT Imports: 7 Imported by: 441

README

Chacha20Poly1305

This repository implements the ChaCha20Poly1305 AEAD construction. ChaCha20Pol1305 is combination of the ChaCha20 stream cipher and the Poly1305 authenticator and is standardized in RFC 7539.

This repository also implements 8 and 24 byte variants additional to the IETF 12 byte version of ChaCha20Poly1305. Further this package provides a streaming API to wrap an io.Writer with an en/decrypting io.WriteCloser.

Recommendations

It is recommended to use the official Chacha20Poly1305 implementation if possible.
This repository just provides additional functionality like 8 and 24 byte variants and a streaming API.

Install

Install in your GOPATH: go get -u github.com/aead/chacha20poly1305
Please notice, that the amd64 AVX2 asm implementation requires go1.7 or newer.

Performance

AMD64
Hardware: Intel i7-6500U 2.50GHz x 2
System: Linux Ubuntu 16.04 - kernel: 4.8.0-54-generic
Go version: 1.8.1

AVX2

name                       speed                cpb
Chacha20Poly1305Open_64-4   131MB/s ± 0%        18.20
Chacha20Poly1305Seal_64-4   134MB/s ± 0%        17.79
Chacha20Poly1305Open_1K-4   830MB/s ± 0%         2.87
Chacha20Poly1305Seal_1K-4   839MB/s ± 0%         2.84
Chacha20Poly1305Open_8K-4  1.15GB/s ± 0%         2.03
Chacha20Poly1305Seal_8K-4  1.15GB/s ± 0%         2.03
EncryptedWriter64-4         392MB/s ± 0%         6.08
DecryptedWriter64-4         255MB/s ± 0%         9.35
EncryptedWriter1K-4        1.97GB/s ± 1%         1.18
DecryptedWriter1K-4        1.70GB/s ± 0%         1.37
EncryptedWriter8K-4        2.23GB/s ± 0%         1.04
DecryptedWriter8K-4        2.17GB/s ± 1%         1.07


SSSE3

name                       speed                cpb
Chacha20Poly1305Open_64-4   133MB/s ± 1%        17.93
Chacha20Poly1305Seal_64-4   137MB/s ± 0%        17.40
Chacha20Poly1305Open_1K-4   626MB/s ± 0%         3.80
Chacha20Poly1305Seal_1K-4   629MB/s ± 0%         3.79
Chacha20Poly1305Open_8K-4   788MB/s ± 0%         3.03
Chacha20Poly1305Seal_8K-4   790MB/s ± 0%         3.02
EncryptedWriter64-4         397MB/s ± 0%         6.01
DecryptedWriter64-4         263MB/s ± 1%         9.07
EncryptedWriter1K-4        1.10GB/s ± 1%         2.12
DecryptedWriter1K-4        1.01GB/s ± 1%         2.31 
EncryptedWriter8K-4        1.18GB/s ± 0%         1.97
DecryptedWriter8K-4        1.16GB/s ± 0%         2.01

Documentation

Index

Examples

Constants

View Source
const KeySize = 32

KeySize is the size of the key used by this AEAD, in bytes.

Variables

This section is empty.

Functions

func DecryptWriter

func DecryptWriter(w io.Writer, key, nonce []byte) (io.WriteCloser, error)

DecryptWriter wraps an io.Writer and returns an io.WriteCloser which decrypts and checks authenticity of all input passed into it with the given key and nonce. The Close function of the returned io.WriteCloser must be called to finish the decryption successfully. If the Close function returns a non-nil error the decryption failed - for example because of an incorrect authentication tag. So the returned error of Close MUST be checked!

If the Write or Close function of the io.WriteCloser returns a non-nil error the hole decryption process cannot succeed and must be restarted. The length of the nonce determines which cipher is used:

  • 8 byte: ChaCha20Poly1305 with 64 bit nonces
  • 12 byte: ChaCha20Poly1305 with 96 bit nonces (used in TLS)
  • 24 byte: XChaCha20Poly1305 with 192 bit nonces
Example
// Create a secret key - can also be generated from a passwort or ...
key := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, key); err != nil {
	panic(fmt.Sprintf("Failed to create random encryption key: %v", err))
}
// Set the nonce, in this case we encrypt the first message so we set it to 1.
// Be aware that the nonce must be unique for every message under the same key.
nonce := make([]byte, 8)
binary.LittleEndian.PutUint64(nonce, 1)

// We first encrypt a stream.
mem := bytes.NewBuffer(nil)
encryptedWriter, err := EncryptWriter(mem, key, nonce)
if err != nil {
	panic(fmt.Sprintf("Cannot create encrypted writer: %v", err))
}
msg := []byte("Nobody should see this - ever!")
encryptedWriter.Write(msg)
if err := encryptedWriter.Close(); err != nil {
	panic(fmt.Sprintf("Failed to finish encryption: %v", err))
}
ciphertext := mem.Bytes()

mem = bytes.NewBuffer(nil)
// So now we want to decrypt the message
decryptedWriter, err := DecryptWriter(mem, key, nonce)
if err != nil {
	panic(fmt.Sprintf("Cannot create decrypted writer: %v", err))
}
decryptedWriter.Write(ciphertext)

// Close finishes the decryption. Close MUST be called to successfully decrypt a
// ciphertext. Further Close returns a non-nil error if the decryption failed - e.g. if
// the authentication failed - so we MUST invoke Close and MUST check if the returned error
// is nil. Otherwise the decryption will fail / was not successfull.
if err := decryptedWriter.Close(); err != nil {
	panic(fmt.Sprintf("Failed to finish decryption: %v", err))
}
fmt.Println(string(mem.Bytes()))
Output:

Nobody should see this - ever!

func EncryptWriter

func EncryptWriter(w io.Writer, key, nonce []byte) (io.WriteCloser, error)

EncryptWriter wraps an io.Writer and returns an io.WriteCloser which encrypts and authenticates all input passed into it with the given key and nonce. The Close function of the returned io.WriteCloser must be called to finish the encryption successfully.

If the Write or Close function of the io.WriteCloser returns a non-nil error the hole encryption process cannot succeed and must be restarted. The length of the nonce determines which cipher is used:

  • 8 byte: ChaCha20Poly1305 with 64 bit nonces
  • 12 byte: ChaCha20Poly1305 with 96 bit nonces (used in TLS)
  • 24 byte: XChaCha20Poly1305 with 192 bit nonces
Example
// we write to memory, real code may write to a file, network connection or ...
mem := bytes.NewBuffer(nil)

// Create a secret key - can also be generated from a passwort or ...
key := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, key); err != nil {
	panic(fmt.Sprintf("Failed to create random encryption key: %v", err))
}

// Set the nonce, in this case we encrypt the first message so we set it to 1.
// Be aware that the nonce must be unique for every message under the same key.
nonce := make([]byte, 8)
binary.LittleEndian.PutUint64(nonce, 1)

encryptedWriter, err := EncryptWriter(mem, key, nonce)
if err != nil {
	panic(fmt.Sprintf("Cannot create encrypted writer: %v", err))
}
// Close finishes the encryption, so it MUST be called! We ensure this through defer.
defer func() {
	if err := encryptedWriter.Close(); err != nil {
		panic(fmt.Sprintf("Failed to finish encryption: %v", err))
	}
}()

msg := []byte("Nobody should see this - ever!")
// encrypt the message
encryptedWriter.Write(msg)
Output:

func NewCipher

func NewCipher(key []byte) (cipher.AEAD, error)

NewCipher returns a cipher.AEAD implementing the ChaCha20Poly1305 construction specified in RFC 7539 with a 128 bit auth. tag.

func NewIETFCipher

func NewIETFCipher(key []byte) (cipher.AEAD, error)

NewIETFCipher returns a cipher.AEAD implementing the ChaCha20Poly1305 construction specified in RFC 7539 with a 128 bit auth. tag.

func NewXCipher

func NewXCipher(key []byte) (cipher.AEAD, error)

NewXCipher returns a cipher.AEAD implementing the XChaCha20Poly1305 construction specified in RFC 7539 with a 128 bit auth. tag.

Types

This section is empty.

Jump to

Keyboard shortcuts

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