Documentation
¶
Overview ¶
Package pomfrit implements the PoMFRIT One-More-MAYO blind signature (Baum, Beckmann, Beullens, Mukherjee, Rechberger — "Concretely Efficient Blind Signatures Based on VOLE-in-the-Head Proofs and the MAYO Trapdoor") in pure, cgo-free Go targeting the TamaGo bare-metal runtime.
It is a faithful transpile of the pq_blind_signatures reference: the vole/optimized_bs C++ VOLE-in-the-Head engine (GGM-forest BAVC, small-VOLE, vole_check universal hashing, degree-2 QuickSilver, the MAYO-eval circuit, and the vole_prove/vole_verify Fiat-Shamir flow) glued to MAYO-C's salt-free preimage sampler (mayo.SignWithoutHashing in the sibling mayo package). Every layer is validated byte-for-byte against dumpers compiled from those reference sources; the AES-CTR PRG and the ZK Horner hash are reused from the sibling faest package.
See SOURCES.md and PLAN.md for per-construct provenance and the verification ledger.
Status ¶
Experimental and unaudited. Correctness rests on reference KATs, not a security review.
Public entry points ¶
MayoOWFL1, MayoOWFL3, MayoOWFL5 // MayoOWF, the three v1 MAYO instances (MayoOWF).Sign1 // user: blind the message, t = h + r mayo.SignWithoutHashing // signer: MAYO preimage of t (sign_2) (MayoOWF).Sign3 // user: VOLE-in-the-Head proof (MayoOWF).BlindVerify // verifier: recompute h, run vole_verify (MayoOWF).Prove / Verify // the underlying VOLE proof pair
Example ¶
The full One-More-MAYO blind signature at L1, playing all three roles: the user blinds the message (sign_1), the signer computes a MAYO preimage of the blinded message (sign_2), the user turns it into a VOLE-in-the-Head proof (sign_3), and the verifier checks the proof without ever seeing the signer's key or the blinding.
package main
import (
"fmt"
"github.com/maceip/tamayo/mayo"
"github.com/maceip/tamayo/pomfrit"
)
func main() {
o := pomfrit.MayoOWFL1
mp := &mayo.Mayo1
// Signer key material: compact keypair; verifiers use the expanded key.
seed := make([]byte, mp.SKSeedBytes)
cpk, csk, err := mp.CompactKeyGen(seed)
if err != nil {
panic(err)
}
epk, err := mp.ExpandPK(cpk)
if err != nil {
panic(err)
}
msg := []byte("This is a message.")
rAdditional := make([]byte, 32) // session randomness bound into Fiat-Shamir
// sign_1 (user): blind the message, t = h + r.
t, st, h := o.Sign1(msg, rAdditional)
// sign_2 (signer): MAYO preimage of the blinded message.
bsig := mp.SignWithoutHashing(t, csk)
// sign_3 (user): prove knowledge of a valid preimage without revealing it.
proof := o.Sign3(epk, h, bsig, st, rAdditional)
// verify: recompute h and run vole_verify.
fmt.Println("blind signature valid:", o.BlindVerify(epk, msg, proof.Bytes, rAdditional))
tampered := append([]byte(nil), proof.Bytes...)
tampered[0] ^= 1
fmt.Println("tampered rejected:", !o.BlindVerify(epk, msg, tampered, rAdditional))
}
Output: blind signature valid: true tampered rejected: true
Index ¶
- Variables
- type MayoForest
- func (m MayoForest) MayoForestCommit(seed, iv []byte) (voleKeys [][][]byte, hashedLeaves [][]byte, check []byte, forest [][][][]byte)
- func (m MayoForest) MayoForestOpen(forest [][][][]byte, hashedLeaves [][]byte, deltaBytes []byte) []byte
- func (m MayoForest) MayoForestVerify(iv, opening, deltaBytes []byte) (voleKeys [][][]byte, check []byte, leafIdx []int)
- func (m MayoForest) MayoVoleCommit(seed, iv []byte) MayoVoleCommitResult
- func (m MayoForest) TransposeToMacs(v []byte, rows int) [][]byte
- func (m MayoForest) VoleCheckSender(u, v, challenge []byte) (proof, transcriptHash []byte)
- func (m MayoForest) VoleCheckSenderBlocks(u, v, challenge []byte) (proof []byte, colHashes [][]byte)
- func (m MayoForest) VoleCommitSender(seed, iv []byte) (u, v, commitment, check []byte)
- func (m MayoForest) VoleReconstruct(iv, opening, commitment, deltaBytes []byte) (q, check []byte)
- type MayoOWF
- func (o MayoOWF) BlindVerify(epk, m, proof, rAdditional []byte) bool
- func (o MayoOWF) ProofSize() int
- func (o MayoOWF) Prove(sk, pk, rAdditional []byte) MayoProof
- func (o MayoOWF) Prove1(rAdditional []byte) MayoProveState
- func (o MayoOWF) Prove2(st MayoProveState, packedPk, packedSk, rAdditional []byte) MayoProof
- func (o MayoOWF) Sign1(m, rAdditional []byte) (t []byte, st MayoProveState, h []byte)
- func (o MayoOWF) Sign3(epk, h, bsig []byte, st MayoProveState, rAdditional []byte) MayoProof
- func (o MayoOWF) Verify(pk, rAdditional, proof []byte) bool
- type MayoParams
- type MayoProof
- type MayoProveState
- type MayoVoleCommitResult
- type QS2Prover
- func (p *QS2Prover) AddConstraint(x QSP2El)
- func (p *QS2Prover) ConstEl(c []uint64) QSP2El
- func (p *QS2Prover) Field() field.Big
- func (p *QS2Prover) GetWitnessBit(index int) QSP2Bit
- func (p *QS2Prover) LoadWitness4BitsAndCombine(bitIndex int) QSP2El
- func (p *QS2Prover) LoadWitness8BitsAndCombine(bitIndex int) QSP2El
- func (p *QS2Prover) Prove(witnessBits int) (proof, check []byte)
- func (p *QS2Prover) ZeroEl(d int) QSP2El
- type QS2Verifier
- func (v *QS2Verifier) AddConstraint(x QSV2El)
- func (v *QS2Verifier) ConstEl(c []uint64) QSV2El
- func (v *QS2Verifier) Field() field.Big
- func (v *QS2Verifier) GetWitnessBit(index int) QSV2El
- func (v *QS2Verifier) LoadWitness4BitsAndCombine(bitIndex int) QSV2El
- func (v *QS2Verifier) LoadWitness8BitsAndCombine(bitIndex int) QSV2El
- func (v *QS2Verifier) Verify(witnessBits int, proof []byte) (check []byte)
- func (v *QS2Verifier) ZeroEl(d int) QSV2El
- type QSP2Bit
- type QSP2El
- type QSV2El
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( MayoForestL1 = NewMayoForest(9, 16, 3752) MayoForestL3 = NewMayoForest(14, 24, 5624) MayoForestL5 = NewMayoForest(19, 32, 7960) )
The three v1 MAYO small parameter sets (mayo_{128,192,256}_s). WitnessBits from VOLEMAYO_WITNESS_SIZE_BITS: L1 4*78+4*10*86, L3 4*108+4*11*118, L5 4*142+4*12*154.
var ( VoleMayoL1 = MayoParams{N: 86, M: 78, O: 8, V: 78, K: 10, FTail: [4]byte{8, 1, 1, 0}} VoleMayoL3 = MayoParams{N: 118, M: 108, O: 10, V: 108, K: 11, FTail: [4]byte{8, 0, 1, 7}} VoleMayoL5 = MayoParams{N: 154, M: 142, O: 12, V: 142, K: 12, FTail: [4]byte{4, 0, 8, 1}} )
The three v1 MAYO instances (L1/L3/L5). F_TAIL from VOLEMAYO_F_TAIL_{78,108,142}.
var ( MayoOWFL1 = MayoOWF{MayoForestL1, VoleMayoL1} MayoOWFL3 = MayoOWF{MayoForestL3, VoleMayoL3} MayoOWFL5 = MayoOWF{MayoForestL5, VoleMayoL5} )
The three v1 MAYO small instances.
Functions ¶
This section is empty.
Types ¶
type MayoForest ¶
type MayoForest struct {
Tau int
LambdaBytes int
WitnessBits int
// contains filtered or unexported fields
}
MayoForest is one v1 MAYO ggm_forest parameter set. minK/maxK and the tree counts are pure functions of (Tau, lambda) exactly as in VECTOR_COMMITMENT_CONSTANTS<TAU, DELTA_BITS=lambda>. WitnessBits = VOLEMAYO_WITNESS_SIZE_BITS (= 4*M + 4*K*N) fixes the VOLE row count.
func NewMayoForest ¶
func NewMayoForest(tau, lambdaBytes, witnessBits int) MayoForest
NewMayoForest builds the parameter set for the given tau, lambda (bytes) and witness-bit count.
func (MayoForest) MayoForestCommit ¶
func (m MayoForest) MayoForestCommit(seed, iv []byte) (voleKeys [][][]byte, hashedLeaves [][]byte, check []byte, forest [][][][]byte)
MayoForestCommit expands all TAU trees from the seed and returns the per-tree natural-order small-VOLE leaf keys (first lambda bytes of each leaf's shake hash), the per-tree concatenated leaf hashes (the next 2*lambda), and the hash-of-hashes check (2*lambda). Transpiled from ggm_forest_bavc::commit + hash_hashed_leaves.
func (MayoForest) MayoForestOpen ¶
func (m MayoForest) MayoForestOpen(forest [][][][]byte, hashedLeaves [][]byte, deltaBytes []byte) []byte
MayoForestOpen produces the all-but-Delta opening: for each tree, walk from the root along the Delta-selected path (LSB-first per level, delta byte 0/0xff) emitting the sibling node key at each level, then the hidden leaf's 2*lambda hash. Transpiled from ggm_forest_bavc::open. deltaBytes is the per-tree little-endian expanded Delta (delta_bits bytes total).
func (MayoForest) MayoForestVerify ¶
func (m MayoForest) MayoForestVerify(iv, opening, deltaBytes []byte) (voleKeys [][][]byte, check []byte, leafIdx []int)
MayoForestVerify reconstructs, per tree, all leaf VOLE keys except the hidden one (from the opening's co-path siblings) plus every leaf hash (the hidden leaf's hash comes from the opening tail), and recomputes the hash-of-hashes check. Transpiled from ggm_forest_bavc::verify. deltaBytes is the expanded per-tree Delta (lambda bytes). Returns per-tree natural-order vole keys (the hidden slot is a zero dummy), the hash-of-hashes check, and the per-tree hidden leaf indices.
func (MayoForest) MayoVoleCommit ¶
func (m MayoForest) MayoVoleCommit(seed, iv []byte) MayoVoleCommitResult
MayoVoleCommit runs the full sender vole_commit and keeps the BAVC forest and leaf hashes for a subsequent Open. Transpiled from vole_commit.inc vole_commit.
func (MayoForest) TransposeToMacs ¶
func (m MayoForest) TransposeToMacs(v []byte, rows int) [][]byte
TransposeToMacs converts the column-major VOLE matrix (lambda columns, each colLen 16-byte blocks) into row-major field elements: macs[row] is the lambda-bit value whose bit c is column c's bit `row`. Matches transpose_secpar truncated to the given number of rows. Returns rows field elements as bytes.
func (MayoForest) VoleCheckSender ¶
func (m MayoForest) VoleCheckSender(u, v, challenge []byte) (proof, transcriptHash []byte)
VoleCheckSender is VoleCheckSenderBlocks plus the fresh-hasher finalization (u_tilde ++ v-col hashes -> 2*lambda), used by the isolated vole_check KAT.
func (MayoForest) VoleCheckSenderBlocks ¶
func (m MayoForest) VoleCheckSenderBlocks(u, v, challenge []byte) (proof []byte, colHashes [][]byte)
VoleCheckSenderBlocks runs the sender vole_check over (u, v) and returns the ordered blocks it absorbs into the transcript hasher: the u_tilde proof (HASH_BYTES = lambda+2) followed by the lambda v-column hashes. Transpiled from vole_check_both (verifier=false): col=-1 (u) yields u_tilde and is absorbed first, then each v column.
func (MayoForest) VoleCommitSender ¶
func (m MayoForest) VoleCommitSender(seed, iv []byte) (u, v, commitment, check []byte)
VoleCommitSender runs vole_commit's sender path: BAVC-commit the seed, then small-VOLE each tree, gluing the columns into the full v matrix and emitting tree 0's accum as u and the later trees' corrections into commitment. Returns u (COL_LEN blocks), v (lambda columns * COL_LEN blocks), the corrections commitment (VOLE_ROWS/8 bytes per tree>0) and the BAVC check.
func (MayoForest) VoleReconstruct ¶
func (m MayoForest) VoleReconstruct(iv, opening, commitment, deltaBytes []byte) (q, check []byte)
VoleReconstruct rebuilds the verifier VOLE tags q (lambda columns, column- major) from the opening and the BAVC corrections. Transpiled from vole_reconstruct. Returns q and the recomputed vole_commit check.
type MayoOWF ¶
type MayoOWF struct {
F MayoForest
P MayoParams
}
MayoOWF binds the ggm_forest/VOLE parameters (MayoForest) with the whipped MAYO map parameters (MayoParams) for one security level.
func (MayoOWF) BlindVerify ¶
BlindVerify is the blind-signature verify: recompute h = SHAKE256(m || proof1) from the proof and check the VOLE proof against epk || h. Malformed proofs and wrong-sized keys are rejected, not panicked on.
func (MayoOWF) ProofSize ¶
ProofSize returns the exact byte length of a proof for this instance (6895/15862/29615 for L1/L3/L5).
func (MayoOWF) Prove ¶
Prove runs vole_prove_1 + vole_prove_2 in one shot (used by the VOLE-only KAT). sk is the packed secret key (public || witness), pk the packed public key (expanded_pk || h).
func (MayoOWF) Prove1 ¶
func (o MayoOWF) Prove1(rAdditional []byte) MayoProveState
Prove1 runs vole_prove_1: derive the VOLE seed/iv deterministically from SHAKE(0x03)/H4, commit the ggm_forest VOLE, and derive r and chal1.
func (MayoOWF) Prove2 ¶
func (o MayoOWF) Prove2(st MayoProveState, packedPk, packedSk, rAdditional []byte) MayoProof
Prove2 runs vole_prove_2 from a prove-1 state, the packed pk (expanded_pk || h) and packed sk (packed_pk || r || witness_s), returning the full proof.
func (MayoOWF) Sign1 ¶
func (o MayoOWF) Sign1(m, rAdditional []byte) (t []byte, st MayoProveState, h []byte)
Sign1 is the blind-signature sign_1: run prove_1, form the blinded message t = h + r with h = SHAKE256(m || proof1), and return t, the carried state, and h. h uses SHAKE256 at every level (reference mayo-c-sys shake256).
func (MayoOWF) Sign3 ¶
func (o MayoOWF) Sign3(epk, h, bsig []byte, st MayoProveState, rAdditional []byte) MayoProof
Sign3 is the blind-signature sign_3: assemble packed_pk = epk || h and packed_sk = packed_pk || r || bsig, then run prove_2. bsig is the MAYO preimage of t from sign_2 (mayo.SignWithoutHashing).
type MayoParams ¶
MayoParams is the whipped MAYO instance proven by One-More-MAYO. Values from pq_blind_signatures vole/optimized_bs/parameters.hpp (VOLEMAYO_*): N, M, O, V=N-O, K, and the whipping tail polynomial F_TAIL.
func (MayoParams) MayoConstraintProve ¶
func (p MayoParams) MayoConstraintProve(qs *QS2Prover, pkBytes, h, chal2 []byte)
MayoConstraintProve builds the prover's degree-2 constraint element u + t_embedded and folds it into the QuickSilver via AddConstraint. Transpiled from enc_constraints (prover instantiation).
func (MayoParams) MayoConstraintVerify ¶
func (p MayoParams) MayoConstraintVerify(qs *QS2Verifier, pkBytes, h, chal2 []byte)
MayoConstraintVerify builds the verifier's evaluation of u + t_embedded and folds it into the QuickSilver. Transpiled from enc_constraints (verifier).
type MayoProof ¶
type MayoProof struct {
Bytes []byte
Commitment []byte
UTilde []byte
D []byte
QSProof []byte
Opening []byte
Delta []byte
IVPre []byte
}
MayoProof holds the assembled One-More-MAYO VOLE proof and its ordered segments, matching the reference proof byte layout.
type MayoProveState ¶
type MayoProveState struct {
VC MayoVoleCommitResult
IVPre []byte
Chal1 []byte
R []byte
}
MayoProveState is the vole_prove_1 output carried into vole_prove_2 (the VOLEMAYOProofState of the reference): the VOLE correlation, BAVC artifacts, the derived r (= u[:R_BYTES]), the commitment (proof1) and chal1.
type MayoVoleCommitResult ¶
type MayoVoleCommitResult struct {
U, V, Commitment, Check []byte
Forest [][][][]byte
HashedLeaves [][]byte
}
MayoVoleCommitResult bundles the sender vole_commit outputs plus the BAVC artifacts (forest, hashed leaves) needed to open at Delta later.
type QS2Prover ¶
type QS2Prover struct {
// contains filtered or unexported fields
}
QS2Prover mirrors quicksilver_state<S, false, 2>. macs holds one field element per witness bit, including the lambda MAC-mask bits appended after the real witness; witness likewise carries lambda/8 extra mask bytes.
func NewQS2Prover ¶
NewQS2Prover initializes the prover state from the 3*lambda+64-bit QuickSilver challenge, one ZKHasher per MAC-polynomial coefficient.
func (*QS2Prover) AddConstraint ¶
AddConstraint mirrors add_constraint: x is lifted to degree 2, its committed value must be zero, and MAC coefficient i feeds hasher i.
func (*QS2Prover) GetWitnessBit ¶
GetWitnessBit mirrors get_witness_bit: degree-1 gf2 with the bit's MAC as the constant coefficient.
func (*QS2Prover) LoadWitness4BitsAndCombine ¶
LoadWitness4BitsAndCombine mirrors load_witness_4_bits_and_combine.
func (*QS2Prover) LoadWitness8BitsAndCombine ¶
LoadWitness8BitsAndCombine mirrors load_witness_8_bits_and_combine.
type QS2Verifier ¶
type QS2Verifier struct {
// contains filtered or unexported fields
}
QS2Verifier mirrors quicksilver_state<S, true, 2>. macs holds the verifier keys (tag + bit*Delta) for every witness bit including the mask bits.
func NewQS2Verifier ¶
NewQS2Verifier initializes the verifier state; deltaPowers = [Delta, Delta^2] as in the reference constructor.
func (*QS2Verifier) AddConstraint ¶
func (v *QS2Verifier) AddConstraint(x QSV2El)
AddConstraint mirrors add_constraint (verifier): lift to degree 2 and hash the evaluation.
func (*QS2Verifier) ConstEl ¶
func (v *QS2Verifier) ConstEl(c []uint64) QSV2El
ConstEl returns the degree-0 public constant c.
func (*QS2Verifier) Field ¶
func (v *QS2Verifier) Field() field.Big
func (*QS2Verifier) GetWitnessBit ¶
func (v *QS2Verifier) GetWitnessBit(index int) QSV2El
GetWitnessBit mirrors get_witness_bit (verifier): degree 1, the key.
func (*QS2Verifier) LoadWitness4BitsAndCombine ¶
func (v *QS2Verifier) LoadWitness4BitsAndCombine(bitIndex int) QSV2El
LoadWitness4BitsAndCombine mirrors the verifier combine_4_bits path.
func (*QS2Verifier) LoadWitness8BitsAndCombine ¶
func (v *QS2Verifier) LoadWitness8BitsAndCombine(bitIndex int) QSV2El
LoadWitness8BitsAndCombine mirrors the verifier combine_8_bits path.
func (*QS2Verifier) Verify ¶
func (v *QS2Verifier) Verify(witnessBits int, proof []byte) (check []byte)
Verify mirrors verify(witness_bits, proof, check): the key mask plus proof * Delta^(max_deg-1) closes the hash.
func (*QS2Verifier) ZeroEl ¶
func (v *QS2Verifier) ZeroEl(d int) QSV2El
ZeroEl returns the zero element of degree d.
type QSP2Bit ¶
type QSP2Bit struct {
// contains filtered or unexported fields
}
QSP2Bit mirrors quicksilver_gf2<prover, deg>: deg ascending MAC coefficients plus the committed bit.
type QSP2El ¶
type QSP2El struct {
// contains filtered or unexported fields
}
QSP2El mirrors quicksilver_gfsecpar<prover, deg>: deg+1 ascending MAC coefficients, mac[deg] being the committed value.
func (QSP2El) Add ¶
Add returns a + b, lifting the lower-degree operand as the reference's implicit conversion constructors do.
func (QSP2El) AddOne ¶
AddOne returns a + 1 (operator+(a, poly1)): the constant is a same-degree gfsecpar whose only nonzero coefficient is the leading one.
func (QSP2El) Mul ¶
Mul returns a * b; degrees add. Coefficient k of the product MAC polynomial is Sum_{i+j=k} a[i]*b[j] (poly2d operator* followed by reduce_to).
type QSV2El ¶
type QSV2El struct {
// contains filtered or unexported fields
}
QSV2El mirrors both verifier value types (gf2 derives from gfsecpar in the reference): the MAC polynomial evaluated at Delta, plus the degree.