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 ¶
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 ¶
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.