mayo

package
v0.1.66 Latest Latest
Warning

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

Go to latest
Published: Jul 24, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package mayo implements the MAYO post-quantum signature scheme (NIST PQC round 2 parameters), a whipped Oil-and-Vinegar multivariate signature over GF(16).

It is a pure-Go port of the MAYO reference (PQCMayo/MAYO-C, cross-checked against the pq-mayo Rust crate) and is validated against the official MAYO round 2 known-answer tests. It has no dependencies beyond the Go standard library and this repository's crypto/gf16, so it builds for every GOOS=tamago target.

Example

Sign a message with MAYO-1 and verify it. Key generation and signing are deterministic in the seed and randomizer, mirroring the reference flow where the NIST DRBG supplies both.

package main

import (
	"fmt"

	"github.com/maceip/tamayo/mayo"
)

func main() {
	seed := make([]byte, mayo.Mayo1.SKSeedBytes)
	randomizer := make([]byte, mayo.Mayo1.SaltBytes)

	cpk, csk, err := mayo.Mayo1.CompactKeyGen(seed)
	if err != nil {
		panic(err)
	}

	msg := []byte("This is a message.")
	sig, err := mayo.Mayo1.Sign(msg, csk, randomizer)
	if err != nil {
		panic(err)
	}

	fmt.Println("signature valid:", mayo.Mayo1.Verify(msg, sig, cpk))
	fmt.Println("tampered rejected:", !mayo.Mayo1.Verify([]byte("Another message."), sig, cpk))
}
Output:
signature valid: true
tampered rejected: true

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	Mayo1 = Params{
		Name: "MAYO_1",
		N:    86, M: 78, O: 8, K: 10, MVecLimbs: 5,
		MBytes: 39, OBytes: 312, VBytes: 39, RBytes: 40,
		P1Bytes: 120159, P2Bytes: 24336, P3Bytes: 1404,
		CSKBytes: 24, CPKBytes: 1420, SigBytes: 454,
		SaltBytes: 24, DigestBytes: 32, PKSeedBytes: 16, SKSeedBytes: 24,
		FTail: [4]byte{8, 1, 1, 0},
	}
	Mayo2 = Params{
		Name: "MAYO_2",
		N:    96, M: 64, O: 16, K: 4, MVecLimbs: 4,
		MBytes: 32, OBytes: 640, VBytes: 40, RBytes: 32,
		P1Bytes: 103680, P2Bytes: 40960, P3Bytes: 4352,
		CSKBytes: 24, CPKBytes: 4368, SigBytes: 216,
		SaltBytes: 24, DigestBytes: 32, PKSeedBytes: 16, SKSeedBytes: 24,
		FTail: [4]byte{8, 0, 2, 8},
	}
	Mayo3 = Params{
		Name: "MAYO_3",
		N:    118, M: 108, O: 10, K: 11, MVecLimbs: 7,
		MBytes: 54, OBytes: 540, VBytes: 54, RBytes: 55,
		P1Bytes: 317844, P2Bytes: 58320, P3Bytes: 2970,
		CSKBytes: 32, CPKBytes: 2986, SigBytes: 681,
		SaltBytes: 32, DigestBytes: 48, PKSeedBytes: 16, SKSeedBytes: 32,
		FTail: [4]byte{8, 0, 1, 7},
	}
	Mayo5 = Params{
		Name: "MAYO_5",
		N:    154, M: 142, O: 12, K: 12, MVecLimbs: 9,
		MBytes: 71, OBytes: 852, VBytes: 71, RBytes: 72,
		P1Bytes: 720863, P2Bytes: 120984, P3Bytes: 5538,
		CSKBytes: 40, CPKBytes: 5554, SigBytes: 964,
		SaltBytes: 40, DigestBytes: 64, PKSeedBytes: 16, SKSeedBytes: 40,
		FTail: [4]byte{4, 0, 8, 1},
	}
)

The four MAYO round 2 parameter sets.

Functions

This section is empty.

Types

type Params

type Params struct {
	Name string

	N int // total variables
	M int // equations
	O int // oil dimension
	K int // whipping parameter

	MVecLimbs int // u64 limbs per m-vector (bitsliced form)

	MBytes int // m field elements, nibble-packed
	OBytes int // O matrix, nibble-packed
	VBytes int // vinegar vector, nibble-packed
	RBytes int // random vector r, nibble-packed

	P1Bytes int
	P2Bytes int
	P3Bytes int

	CSKBytes int // compact secret key
	CPKBytes int // compact public key
	SigBytes int

	SaltBytes   int
	DigestBytes int
	PKSeedBytes int
	SKSeedBytes int

	FTail [fTailLen]byte // tail coefficients of the irreducible f(X)
}

Params holds the constants of one MAYO parameter set.

Field element count is over GF(16); byte sizes below are the nibble-packed serializations used by the reference.

func (*Params) ACols

func (p *Params) ACols() int

ACols is the number of columns of the linearized system A (k*o + 1).

func (*Params) CompactKeyGen

func (p *Params) CompactKeyGen(seedSK []byte) (cpk, csk []byte, err error)

CompactKeyGen derives a compact keypair from a secret seed of SKSeedBytes, as MAYO-C mayo_keypair does from its DRBG output. Deterministic in seedSK.

func (*Params) ExpandPK

func (p *Params) ExpandPK(cpk []byte) ([]byte, error)

ExpandPK expands the compact public key into the full bitsliced public map P1 ‖ P2 ‖ P3 serialized as little-endian uint64 limbs — byte-identical to MAYO-C mayo_expand_pk's output buffer, and the epk format the pomfrit blind-signature engine consumes.

func (*Params) KeyGen

func (p *Params) KeyGen(rand io.Reader) (cpk, csk []byte, err error)

KeyGen samples a compact keypair with a fresh seed drawn from rand.

func (*Params) P1Limbs

func (p *Params) P1Limbs() int

P1Limbs is the number of u64 limbs for P1 in bitsliced form.

func (*Params) P2Limbs

func (p *Params) P2Limbs() int

P2Limbs is the number of u64 limbs for P2 in bitsliced form.

func (*Params) P3Limbs

func (p *Params) P3Limbs() int

P3Limbs is the number of u64 limbs for P3 in bitsliced form.

func (*Params) Sign

func (p *Params) Sign(msg, csk, randomizer []byte) ([]byte, error)

Sign produces a MAYO signature (SigBytes: s ‖ salt) on msg under csk. The salt is derived from randomizer (SaltBytes), matching the reference flow where the NIST DRBG supplies it; fixing randomizer makes signing deterministic and reproduces the NIST KAT signatures byte-for-byte.

func (*Params) SignWithoutHashing

func (p *Params) SignWithoutHashing(t, csk []byte) []byte

SignWithoutHashing is the MAYO preimage sampler used by One-More-MAYO's blind sign_2. Transpiled from pq_blind_signatures mayo-c-sys mayo_without_hashing.c (mayo_sign_signature_without_hashing): the standard MAYO signer with the message->digest->salt->t hashing chain removed. The target t is supplied directly (m_bytes, nibble-encoded), the vinegar is V = SHAKE256(t || seed_sk || ctr) with NO salt, and the output is encode(s) of length sig_bytes - salt_bytes (no salt appended).

It returns a preimage s (the blinded MAYO signature) with eval_public_map(s) == decode(t), i.e. the vole witness s-part for the ZK proof.

t is attacker-controlled in the blind protocol (the user supplies it), so a wrong-sized t or csk returns nil instead of panicking.

func (*Params) V

func (p *Params) V() int

V is the vinegar dimension v = n - o.

func (*Params) Verify

func (p *Params) Verify(msg, sig, cpk []byte) bool

Verify reports whether sig is a valid MAYO signature on msg under the compact public key cpk.

Jump to

Keyboard shortcuts

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