xoodyak

package
v1.0.3021 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2024 License: Apache-2.0 Imports: 7 Imported by: 1

Documentation

Index

Examples

Constants

View Source
const (
	// KeyLen is the number of bytes for Xoodyak AEAD encryption keys
	KeyLen = 16
	// TagLen is the number of authentication tag bytes generated by Xoodyak AEAD
	TagLen = 16
	// NonceLen is the number of bytes required for Xoodyak AEAD nonce
	NonceLen = 16
)
View Source
const (
	AbsorbCdInit  uint8 = 0x03
	AbsorbCdMain  uint8 = 0x00
	SqueezeCuInit uint8 = 0x40
	CryptCuInit   uint8 = 0x80
	CryptCuMain   uint8 = 0x00
	CryptCd       uint8 = 0x00
	RatchetCu     uint8 = 0x10
)

Variables

View Source
var (
	// ErrAuthOpen is returned when the AEAD tag fails to authenticate the decrypted plaintext message
	ErrAuthOpen = errors.New("xoodyak/aead: message authentication failed")

	// ErrEncryptStreamClosed is returned when trying to close an EncryptStream that has previously been closed
	ErrEncryptStreamClosed = errors.New("xoodyak/aead: encryptstream already closed")
)

Functions

func CryptoDecryptAEAD

func CryptoDecryptAEAD(in, key, id, ad, tag []byte) (pt []byte, valid bool, err error)

CryptoDecryptAEAD decrypts and authenticates a ciphertext message given a 16-byte key, 16-byte nonce. optional associated metadata bytes, and a 16 byte authentication tag generated at encryption. The valid flag is true if the provided tag validates the decrypted plaintext and is false if the message or tag or invalid (no error is returned in this case) The plaintext message is only returned if authentication is successful This decryption process is compatible with the Xoodyak LWC AEAD implementation.

func CryptoEncryptAEAD

func CryptoEncryptAEAD(in, key, id, ad []byte) (ct, tag []byte, err error)

CryptoEncryptAEAD encrypts a plaintext message given a 16-byte key, 16-bytes nonce, and optional associated metadata bytes. Along with a cipher text, a 16-byte authentication tag is also generated The ciphertext and tag data is compatible with the Xoodyak LWC AEAD implementation.

Example
package main

import (
	"fmt"

	"strings"

	"github.com/deatil/go-cryptobin/cipher/xoodoo/xoodyak"
)

func main() {
	myMsg := []byte("hello xoodoo")
	// Normally, this is randomly generated and kept secret
	myKey := []byte{
		0x0F, 0x0E, 0x0D, 0x0C,
		0x0B, 0x0A, 0x09, 0x08,
		0x07, 0x06, 0x05, 0x04,
		0x03, 0x02, 0x01, 0x00,
	}
	// Normally, this is randomly generated and never repeated per key
	myNonce := []byte{
		0xF0, 0xE1, 0xD2, 0xC3,
		0xB4, 0xA5, 0x96, 0x87,
		0x78, 0x69, 0x5A, 0x4B,
		0x3C, 0x2D, 0x1E, 0x0F,
	}
	// Any sort of non-secret information about the plaintext or context of encryption
	myAD := []byte("33°59’39.51″N, 7°50’33.69″E")
	myCt, myTag, _ := xoodyak.CryptoEncryptAEAD(myMsg, myKey, myNonce, myAD)
	myPt, valid, _ := xoodyak.CryptoDecryptAEAD(myCt, myKey, myNonce, myAD, myTag)
	var output strings.Builder
	fmt.Fprintf(&output, "Msg:'%s'\n", myMsg)
	fmt.Fprintf(&output, "Key:%x\n", myKey)
	fmt.Fprintf(&output, "Nonce:%x\n", myNonce)
	fmt.Fprintf(&output, "Metadata:%x\n", myAD)
	fmt.Fprintf(&output, "Ciphertext:%x\n", myCt)
	fmt.Fprintf(&output, "AuthTag:%x\n", myTag)
	fmt.Fprintf(&output, "DecryptOK:%t\n", valid)
	fmt.Fprintf(&output, "Plaintext:'%s'", myPt)
	fmt.Println(output.String())
}
Output:

Msg:'hello xoodoo'
Key:0f0e0d0c0b0a09080706050403020100
Nonce:f0e1d2c3b4a5968778695a4b3c2d1e0f
Metadata:3333c2b03539e2809933392e3531e280b34e2c2037c2b03530e2809933332e3639e280b345
Ciphertext:fffc82f88d8bb2ba4f38b85d
AuthTag:6ef42d19830b3f0ecd784be7f4d10f46
DecryptOK:true
Plaintext:'hello xoodoo'

func HashXoodyak

func HashXoodyak(in []byte) []byte

HashXoodyak calculates a 32-byte hash on a provided slice of bytes. The output is compatible with the Xoodyak LWC definition

Example
package main

import (
	"fmt"

	"github.com/deatil/go-cryptobin/cipher/xoodoo/xoodyak"
)

func main() {
	myMsg := []byte("hello xoodoo")
	myHash := xoodyak.HashXoodyak(myMsg)
	fmt.Printf("Msg:'%s'\nHash:%x\n", myMsg, myHash)
}
Output:

Msg:'hello xoodoo'
Hash:5c9a95363d79b2157cbdfff49dddaf1f20562dc64644f2d28211478537e6b29a

func HashXoodyakLen

func HashXoodyakLen(in []byte, hLen uint) []byte

HashXoodyakLen calculates a cryptographic hash of arbitrary length on a provided slice of bytes

Example
package main

import (
	"fmt"

	"github.com/deatil/go-cryptobin/cipher/xoodoo/xoodyak"
)

func main() {
	myMsg := []byte("hello xoodoo")
	myHash := xoodyak.HashXoodyakLen(myMsg, 64)
	fmt.Printf("Msg:'%s'\nHash:%x\n", myMsg, myHash)
}
Output:

Msg:'hello xoodoo'
Hash:5c9a95363d79b2157cbdfff49dddaf1f20562dc64644f2d28211478537e6b29a5675a6d4a3fe18b985e7ae018133c118a44c5f82b3672492a30408937e5712cb

func MACXoodyak

func MACXoodyak(key, msg []byte, macLen uint) []byte

MACXoodyak generates a message authentication code of the desired length in bytes for the provided message based on the provided key data. This implements the MAC behavior described in section 1.3.2 of the Xoodyak specification.

Example
package main

import (
	"fmt"

	"github.com/deatil/go-cryptobin/cipher/xoodoo/xoodyak"
)

func main() {
	myMsg := []byte("hello xoodoo")
	/* use a secret value here */
	myKey := []byte("abcdefghijklmnop")
	myMac := xoodyak.MACXoodyak(myKey, myMsg, 32)
	fmt.Printf("Key:%x\nMsg:'%s'\nMAC:%x\n", myKey, myMsg, myMac)
}
Output:

Key:6162636465666768696a6b6c6d6e6f70
Msg:'hello xoodoo'
MAC:57abf40d9927f0ed5e65ef5b57a3ecc2da46ebb4f3fc5346202056e2b24e6121

func NewXoodyakAEAD

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

NewXoodyakAEAD accepts a set of key bytes and returns object compatible with the stdlib crypto/cipher AEAD interface

Example
package main

import (
	"fmt"
	"log"

	"strings"

	"github.com/deatil/go-cryptobin/cipher/xoodoo/xoodyak"
)

func main() {
	myMsg := []byte("hello xoodoo")
	// Normally, this is randomly generated and kept secret
	myKey := []byte{
		0x0F, 0x0E, 0x0D, 0x0C,
		0x0B, 0x0A, 0x09, 0x08,
		0x07, 0x06, 0x05, 0x04,
		0x03, 0x02, 0x01, 0x00,
	}
	// Normally, this is randomly generated and never repeated per key
	myNonce := []byte{
		0xF0, 0xE1, 0xD2, 0xC3,
		0xB4, 0xA5, 0x96, 0x87,
		0x78, 0x69, 0x5A, 0x4B,
		0x3C, 0x2D, 0x1E, 0x0F,
	}
	// Any sort of non-secret data
	myAD := []byte("33°59’39.51″N, 7°50’33.69″E")
	myXkAEAD, _ := xoodyak.NewXoodyakAEAD(myKey)

	myAuthCt := myXkAEAD.Seal(nil, myNonce, myMsg, myAD)
	myPt, err := myXkAEAD.Open(nil, myNonce, myAuthCt, myAD)
	// error is returned on decrypt authentication failure
	if err != nil {
		log.Fatal(err)
	}
	var output strings.Builder
	fmt.Fprintf(&output, "Msg:'%s'\n", myMsg)
	fmt.Fprintf(&output, "Key:%x\n", myKey)
	fmt.Fprintf(&output, "Nonce:%x\n", myNonce)
	fmt.Fprintf(&output, "Metadata:%x\n", myAD)
	fmt.Fprintf(&output, "Authenticated Ciphertext:%x\n", myAuthCt)
	fmt.Fprintf(&output, "Plaintext:'%s'", myPt)
	fmt.Println(output.String())
}
Output:

Msg:'hello xoodoo'
Key:0f0e0d0c0b0a09080706050403020100
Nonce:f0e1d2c3b4a5968778695a4b3c2d1e0f
Metadata:3333c2b03539e2809933392e3531e280b34e2c2037c2b03530e2809933332e3639e280b345
Authenticated Ciphertext:fffc82f88d8bb2ba4f38b85d6ef42d19830b3f0ecd784be7f4d10f46
Plaintext:'hello xoodoo'

func NewXoodyakHash

func NewXoodyakHash() hash.Hash

NewXoodyakHash returns a initialized Xoodyak digest object compatible with the stdlib Hash interface

Example
package main

import (
	"io"

	"bytes"
	"fmt"

	"github.com/deatil/go-cryptobin/cipher/xoodoo/xoodyak"
)

func main() {
	myMsg := []byte("hello xoodoo")
	msgBuf := bytes.NewBuffer(myMsg)
	xHash := xoodyak.NewXoodyakHash()
	io.Copy(xHash, msgBuf)
	myHash := xHash.Sum(nil)
	fmt.Printf("Msg:'%s'\nHash:%x\n", myMsg, myHash)
}
Output:

Msg:'hello xoodoo'
Hash:5c9a95363d79b2157cbdfff49dddaf1f20562dc64644f2d28211478537e6b29a

func NewXoodyakMac

func NewXoodyakMac(key []byte) hash.Hash

NewXoodyakMac generates a new hashing object with the provided key data already baked in. Writing Any data then written to the hash object is part of the MAC check. Note that the length of the resulting MAC matches that of the official Xoodyak hash output: 32 bytes

Example
package main

import (
	"fmt"

	"github.com/deatil/go-cryptobin/cipher/xoodoo/xoodyak"
)

func main() {
	myMsg := []byte("hello xoodoo")
	/* use a secret value here */
	myKey := []byte("abcdefghijklmnop")
	newMac := xoodyak.NewXoodyakMac(myKey)
	newMac.Write(myMsg)
	myMac := newMac.Sum(nil)
	fmt.Printf("Key:%x\nMsg:'%s'\nMAC:%x\n", myKey, myMsg, myMac)
}
Output:

Key:6162636465666768696a6b6c6d6e6f70
Msg:'hello xoodoo'
MAC:57abf40d9927f0ed5e65ef5b57a3ecc2da46ebb4f3fc5346202056e2b24e6121

Types

type CryptMode

type CryptMode int

CryptMode defines if a Xoodyak instance (already running in keyed mode) is encrypting or decrypting provided message data

const (
	Encrypting CryptMode = iota + 1
	Decrypting
)

type CyclistMode

type CyclistMode int

CyclistMode defines if a Xoodyak instance should be running in hashing mode or encryption (keyed) modes

const (
	Hash CyclistMode = iota + 1
	Keyed
)

type CyclistPhase

type CyclistPhase int

CyclistPhase defines if a Xoodyak instance should perform the Up or Down method in the current Cyclist iteration

const (
	Down CyclistPhase = iota + 1
	Up
)

type DecryptStream

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

DecryptStream implements an io.Reader that can decrypt a stream of bytes according to the Xoodyak LWC AEAD specification. The input stream of ciphertext must have a valid authentication tag as the final 16 bytes, but may be proceeded by a encrypted message of any length (including zero)

func NewDecryptStream

func NewDecryptStream(source io.Reader, key, id, ad []byte) (*DecryptStream, error)

NewDecryptStream wraps an existing io.Reader with the Xoodyak AEAD decryption engine with a given encryption key, nonce(id) and metadata(ad).

Example
package main

import (
	"bytes"
	"fmt"
	"log"
	"strings"

	"github.com/deatil/go-cryptobin/cipher/xoodoo/xoodyak"
)

func main() {
	myCt := []byte{
		0xff, 0xfc, 0x82, 0xf8,
		0x8d, 0x8b, 0xb2, 0xba,
		0x4f, 0x38, 0xb8, 0x5d,
		0x6e, 0xf4, 0x2d, 0x19,
		0x83, 0x0b, 0x3f, 0x0e,
		0xcd, 0x78, 0x4b, 0xe7,
		0xf4, 0xd1, 0x0f, 0x46}
	myCtBuf := bytes.NewBuffer(myCt)
	// Normally, this is randomly generated and kept secret
	myKey := []byte{
		0x0F, 0x0E, 0x0D, 0x0C,
		0x0B, 0x0A, 0x09, 0x08,
		0x07, 0x06, 0x05, 0x04,
		0x03, 0x02, 0x01, 0x00,
	}
	// Normally, this is randomly generated and never repeated per key
	myNonce := []byte{
		0xF0, 0xE1, 0xD2, 0xC3,
		0xB4, 0xA5, 0x96, 0x87,
		0x78, 0x69, 0x5A, 0x4B,
		0x3C, 0x2D, 0x1E, 0x0F,
	}
	// Any sort of non-secret data
	myAD := []byte("33°59’39.51″N, 7°50’33.69″E")
	myXkDecrypt, _ := xoodyak.NewDecryptStream(myCtBuf, myKey, myNonce, myAD)

	myPt := make([]byte, 12)
	_, gotErr := myXkDecrypt.Read(myPt)
	// error is returned on decrypt authentication failure
	if gotErr != nil {
		log.Fatal(gotErr)
	}

	var output strings.Builder
	fmt.Fprintf(&output, "Input Ciphertext:%x\n", myCt)
	fmt.Fprintf(&output, "Key:%x\n", myKey)
	fmt.Fprintf(&output, "Nonce:%x\n", myNonce)
	fmt.Fprintf(&output, "Metadata:%x\n", myAD)
	fmt.Fprintf(&output, "Output Message:'%s'\n", string(myPt))
	fmt.Println(output.String())
}
Output:

Input Ciphertext:fffc82f88d8bb2ba4f38b85d6ef42d19830b3f0ecd784be7f4d10f46
Key:0f0e0d0c0b0a09080706050403020100
Nonce:f0e1d2c3b4a5968778695a4b3c2d1e0f
Metadata:3333c2b03539e2809933392e3531e280b34e2c2037c2b03530e2809933332e3639e280b345
Output Message:'hello xoodoo'

func (*DecryptStream) Read

func (ds *DecryptStream) Read(p []byte) (n int, err error)

Read decrypts ciphertext bytes from the underlying io.Reader and returns then in provided buffer Multiple reads may be used if the resulting plaintext is larger than the provided output buffer Decryption authentication is performed transparently once all ciphertext input is read out. Failure to authenticate returns an error, otherwise no error is returned beyond EOF. A special "authenticate-only" mode is available if a zero length slice is provided for the output buffer. This forces the full ciphertext of the underlying reader to be read-out, decrypted, and authenticated without any plaintext being returned. This is useful for in cases where the integrity of an encrypted payload needs to be checked, but the underlying plaintext is not required or for zero length authenticated token messages that made up of tag bytes only

type EncryptStream

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

EncryptStream implements an io.WriteCloser that can encrypt a stream of bytes according to the Xoodyak LWC AEAD specification.

func NewEncryptStream

func NewEncryptStream(target io.Writer, key, id, ad []byte) (*EncryptStream, error)

NewEncryptStream wraps an existing io.Writer with the Xoodyak LWC AEAD encryption engine given an encryption key, nonce(id) and metadata(ad). The input message may be any length (including zero).

Example
package main

import (
	"bytes"
	"fmt"
	"log"
	"strings"

	"github.com/deatil/go-cryptobin/cipher/xoodoo/xoodyak"
)

func main() {
	myMsg := []byte("hello xoodoo")
	myCTBuf := bytes.NewBuffer(nil)
	// Normally, this is randomly generated and kept secret
	myKey := []byte{
		0x0F, 0x0E, 0x0D, 0x0C,
		0x0B, 0x0A, 0x09, 0x08,
		0x07, 0x06, 0x05, 0x04,
		0x03, 0x02, 0x01, 0x00,
	}
	// Normally, this is randomly generated and never repeated per key
	myNonce := []byte{
		0xF0, 0xE1, 0xD2, 0xC3,
		0xB4, 0xA5, 0x96, 0x87,
		0x78, 0x69, 0x5A, 0x4B,
		0x3C, 0x2D, 0x1E, 0x0F,
	}
	// Any sort of non-secret data
	myAD := []byte("33°59’39.51″N, 7°50’33.69″E")
	myXkEncrypt, _ := xoodyak.NewEncryptStream(myCTBuf, myKey, myNonce, myAD)

	_, gotErr := myXkEncrypt.Write(myMsg)
	// error is returned on decrypt authentication failure
	if gotErr != nil {
		log.Fatal(gotErr)
	}

	myXkEncrypt.Close()

	var output strings.Builder
	fmt.Fprintf(&output, "Msg:'%s'\n", myMsg)
	fmt.Fprintf(&output, "Key:%x\n", myKey)
	fmt.Fprintf(&output, "Nonce:%x\n", myNonce)
	fmt.Fprintf(&output, "Metadata:%x\n", myAD)
	fmt.Fprintf(&output, "Authenticated Ciphertext:%x\n", myCTBuf.Bytes())
	fmt.Println(output.String())
}
Output:

Msg:'hello xoodoo'
Key:0f0e0d0c0b0a09080706050403020100
Nonce:f0e1d2c3b4a5968778695a4b3c2d1e0f
Metadata:3333c2b03539e2809933392e3531e280b34e2c2037c2b03530e2809933332e3639e280b345
Authenticated Ciphertext:fffc82f88d8bb2ba4f38b85d6ef42d19830b3f0ecd784be7f4d10f46

func (*EncryptStream) Close

func (es *EncryptStream) Close() error

Close finalizes the Xoodayak encryption by encrypting/writing any remaining buffered plaintext as well as generating the authentication tag and passing it to the underlying io.Writer. Note: running this method does not also run Close() on the underlying io.Writer; that should be done separately after this writer has been closed.

func (*EncryptStream) Write

func (es *EncryptStream) Write(p []byte) (n int, err error)

Write encrypts the provided bytes and passes them to the underlying io.Writer Multiple writes may be used to write out the complete messagage, but because encryption occurs in blocks, plaintext may be buffered between multiple writes. To ensure all plaintext bytes are encrypted and written along with the authentication tag, the Close() method must be called after the final call to Write

type Xoodyak

type Xoodyak struct {
	Instance    *xoodoo.Xoodoo
	Mode        CyclistMode
	Phase       CyclistPhase
	AbsorbSize  uint
	SqueezeSize uint
}

Xoodyak is a cryptographic object that allows execution of the Cyclist operating mode on the Xoodoo permutation primitive. Xoodyak allows for construction of a variety of hashing, encryption and authentication schemes through assembly of its various operating methods

func Instantiate

func Instantiate(key, id, counter []byte) *Xoodyak

Instantiate generate a new Xoodoo object initialized for hashing or keyed operations

func (*Xoodyak) Absorb

func (xk *Xoodyak) Absorb(x []byte)

Absorb ingests a provided message at the rate of the Xoodyak instance's absorption size

func (*Xoodyak) AbsorbAny

func (xk *Xoodyak) AbsorbAny(x []byte, r uint, cd uint8)

AbsorbAny allow input of any size number of bytes into the Xoodoo state

func (*Xoodyak) AbsorbBlock

func (xk *Xoodyak) AbsorbBlock(x []byte, cd uint8)

AbsorbBlock ingests a single block of bytes encompassing a single iteration of the Cyclist sequence

func (*Xoodyak) AbsorbKey

func (xk *Xoodyak) AbsorbKey(key, id, counter []byte)

AbsorbKey is special Xoodyak method that ingests provided key, id (nonce), and counter messages into the Xoodoo state enabling the keyed mode of operation typically used for authenticated encryption

func (*Xoodyak) Crypt

func (xk *Xoodyak) Crypt(msg []byte, cm CryptMode) []byte

Crypt is core encryption function of Xoodyak/Cyclist. It accepts a byte message of arbitrary length and generates either a ciphertext or plaintext based on the mode provided. Encryption or decryption is accomplished via XOR against a keystream generated from the Xoodoo primitive

func (*Xoodyak) CryptBlock

func (xk *Xoodyak) CryptBlock(msg []byte, cu uint8, cm CryptMode) ([]byte, error)

CryptBlock executes one step of the encryption/decryption cycle on the provided bytes. Useful for building more granular encryption decryption functions

func (*Xoodyak) Decrypt

func (xk *Xoodyak) Decrypt(ct []byte) []byte

Decrypt transforms the provided ciphertext message into a plainext message of equal size based on the Xoodyak instance provided (key, nonce, counter have already been processed)

func (*Xoodyak) Down

func (xk *Xoodyak) Down(Xi []byte, Cd byte)

Down injects the provided slice of bytes into the provided Xoodoo state via xor with the existing state

func (*Xoodyak) Encrypt

func (xk *Xoodyak) Encrypt(pt []byte) []byte

Encrypt transforms the provided plaintext message into a ciphertext message of equal size based on the Xoodyak instance provided (key, nonce, counter have already been processed)

func (*Xoodyak) Ratchet

func (xk *Xoodyak) Ratchet()

Ratchet performs a irreversible transformation of the underlying Xoodoo state to prevent key recovery

func (*Xoodyak) Squeeze

func (xk *Xoodyak) Squeeze(outLen uint) []byte

Squeeze outputs a provided stream of pseudo-random bytes at the rate of the Xoodyak instance's squeeze size

func (*Xoodyak) SqueezeAny

func (xk *Xoodyak) SqueezeAny(YLen uint, Cu uint8) []byte

SqueezeAny allow generation of a message of pseudo-random bytes of any size based on permutating the underlying Xoodoo state

func (*Xoodyak) SqueezeKey

func (xk *Xoodyak) SqueezeKey(keyLen uint) []byte

SqueezeKey can generate a new encryption key from the existing Xoodyak state

func (*Xoodyak) Up

func (xk *Xoodyak) Up(Cu byte, Yilen uint) []byte

Up applies the Xoodoo permutation to the Xoodoo state and returns the requested number of bytes

Jump to

Keyboard shortcuts

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