siv

package module
v0.0.0-...-5ff4065 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2018 License: MIT Imports: 8 Imported by: 6

README

Godoc Reference Build Status

Warning - This package is just an experimental proof-of-concept implementation. This implementation is currently not optimized for performance or (side channel) security.

SIV

Synthetic Initialization Vector (SIV) is an nonce-misuse resistant authenticated encryption scheme specified in RFC 5297 using AES and CMAC.

Documentation

Overview

Package siv implements the Synthetic Initialization Vector (SIV) authenticated encryption scheme specified in RFC 5297. It also implements AES-GCM-SIV as misuse-resistant version of AES-GCM as proposed by the RFC-draft [1].

AES-GCM-SIV

AES-GCM-SIV is a misuse-resistant AEAD scheme using AES-{128/256} for message privacy and a polynomial authenticator (POLYVAL) for message integrity. In contrast to other AEAD schemes - like AES-GCM - AES-GCM-SIV provides message integrity and message privacy (w.r.t the security of deterministic encryption) even if the nonce is reused. AES-GCM-SIV creates a ciphertext which is 16 bytes longer than the plaintext. The ciphertext consists of the encrypted plaintext followed by the (16 byte) authentication tag. For more details see [1].

AES-SIV-CMAC

AES-SIV-CMAC is a misuse-resistant AEAD scheme using AES-{128/192/256} for message privacy and integrity. In contrast to other AEAD schemes - like AES-GCM - AES-SIV-CMAC provides message integrity and message privacy (w.r.t the security of deterministic encryption) even if the nonce is reused or omitted at all. AES-SIV-CMAC creates a ciphertext which is 16 bytes longer than the plaintext. The ciphertext consists of the authentication tag (16 bytes) followed by the encrypted plaintext. For more details see [2].

Deterministic AEAD

Given the same plaintext and additional data a deterministic AEAD produces always the same ciphertext. Therefore it is not semantically secure. [3] However, any deterministic AEAD implemented by this package accepts a non-nil nonce making the encryption probabilistic. A deterministic AEAD which can be turned into a probabilistic AEAD using a nonce value is called misuse-resistant AEAD.

[1] https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-08 [2] https://tools.ietf.org/html/rfc5297 [3] https://en.wikipedia.org/wiki/Deterministic_encryption

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewCMAC

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

NewCMAC returns a cipher.AEAD implementing AES-SIV-CMAC as specified in RFC 5297. The key must be twice as large as an AES key - so either 32, 48 or 64 bytes long.

The returned cipher.AEAD accepts an empty or NonceSize() bytes long nonce.

Example (Decrypt)
package main

import (
	"encoding/hex"
	"fmt"

	siv "github.com/secure-io/siv-go"
)

func main() {
	// Load your secret key from a safe place and reuse it across multiple
	// Seal/Open calls. (Obviously don't use this example key for anything
	// real.) If you want to convert a passphrase to a key, use a suitable
	// package like argon2 (`go doc golang.org/x/crypto/argon2`).
	// When decoded the key should be 32 bytes (AES-128) or 64 (AES-256).
	key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
	ciphertext, _ := hex.DecodeString("485bdd0e072f857e623620ebad3eb1925bcb1cafc1780d625710b6bcdd34bf79b2")
	var nonce []byte = nil // An empty nonce was used to encrypt the plaintext.

	aessiv, err := siv.NewCMAC(key)
	if err != nil {
		panic(err.Error())
	}

	plaintext, err := aessiv.Open(nil, nonce, ciphertext, nil)
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("%s\n", plaintext)
}
Output:

example_plaintext
Example (Encrypt)
package main

import (
	"encoding/hex"
	"fmt"

	siv "github.com/secure-io/siv-go"
)

func main() {
	// Load your secret key from a safe place and reuse it across multiple
	// Seal/Open calls. (Obviously don't use this example key for anything
	// real.) If you want to convert a passphrase to a key, use a suitable
	// package like argon2 (`go doc golang.org/x/crypto/argon2`).
	// When decoded the key should be 32 bytes (AES-128) or 64 (AES-256).
	key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
	plaintext := []byte("example_plaintext")

	aessiv, err := siv.NewCMAC(key)
	if err != nil {
		panic(err.Error())
	}

	// An empty nonce makes AES-SIV-CMAC a deterministic authenticated encryption
	// scheme (same plaintext && additional data produces the same ciphertext).
	// You can also use a random 16 byte nonce to make AES-SIV-CMAC non-deterministic.
	var nonce []byte = nil

	ciphertext := aessiv.Seal(nil, nonce, plaintext, nil)
	fmt.Printf("%x\n", ciphertext)
}
Output:

485bdd0e072f857e623620ebad3eb1925bcb1cafc1780d625710b6bcdd34bf79b2
Example (EncryptDecrypt)
package main

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io"

	siv "github.com/secure-io/siv-go"
)

func main() {
	// Load your secret key from a safe place and reuse it across multiple
	// Seal/Open calls. (Obviously don't use this example key for anything
	// real.) If you want to convert a passphrase to a key, use a suitable
	// package like argon2 (`go doc golang.org/x/crypto/argon2`).
	// When decoded the key should be 32 bytes (AES-128) or 64 (AES-256).
	key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
	plaintext := []byte("example_plaintext")

	aessiv, err := siv.NewCMAC(key)
	if err != nil {
		panic(err.Error())
	}

	// We use a random nonce to make AES-SIV-CMAC a probabilistic authenticated
	// encryption scheme.
	nonce := make([]byte, aessiv.NonceSize())
	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
		panic(err.Error())
	}

	ciphertext := aessiv.Seal(nil, nonce, plaintext, nil)
	plaintext, err = aessiv.Open(plaintext[:0], nonce, ciphertext, nil)
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("%s\n", plaintext)
}
Output:

example_plaintext

func NewGCM

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

NewGCM returns a cipher.AEAD implementing the AES-GCM-SIV construction. The key must be either 16 or 32 bytes long.

Example (Decrypt)
package main

import (
	"encoding/hex"
	"fmt"

	siv "github.com/secure-io/siv-go"
)

func main() {
	// Load your secret key from a safe place and reuse it across multiple
	// Seal/Open calls. (Obviously don't use this example key for anything
	// real.) If you want to convert a passphrase to a key, use a suitable
	// package like argon2 (`go doc golang.org/x/crypto/argon2`).
	// When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
	key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
	ciphertext, _ := hex.DecodeString("eb87399f2550f35b572b10b1a269b6446dce046bfd35e48208b7efa7a7b934cf69")

	aessiv, err := siv.NewGCM(key)
	if err != nil {
		panic(err.Error())
	}

	nonce := make([]byte, aessiv.NonceSize()) // An fixed nonce was used to encrypt the plaintext.

	plaintext, err := aessiv.Open(nil, nonce, ciphertext, nil)
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("%s\n", plaintext)
}
Output:

example_plaintext
Example (Encrypt)
package main

import (
	"encoding/hex"
	"fmt"

	siv "github.com/secure-io/siv-go"
)

func main() {
	// Load your secret key from a safe place and reuse it across multiple
	// Seal/Open calls. (Obviously don't use this example key for anything
	// real.) If you want to convert a passphrase to a key, use a suitable
	// package like argon2 (`go doc golang.org/x/crypto/argon2`).
	// When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
	key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
	plaintext := []byte("example_plaintext")

	aessiv, err := siv.NewGCM(key)
	if err != nil {
		panic(err.Error())
	}

	// A fixed nonce makes AES-GCM-SIV a deterministic authenticated encryption
	// scheme (same plaintext && additional data produces the same ciphertext).
	// You can also use a random 12 byte nonce to make AES-GCM-SIV non-deterministic.
	nonce := make([]byte, aessiv.NonceSize())

	ciphertext := aessiv.Seal(nil, nonce, plaintext, nil)
	fmt.Printf("%x\n", ciphertext)
}
Output:

eb87399f2550f35b572b10b1a269b6446dce046bfd35e48208b7efa7a7b934cf69
Example (EncryptDecrypt)
package main

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io"

	siv "github.com/secure-io/siv-go"
)

func main() {
	// Load your secret key from a safe place and reuse it across multiple
	// Seal/Open calls. (Obviously don't use this example key for anything
	// real.) If you want to convert a passphrase to a key, use a suitable
	// package like argon2 (`go doc golang.org/x/crypto/argon2`).
	// When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
	key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
	plaintext := []byte("example_plaintext")

	aessiv, err := siv.NewGCM(key)
	if err != nil {
		panic(err.Error())
	}

	// We use a random nonce to make AES-GCM-SIV a probabilistic authenticated
	// encryption scheme.
	nonce := make([]byte, aessiv.NonceSize())
	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
		panic(err.Error())
	}

	ciphertext := aessiv.Seal(nil, nonce, plaintext, nil)
	plaintext, err = aessiv.Open(plaintext[:0], nonce, ciphertext, nil)
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("%s\n", plaintext)
}
Output:

example_plaintext

Types

This section is empty.

Jump to

Keyboard shortcuts

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