Documentation
¶
Overview ¶
Package tss defines transport-neutral building blocks shared by the threshold-signature protocol packages in this module.
The root package intentionally does not provide a network transport, durable storage, or secret-at-rest encryption. Callers are responsible for authenticated delivery of envelopes and must construct InboundEnvelope values with OpenEnvelope and transport-verified ReceiveInfo. Confidentiality requirements are defined per payload type by the protocol PolicySet and enforced by EnvelopeGuard.
Security Model ¶
Every protocol session must receive an EnvelopeGuard at its Start* entry point before it can emit or process protocol envelopes. The guard enforces:
- transport authentication (ReceiveInfo.Peer)
- sender identity binding (ReceiveInfo.Peer == Envelope.From)
- confidentiality per protocol policy (DeliveryPolicy.Confidentiality)
- broadcast consistency via BroadcastCertificate where required
- replay detection via ReplayCache
Sessions reject startup and inbound handling when no guard is configured. Production integrations must construct a guard via NewEnvelopeGuard or GuardConfig.BuildGuard with a production PolicySet and a durable ReplayCache.
See docs/security.md for the complete threat model and integration checklist.
Example (EncryptDecrypt) ¶
ExampleStorage_encryptDecrypt demonstrates password-based encryption and decryption of key material using the reference EncryptKeyShareWithPassphrase and DecryptKeyShareWithPassphrase helpers. These functions are intended for local storage encryption at rest; they are NOT a substitute for transport encryption between parties.
package main
import (
"fmt"
"github.com/islishude/tss"
)
func main() {
passphrase := []byte("correct horse battery staple")
keyMaterial := []byte("this is a serialized key share")
// --- 1. Encrypt key material with a passphrase ---
// The optional PassphraseParams can tune Argon2id cost parameters.
// Nil parameters use the documented production defaults.
encrypted, err := tss.EncryptKeyShareWithPassphrase(keyMaterial, passphrase, "my-key-id", nil)
if err != nil {
panic(err)
}
// --- 2. Decrypt the ciphertext with the same passphrase ---
// DecryptKeyShareWithPassphrase verifies the key ID and AEAD tag,
// returning the original plaintext only if both are correct.
decrypted, err := tss.DecryptKeyShareWithPassphrase(encrypted, passphrase, "my-key-id")
if err != nil {
panic(err)
}
fmt.Println(string(decrypted))
}
Output: this is a serialized key share
Index ¶
- Constants
- Variables
- func AckDigest(protocol ProtocolID, sessionID SessionID, round uint8, from PartyID, ...) [32]byte
- func CheckHandlerContext(delivery, session context.Context) error
- func ContainsParty(parties PartySet, id PartyID) bool
- func DecodeBinary[T any](in []byte) (*T, error)
- func DecodeBinaryValue[T any](in []byte) (T, error)
- func DecodeBinaryValueWithLimits[T any, L any](in []byte, limits L) (T, error)
- func DecodeBinaryWithLimits[T any, L any](in []byte, limits L) (*T, error)
- func DecryptKeyShareWithPassphrase(encoded, passphrase []byte, expectedKeyID string) ([]byte, error)
- func DecryptPresignWithPassphrase(encoded, passphrase []byte, expectedKeyID string) ([]byte, error)
- func DecryptSignAttemptWithPassphrase(encoded, passphrase []byte, expectedKeyID string) ([]byte, error)
- func DecryptSignAttemptWithPassphraseAndKeyID(encoded, passphrase []byte) ([]byte, string, error)
- func EncryptKeyShareWithPassphrase(plaintext, passphrase []byte, keyID string, params *PassphraseParams) ([]byte, error)
- func EncryptPresignWithPassphrase(plaintext, passphrase []byte, keyID string, params *PassphraseParams) ([]byte, error)
- func EncryptSignAttemptWithPassphrase(plaintext, passphrase []byte, keyID string, params *PassphraseParams) ([]byte, error)
- func EnvelopeSigningDigest(e Envelope) [32]byte
- func IsAttributableError(err error) bool
- func IsSessionAborted(err error) bool
- func IsSessionCompleted(err error) bool
- func MarshalEnvelopeWithLimits(env Envelope, limits EnvelopeLimits) ([]byte, error)
- func MarshalEvidenceWithLimits(e *BlameEvidence, l EvidenceLimits) ([]byte, error)
- func PartySetHash(parties PartySet, label string) []byte
- func PayloadHashFromEnvelope(env Envelope) [32]byte
- func RequireEnvelopeGuard(guard *EnvelopeGuard, expectedProtocol ProtocolID, expectedSession SessionID, ...) error
- func ValidateEnvelopePolicy(env InboundEnvelope, self PartyID, policies PolicySet) error
- func ValidateInbound(guard *EnvelopeGuard, env InboundEnvelope, expectedProtocol ProtocolID, ...) error
- func ValidateInboundWithoutReplay(guard *EnvelopeGuard, env InboundEnvelope, expectedProtocol ProtocolID, ...) error
- func ValidateSignerSet(keyParties PartySet, threshold int, signers PartySet, limits ThresholdLimits) error
- func VerifyBroadcastAck(env Envelope, ack BroadcastAck, verifier BroadcastAckVerifier) error
- func VerifyBroadcastCertificateWithSignatures(env Envelope, parties PartySet, cert *BroadcastCertificate, ...) error
- func VerifyEnvelopeSignature(e Envelope, verifier EnvelopeSignatureVerifier) error
- type Algorithm
- type AttackMode
- type BinaryUnmarshalerWithLimits
- type Blame
- type BlameEvidence
- func NewBlameEvidence(env Envelope, kind EvidenceKind, reason string, inputs []EvidenceField) (*BlameEvidence, error)
- func NewBlameEvidenceWithLimits(env Envelope, kind EvidenceKind, reason string, inputs []EvidenceField, ...) (*BlameEvidence, error)
- func UnmarshalBlameEvidenceWithLimits(in []byte, l EvidenceLimits) (*BlameEvidence, error)
- func (e *BlameEvidence) BeforeMarshalWire() error
- func (e *BlameEvidence) Field(key string) ([]byte, bool)
- func (e *BlameEvidence) Hash() ([]byte, error)
- func (e *BlameEvidence) MarshalBinary() ([]byte, error)
- func (e *BlameEvidence) MarshalBinaryWithLimits(l EvidenceLimits) ([]byte, error)
- func (e *BlameEvidence) UnmarshalBinary(in []byte) error
- func (e *BlameEvidence) UnmarshalBinaryWithLimits(in []byte, l EvidenceLimits) error
- func (e *BlameEvidence) Validate() error
- func (e *BlameEvidence) ValidateWithLimits(l EvidenceLimits) error
- func (BlameEvidence) WireType() string
- func (BlameEvidence) WireVersion() uint16
- type BroadcastAck
- func (a BroadcastAck) Clone() BroadcastAck
- func (a BroadcastAck) Equal(b BroadcastAck) bool
- func (a BroadcastAck) MarshalBinary() ([]byte, error)
- func (a *BroadcastAck) UnmarshalBinary(in []byte) error
- func (a BroadcastAck) Validate() error
- func (BroadcastAck) WireType() string
- func (BroadcastAck) WireVersion() uint16
- type BroadcastAckSigner
- type BroadcastAckVerifier
- type BroadcastCertificate
- func (c *BroadcastCertificate) BeforeMarshalWire() error
- func (c *BroadcastCertificate) Clone() *BroadcastCertificate
- func (a *BroadcastCertificate) Equal(b *BroadcastCertificate) bool
- func (c *BroadcastCertificate) MarshalBinary() ([]byte, error)
- func (c *BroadcastCertificate) UnmarshalBinary(in []byte) error
- func (c *BroadcastCertificate) Validate() error
- func (c *BroadcastCertificate) VerifyFull(env Envelope, parties PartySet, verifier BroadcastAckVerifier) error
- func (c *BroadcastCertificate) VerifyStructure(env Envelope, parties PartySet) error
- func (BroadcastCertificate) WireType() string
- func (BroadcastCertificate) WireVersion() uint16
- type BroadcastConsistency
- func (bc *BroadcastConsistency) AckCount() int
- func (bc *BroadcastConsistency) AddAck(env Envelope, ack BroadcastAck) error
- func (bc *BroadcastConsistency) Certificate() (*BroadcastCertificate, error)
- func (bc *BroadcastConsistency) Commit(env Envelope) (bool, error)
- func (bc *BroadcastConsistency) Complete() bool
- type BroadcastConsistencyPolicy
- type ChannelProtection
- type ConfidentialityPolicy
- type DeliveryMode
- type DeliveryPolicy
- type DerivationPath
- type DerivationRequest
- type DerivationResult
- func (r *DerivationResult) Clone() *DerivationResult
- func (r *DerivationResult) Destroy()
- func (r *DerivationResult) Equal(other *DerivationResult) bool
- func (r *DerivationResult) MarshalBinary() ([]byte, error)
- func (r *DerivationResult) UnmarshalBinary(in []byte) error
- func (r *DerivationResult) Validate() error
- func (r *DerivationResult) VerificationKeyBytes() []byte
- func (DerivationResult) WireType() string
- func (DerivationResult) WireVersion() uint16
- type DerivationScheme
- type DeriveConfig
- type DeriveOption
- type Envelope
- func NewEnvelope(input EnvelopeInput) (Envelope, error)
- func NewEnvelopeWithLimits(input EnvelopeInput, limits EnvelopeLimits) (Envelope, error)
- func SignEnvelope(e Envelope, signer EnvelopeSigner) (Envelope, error)
- func UnmarshalEnvelopeWithLimits(in []byte, limits EnvelopeLimits) (Envelope, error)
- func (e Envelope) Clone() Envelope
- func (e Envelope) Digest() EnvelopeDigest
- func (e Envelope) MarshalBinary() ([]byte, error)
- func (e Envelope) MarshalBinaryWithLimits(limits EnvelopeLimits) ([]byte, error)
- func (e Envelope) SigningDigest() [32]byte
- func (e *Envelope) UnmarshalBinary(in []byte) error
- func (e *Envelope) UnmarshalBinaryWithLimits(in []byte, limits EnvelopeLimits) error
- func (Envelope) WireType() string
- func (Envelope) WireVersion() uint16
- type EnvelopeDigest
- type EnvelopeGuard
- func NewEnvelopeGuard(self PartyID, parties PartySet, protocol ProtocolID, sessionID SessionID, ...) (*EnvelopeGuard, error)
- func NewTestEnvelopeGuard(self PartyID, parties PartySet, protocol ProtocolID, sessionID SessionID, ...) *EnvelopeGuard
- func NewTestEnvelopeGuardWithCache(self PartyID, parties PartySet, protocol ProtocolID, sessionID SessionID, ...) *EnvelopeGuard
- func (g *EnvelopeGuard) AckVerifier() BroadcastAckVerifier
- func (g *EnvelopeGuard) EnvelopeVerifier() EnvelopeSignatureVerifier
- func (g *EnvelopeGuard) Parties() PartySet
- func (g *EnvelopeGuard) Policies() PolicySet
- func (g *EnvelopeGuard) PolicyDigest() [32]byte
- func (g *EnvelopeGuard) Protocol() ProtocolID
- func (g *EnvelopeGuard) ReplayCache() ReplayCache
- func (g *EnvelopeGuard) RequiresSenderSignatures() bool
- func (g *EnvelopeGuard) Self() PartyID
- func (g *EnvelopeGuard) SessionID() SessionID
- func (g *EnvelopeGuard) Validate(env InboundEnvelope) error
- func (g *EnvelopeGuard) ValidateForRound(env InboundEnvelope, allowedSenders PartySet) error
- func (g *EnvelopeGuard) ValidateWithParties(env InboundEnvelope, parties PartySet) error
- func (g *EnvelopeGuard) ValidateWithoutReplay(env InboundEnvelope, parties PartySet) error
- type EnvelopeInput
- type EnvelopeLimits
- type EnvelopeSignatureVerifier
- type EnvelopeSigner
- type EvidenceField
- type EvidenceKind
- type EvidenceLimits
- type GuardConfig
- type IdentificationRecord
- func (r *IdentificationRecord) BeforeMarshalWire() error
- func (r IdentificationRecord) Clone() IdentificationRecord
- func (r IdentificationRecord) ComputeAlertDigest() [32]byte
- func (r *IdentificationRecord) MarshalBinary() ([]byte, error)
- func (r *IdentificationRecord) MarshalBinaryWithLimits(limits IdentificationRecordLimits) ([]byte, error)
- func (r *IdentificationRecord) UnmarshalBinary(in []byte) error
- func (r *IdentificationRecord) UnmarshalBinaryWithLimits(in []byte, limits IdentificationRecordLimits) error
- func (r *IdentificationRecord) Validate() error
- func (r *IdentificationRecord) ValidateWithLimits(limits IdentificationRecordLimits) error
- func (IdentificationRecord) WireType() string
- func (IdentificationRecord) WireVersion() uint16
- type IdentificationRecordLimits
- type InMemoryAckSigner
- type InMemoryAckVerifier
- type InMemoryReplayCache
- type InMemoryTransport
- func (t *InMemoryTransport) Broadcast(_ context.Context, env Envelope) error
- func (t *InMemoryTransport) ConnectOutbox(party PartyID, outbox chan<- InboundEnvelope)
- func (t *InMemoryTransport) Inbox() <-chan InboundEnvelope
- func (t *InMemoryTransport) Parties() PartySet
- func (t *InMemoryTransport) Receive(ctx context.Context) (InboundEnvelope, error)
- func (t *InMemoryTransport) Send(_ context.Context, env Envelope) error
- type InboundEnvelope
- func (in InboundEnvelope) BroadcastCertificate() *BroadcastCertificate
- func (in InboundEnvelope) Digest() EnvelopeDigest
- func (in InboundEnvelope) Envelope() Envelope
- func (in InboundEnvelope) From() PartyID
- func (in InboundEnvelope) Payload() []byte
- func (in InboundEnvelope) PayloadType() PayloadType
- func (in InboundEnvelope) Protocol() ProtocolID
- func (in InboundEnvelope) ReceiveInfo() ReceiveInfo
- func (in InboundEnvelope) Round() uint8
- func (in InboundEnvelope) SessionID() SessionID
- func (in InboundEnvelope) To() PartyID
- type InvalidChildMode
- type KeyShare
- type LocalConfig
- type Logger
- type MaliciousTransport
- type MessageSlotKey
- type OpenOption
- type PartyID
- type PartySet
- type PassphraseParams
- type PayloadType
- type PolicySet
- type ProtocolError
- type ProtocolID
- type ReceiveInfo
- type RefreshRunConfig
- type RefreshRunner
- type RefreshScheduler
- type RefreshSchedulerOptions
- type RefreshSession
- type ReplayCache
- type SLogger
- type SessionConfig
- type SessionID
- type SignIntent
- type SignRequest
- type SigningContext
- func (c SigningContext) Clone() SigningContext
- func (c SigningContext) DerivationPath() DerivationPath
- func (c SigningContext) MarshalBinary() ([]byte, error)
- func (c *SigningContext) UnmarshalBinary(in []byte) error
- func (c SigningContext) Validate() error
- func (SigningContext) WireType() string
- func (SigningContext) WireVersion() uint16
- type TLVLimits
- type ThresholdConfig
- type ThresholdLimits
- type Transport
Examples ¶
Constants ¶
const ( // ErrCodeInvalidConfig marks invalid local protocol configuration. ErrCodeInvalidConfig = "invalid_config" // ErrCodeInvalidMessage marks malformed or cross-session protocol messages. ErrCodeInvalidMessage = "invalid_message" // ErrCodeDuplicate marks replayed or repeated messages for a round. ErrCodeDuplicate = "duplicate_message" // ErrCodeRound marks a message delivered to the wrong protocol round. ErrCodeRound = "wrong_round" // ErrCodeVerification marks a failed cryptographic or transcript check. ErrCodeVerification = "verification_failed" // ErrCodeAggregateSignInvalid marks an aggregate signature that failed verification. // The blamed parties form a suspect set — individual partials cannot be verified // independently in the current protocol, so all signers are listed as candidate // sources. This is not a proof that any specific signer acted maliciously. ErrCodeAggregateSignInvalid = "aggregate_sign_invalid" // ErrCodeNotReady marks a protocol state that has not collected enough messages. ErrCodeNotReady = "not_ready" // ErrCodeConsumed marks one-use material that has already been consumed. ErrCodeConsumed = "consumed" // ErrCodeCompleted marks a protocol session that has already completed. ErrCodeCompleted = "completed" // ErrCodeAborted marks a protocol session that previously hit an attributable abort. ErrCodeAborted = "aborted" // ErrCodeNotImplemented marks intentionally unsupported protocol features. ErrCodeNotImplemented = "not_implemented" // ErrCodeLimitExceeded marks a value that exceeds a configured hard cap. ErrCodeLimitExceeded = "limit_exceeded" // ErrCodeTooManyParties marks a party set that exceeds the configured maximum. ErrCodeTooManyParties = "too_many_parties" // ErrCodeTooManySigners marks a signer set that exceeds the configured maximum. ErrCodeTooManySigners = "too_many_signers" // ErrCodePayloadTooLarge marks a payload that exceeds its byte cap. ErrCodePayloadTooLarge = "payload_too_large" // ErrCodeProofTooLarge marks a proof input that exceeds its byte cap. ErrCodeProofTooLarge = "proof_too_large" // ErrCodeInvariant marks an implementation-invariant failure. This is not a // protocol-level blame event — it indicates a bug in the library or corrupted // local state. No participants are blamed. ErrCodeInvariant = "invariant" )
const ( // DefaultMaxParties is the maximum number of participants across algorithms. DefaultMaxParties = 64 // DefaultMaxThreshold is the maximum threshold value across algorithms. DefaultMaxThreshold = 64 // DefaultMaxSigners is the maximum number of concurrent signers. DefaultMaxSigners = 64 )
const ( // DefaultMaxWireFields caps the field count inside a TLV message. DefaultMaxWireFields = 256 // DefaultMaxWireFieldBytes caps a single TLV field value. DefaultMaxWireFieldBytes = 1 << 20 )
const ( // DefaultMaxEnvelopeBytes is the maximum wire-encoded envelope size (1 MiB). DefaultMaxEnvelopeBytes = 1 << 20 // DefaultMaxEnvelopePayloadBytes is the maximum payload inside an envelope (1 MiB). DefaultMaxEnvelopePayloadBytes = 1 << 20 // DefaultMaxPayloadTypeBytes caps the payload type identifier length. DefaultMaxPayloadTypeBytes = 128 // DefaultMaxProtocolNameBytes caps the protocol name length inside envelopes. DefaultMaxProtocolNameBytes = 64 // DefaultMaxEnvelopeSignatureBytes caps a portable sender signature. DefaultMaxEnvelopeSignatureBytes = 4096 )
const ( // DefaultMaxBlameEvidenceBytes caps the total encoded blame evidence size (1 MiB). DefaultMaxBlameEvidenceBytes = 1 << 20 // DefaultMaxEvidenceReasonBytes caps the reason string length in blame evidence. DefaultMaxEvidenceReasonBytes = 256 // DefaultMaxEvidenceFieldCount caps the number of public input fields in blame evidence. DefaultMaxEvidenceFieldCount = 64 // DefaultMaxEvidenceFieldKeyBytes caps a single evidence field key length. DefaultMaxEvidenceFieldKeyBytes = 128 // DefaultMaxEvidenceFieldValueBytes caps a single evidence field value length. DefaultMaxEvidenceFieldValueBytes = 1 << 20 )
const ( DefaultMaxSerializedKeyShareBytes = 2 << 20 // DefaultMaxSerializedPresignBytes caps serialized Presign size (2 MiB). DefaultMaxSerializedPresignBytes = 2 << 20 DefaultMaxSerializedResharePlanBytes = 1 << 20 // DefaultMaxSerializedTrustedDealerPlanBytes caps serialized trusted-dealer import plans (1 MiB). DefaultMaxSerializedTrustedDealerPlanBytes = 1 << 20 // DefaultMaxSerializedTrustedDealerContributionBytes caps one serialized secret contribution (64 KiB). DefaultMaxSerializedTrustedDealerContributionBytes = 64 << 10 )
const ( // DefaultMaxPointBytes caps curve point encoding size. DefaultMaxPointBytes = 65 // DefaultMaxScalarBytes caps curve scalar encoding size. DefaultMaxScalarBytes = 32 )
const ( // DefaultMaxPaillierModulusBits caps the Paillier modulus size (8192 bits). DefaultMaxPaillierModulusBits = 8192 // DefaultMaxPaillierPublicKeyBytes caps marshaled Paillier public key size. DefaultMaxPaillierPublicKeyBytes = 2048 // DefaultMaxPaillierPrivateKeyBytes caps marshaled Paillier private key size. DefaultMaxPaillierPrivateKeyBytes = 4096 // DefaultMaxPaillierCiphertextBytes caps a Paillier ciphertext (N^2 encoding). DefaultMaxPaillierCiphertextBytes = 2048 // DefaultMaxPaillierProofBytes caps Paillier-related ZK proof size (256 KiB). DefaultMaxPaillierProofBytes = 256 << 10 // DefaultMaxRingPedersenParamsBytes caps Ring-Pedersen parameter marshaling. DefaultMaxRingPedersenParamsBytes = 16384 // DefaultMaxMTAResponseBytes caps an MtA response message size (512 KiB). DefaultMaxMTAResponseBytes = 512 << 10 // DefaultMaxZKProofBytes caps any ZK proof input (512 KiB). DefaultMaxZKProofBytes = 512 << 10 )
const HardenedKeyStart uint32 = 1 << 31
HardenedKeyStart is the first index reserved for hardened BIP32 derivation. Online signing APIs currently accept only indices below this value.
const ( // IdentificationRecordEvidenceKey is the fixed BlameEvidence.PublicInputs // key carrying a canonical IdentificationRecord. IdentificationRecordEvidenceKey = "identification_record" )
const MaxDerivationDepth = 255
MaxDerivationDepth is the maximum path depth representable by BIP32 extended keys and derivation results.
const ProtocolVersion uint16 = 1
ProtocolVersion is the semantic protocol version bound into transcripts and durable protocol records.
Variables ¶
var ( // ErrChainCodeRequired reports that a key share or derivation input lacks chain code. ErrChainCodeRequired = errors.New("chain code required") // ErrInvalidChainCodeLength reports that a chain code is not exactly 32 bytes. ErrInvalidChainCodeLength = errors.New("invalid chain code length") // ErrInvalidPublicKey reports that a derivation input public key is not valid for the scheme. ErrInvalidPublicKey = errors.New("invalid public key") // ErrHardenedDerivationUnsupported reports that an online signing path contains a hardened index. ErrHardenedDerivationUnsupported = errors.New("hardened derivation unsupported") // ErrInvalidChild reports that public derivation produced an invalid child. ErrInvalidChild = errors.New("invalid child derivation") // ErrDerivationDepthOverflow reports that a path exceeds the BIP32 255-level depth. ErrDerivationDepthOverflow = errors.New("derivation depth overflow") // ErrInvalidChildMode reports an undefined invalid-child handling mode. ErrInvalidChildMode = errors.New("invalid child mode") // ErrInvalidExtendedPublicKey is returned when an extended public key fails // validation (bad version, invalid point, etc.). ErrInvalidExtendedPublicKey = errors.New("invalid extended public key") )
var ErrBroadcastEquivocation = errors.New("broadcast equivocation detected")
ErrBroadcastEquivocation is returned when a sender sends different payloads to different parties.
var ErrDuplicateMessage = errors.New("duplicate message")
ErrDuplicateMessage is returned when an identical message (same slot, same payload hash) is delivered more than once.
var ErrEquivocation = errors.New("equivocation detected")
ErrEquivocation is returned when a party sends different payloads to different recipients for the same protocol message slot: the slot exists but with a different payload hash.
var ErrExpectedBroadcastMessage = errors.New("expected broadcast message")
ErrExpectedBroadcastMessage is returned when a direct envelope arrives for a broadcast-only payload type.
var ErrExpectedDirectMessage = errors.New("expected direct message")
ErrExpectedDirectMessage is returned when a broadcast envelope arrives for a direct-only payload type.
var ErrInvalidBroadcastCertificate = errors.New("invalid broadcast certificate")
ErrInvalidBroadcastCertificate is returned when a broadcast certificate fails validation.
var ErrInvalidChannelProtection = errors.New("invalid channel protection")
ErrInvalidChannelProtection is returned when the receive path reports an undefined non-zero channel-protection value.
var ErrInvalidEnvelopeSignature = errors.New("invalid envelope sender signature")
ErrInvalidEnvelopeSignature is returned when portable sender authentication fails.
var ErrInvalidSessionID = errors.New("invalid session id")
ErrInvalidSessionID is returned when a session is created with a zero or invalid session ID.
var ErrMissingAckVerifier = errors.New("missing broadcast ack verifier")
ErrMissingAckVerifier is returned when broadcast ACK verification is required but no verifier is configured.
var ErrMissingBroadcastCertificate = errors.New("missing broadcast certificate")
ErrMissingBroadcastCertificate is returned when a broadcast-consistency-required payload has no certificate.
var ErrMissingChannelProtection = errors.New("missing channel protection")
ErrMissingChannelProtection is returned when the receive path does not report whether an envelope arrived over plaintext or confidential transport.
var ErrMissingConfidentiality = errors.New("missing transport confidentiality")
ErrMissingConfidentiality is returned when a confidential-required payload arrives over plaintext.
var ErrMissingEnvelopeGuard = errors.New("missing envelope guard")
ErrMissingEnvelopeGuard is returned when an envelope arrives without a configured guard.
var ErrMissingEnvelopeSignature = errors.New("missing envelope sender signature")
ErrMissingEnvelopeSignature is returned when policy requires portable sender authentication.
var ErrMissingEnvelopeSignatureVerifier = errors.New("missing envelope signature verifier")
ErrMissingEnvelopeSignatureVerifier is returned when signature policy has no verifier.
var ErrMissingEnvelopeSigner = errors.New("missing envelope signer")
ErrMissingEnvelopeSigner indicates that a protocol requiring portable direct message signatures was started without a local transport-identity signer.
var ErrMissingReplayCache = errors.New("missing replay cache")
ErrMissingReplayCache is returned when a session constructor receives a nil ReplayCache.
var ErrPlanHashMismatch = errors.New("lifecycle plan hash mismatch")
ErrPlanHashMismatch is returned when protocol input is bound to a different lifecycle plan.
var ErrRefreshCommitOutcomeUnknown = errors.New("refresh key-share commit outcome unknown")
ErrRefreshCommitOutcomeUnknown marks a CommitKeyShare error whose durable outcome cannot be determined. When this error is wrapped, the callback keeps ownership of the refreshed key share for recovery and reconciliation.
var ErrRefreshSchedulerRunning = errors.New("refresh scheduler is already running")
ErrRefreshSchedulerRunning is returned when Run or RunOnce is called while another scheduler run is active.
var ErrReplayCacheFull = errors.New("replay cache full")
ErrReplayCacheFull is returned when a bounded replay cache cannot record a new message slot without forgetting previously accepted protocol traffic.
var ErrSelfSender = errors.New("envelope sender is local party")
ErrSelfSender is returned when a local guard receives an envelope claiming to have been sent by the same local party.
var ErrSenderIdentityMismatch = errors.New("sender identity mismatch")
ErrSenderIdentityMismatch is returned when the transport-authenticated party differs from Envelope.From.
var ErrStorageKeyIDMismatch = errors.New("storage key id mismatch")
ErrStorageKeyIDMismatch is returned when an authenticated storage record is valid but is bound to a different caller-assigned key ID.
var ErrUnauthenticatedTransport = errors.New("unauthenticated transport")
ErrUnauthenticatedTransport is returned when an envelope arrives over an unauthenticated transport.
var ErrUnexpectedConfidentiality = errors.New("unexpected transport confidentiality")
ErrUnexpectedConfidentiality is returned when a confidential-forbidden payload arrives over a confidential channel.
var ErrUnknownPayloadPolicy = errors.New("unknown payload delivery policy")
ErrUnknownPayloadPolicy is returned when no delivery policy matches the envelope's protocol/round/payloadType.
var ErrWrongRecipient = errors.New("wrong envelope recipient")
ErrWrongRecipient is returned when a direct message is addressed to the wrong party.
Functions ¶
func AckDigest ¶
func AckDigest(protocol ProtocolID, sessionID SessionID, round uint8, from PartyID, payloadType PayloadType, payloadHash [32]byte, envelopeDigest EnvelopeDigest) [32]byte
AckDigest computes the canonical digest that parties sign for a broadcast ack. It binds the ack to the complete broadcast message identity.
func CheckHandlerContext ¶
CheckHandlerContext checks both the per-delivery context and the session context. Protocol handlers call it at state-transition boundaries; it does not claim to interrupt one indivisible cryptographic operation.
func ContainsParty ¶
ContainsParty reports whether id appears in parties.
func DecodeBinary ¶
DecodeBinary decodes a binary-encoded value through its standard encoding.BinaryUnmarshaler implementation.
func DecodeBinaryValue ¶
DecodeBinaryValue decodes a binary-encoded value and returns it by value.
func DecodeBinaryValueWithLimits ¶
DecodeBinaryValueWithLimits decodes a limits-aware binary value and returns it by value.
func DecodeBinaryWithLimits ¶
DecodeBinaryWithLimits decodes a binary-encoded value through its limits-aware unmarshaler implementation.
func DecryptKeyShareWithPassphrase ¶
func DecryptKeyShareWithPassphrase(encoded, passphrase []byte, expectedKeyID string) ([]byte, error)
DecryptKeyShareWithPassphrase decrypts an encoding produced by EncryptKeyShareWithPassphrase and requires its authenticated key ID to match expectedKeyID.
func DecryptPresignWithPassphrase ¶
DecryptPresignWithPassphrase decrypts an encoding produced by EncryptPresignWithPassphrase and requires its authenticated key ID to match expectedKeyID.
func DecryptSignAttemptWithPassphrase ¶
func DecryptSignAttemptWithPassphrase(encoded, passphrase []byte, expectedKeyID string) ([]byte, error)
DecryptSignAttemptWithPassphrase decrypts an encoding produced by EncryptSignAttemptWithPassphrase and requires its authenticated key ID to match expectedKeyID.
func DecryptSignAttemptWithPassphraseAndKeyID ¶
DecryptSignAttemptWithPassphraseAndKeyID decrypts a sign-attempt encoding and returns its authenticated caller-assigned key ID. Callers that use keyID to bind object kind or storage identity must compare the returned value with the expected value after decoding the plaintext record.
func EncryptKeyShareWithPassphrase ¶
func EncryptKeyShareWithPassphrase(plaintext, passphrase []byte, keyID string, params *PassphraseParams) ([]byte, error)
EncryptKeyShareWithPassphrase encrypts a key-share with a passphrase using Argon2id key derivation and ChaCha20-Poly1305. keyID is an optional caller-assigned identifier that is authenticated as AAD (empty string is allowed).
This is a reference/demo implementation. Production deployments should use a KMS or HSM for key material protection.
func EncryptPresignWithPassphrase ¶
func EncryptPresignWithPassphrase(plaintext, passphrase []byte, keyID string, params *PassphraseParams) ([]byte, error)
EncryptPresignWithPassphrase encrypts a presign record with a passphrase using Argon2id key derivation and ChaCha20-Poly1305. keyID is an optional caller-assigned identifier that is authenticated as AAD (empty string is allowed).
This is a reference/demo implementation. Production deployments should use a KMS or HSM for key material protection.
func EncryptSignAttemptWithPassphrase ¶
func EncryptSignAttemptWithPassphrase(plaintext, passphrase []byte, keyID string, params *PassphraseParams) ([]byte, error)
EncryptSignAttemptWithPassphrase encrypts a sign-attempt record with a passphrase using Argon2id key derivation and ChaCha20-Poly1305. keyID is an optional caller-assigned identifier that is authenticated as AAD.
This is a reference/demo implementation. Production deployments should use a KMS or HSM for confidential signing-outbox records.
func EnvelopeSigningDigest ¶
EnvelopeSigningDigest computes the digest authenticated by SenderSignature. The signature field itself is deliberately excluded.
func IsAttributableError ¶
IsAttributableError reports whether err carries blame evidence and should cause the session to abort. Verification failures with blame are attributable; duplicate messages are not.
This matches the [shouldAbortSession] logic used by protocol handlers.
func IsSessionAborted ¶
IsSessionAborted reports whether err is a ProtocolError with code ErrCodeAborted, indicating the protocol session was aborted due to an attributable verification failure.
func IsSessionCompleted ¶
IsSessionCompleted reports whether err is a ProtocolError with code ErrCodeCompleted, indicating the protocol session has already finished.
func MarshalEnvelopeWithLimits ¶
func MarshalEnvelopeWithLimits(env Envelope, limits EnvelopeLimits) ([]byte, error)
MarshalEnvelopeWithLimits encodes the envelope using the object-level wire codec, enforcing the provided size limits.
func MarshalEvidenceWithLimits ¶
func MarshalEvidenceWithLimits(e *BlameEvidence, l EvidenceLimits) ([]byte, error)
MarshalEvidenceWithLimits encodes BlameEvidence using the object-level wire codec with explicit limits. Fields are sorted into canonical order so that logically equivalent evidence records produce identical hashes.
func PartySetHash ¶
PartySetHash returns a SHA-256 digest that binds a label and a sorted party set.
Parties are sorted with tss.SortParties before hashing so that the same set always produces the same 32-byte digest regardless of input order.
Different labels guarantee domain separation — the same party set hashed under "keygen" and "signing" labels will produce distinct digests.
func PayloadHashFromEnvelope ¶
PayloadHashFromEnvelope returns the SHA-256 hash of the envelope payload. It is used with ReplayCache.CheckAndStore as the content discriminator: two messages in the same slot with different payload hashes are equivocation.
func RequireEnvelopeGuard ¶
func RequireEnvelopeGuard(guard *EnvelopeGuard, expectedProtocol ProtocolID, expectedSession SessionID, self PartyID, expectedPolicies PolicySet) error
RequireEnvelopeGuard verifies that guard is bound to the expected protocol session and has the fixed validation dependencies required by inbound handlers. It does not validate the guard's party set; protocol handlers pass the per-message allowed sender set to ValidateInbound.
func ValidateEnvelopePolicy ¶
func ValidateEnvelopePolicy(env InboundEnvelope, self PartyID, policies PolicySet) error
ValidateEnvelopePolicy checks delivery mode and confidentiality against a PolicySet. It is a lightweight complement for the test fallback path (when no EnvelopeGuard is set and the transport is unauthenticated). It does NOT check broadcast consistency or replay — those require guard infrastructure.
func ValidateInbound ¶
func ValidateInbound(guard *EnvelopeGuard, env InboundEnvelope, expectedProtocol ProtocolID, expectedSession SessionID, allowedSenders PartySet, self PartyID) error
ValidateInbound validates an incoming envelope through the provided guard. The guard must be non-nil — a nil guard returns ErrMissingEnvelopeGuard. This ensures transport authentication, confidentiality enforcement, broadcast consistency, and replay detection are applied uniformly in all code paths.
The allowedSenders parameter specifies which participants are accepted as senders for this message. The guard's configured EnvelopeGuard.Parties field is the construction-time party universe; callers must supply the appropriate allowed sender set per round or per payload type. For sessions where the trusted party universe changes between rounds (e.g. reshare with old and new party subsets), this design avoids coupling guard construction to per-message validation.
func ValidateInboundWithoutReplay ¶
func ValidateInboundWithoutReplay(guard *EnvelopeGuard, env InboundEnvelope, expectedProtocol ProtocolID, expectedSession SessionID, allowedSenders PartySet, self PartyID) error
ValidateInboundWithoutReplay validates a retryable early message without mutating the guard's replay cache. Once the protocol becomes ready, callers must pass the message through ValidateInbound before processing it.
func ValidateSignerSet ¶
func ValidateSignerSet(keyParties PartySet, threshold int, signers PartySet, limits ThresholdLimits) error
ValidateSignerSet checks signers against a key's participant set and limits. It verifies: non-empty, minimum size (threshold), maximum size, membership, and no duplicates. For algorithms where AllowOversizedSignerSet is false, signer count must exactly equal threshold.
func VerifyBroadcastAck ¶
func VerifyBroadcastAck(env Envelope, ack BroadcastAck, verifier BroadcastAckVerifier) error
VerifyBroadcastAck checks that an ack is valid for the given envelope and party.
func VerifyBroadcastCertificateWithSignatures ¶
func VerifyBroadcastCertificateWithSignatures(env Envelope, parties PartySet, cert *BroadcastCertificate, verifier BroadcastAckVerifier) error
VerifyBroadcastCertificateWithSignatures performs full certificate validation including individual ack signature verification. Prefer BroadcastCertificate.VerifyFull for new code.
func VerifyEnvelopeSignature ¶
func VerifyEnvelopeSignature(e Envelope, verifier EnvelopeSignatureVerifier) error
VerifyEnvelopeSignature verifies the portable sender signature carried by e.
Types ¶
type Algorithm ¶
type Algorithm string
Algorithm names a threshold signature algorithm implemented by this module.
type AttackMode ¶
type AttackMode uint8
AttackMode specifies a type of transport-layer attack for testing.
const ( // AttackSenderSpoof opens an envelope with ReceiveInfo.Peer different from Envelope.From. AttackSenderSpoof AttackMode = iota // AttackPlaintextConfidential reports plaintext delivery for confidential-required messages. AttackPlaintextConfidential // AttackReplay sends the same envelope twice. AttackReplay // AttackWrongRecipient delivers a direct message to the wrong party. AttackWrongRecipient // AttackBroadcastEquivocation sends different payloads to different parties. AttackBroadcastEquivocation // AttackDropAck fails to include an ack in the broadcast certificate. AttackDropAck // AttackInvalidAckSignature includes an ack with an invalid signature. AttackInvalidAckSignature )
type BinaryUnmarshalerWithLimits ¶
BinaryUnmarshalerWithLimits is implemented by binary decoders that require caller-provided resource limits.
type Blame ¶
type Blame struct {
Reason string `json:"reason"`
Parties PartySet `json:"parties"`
Evidence []byte `json:"evidence,omitempty"`
}
Blame identifies parties and public evidence associated with a protocol failure.
type BlameEvidence ¶
type BlameEvidence struct {
Protocol ProtocolID `wire:"1"`
SessionID SessionID `wire:"2,len=32"`
Round uint8 `wire:"3"`
From PartyID `wire:"4"`
To PartyID `wire:"5"`
PayloadType PayloadType `wire:"6,max_bytes=payload_type"`
PayloadHash []byte `wire:"7,len=32"`
EnvelopeDigest []byte `wire:"8"`
Kind EvidenceKind `wire:"9"`
Reason string `wire:"10,max_bytes=evidence_reason"`
PublicInputs []EvidenceField `wire:"11,max_items=evidence_fields"`
}
BlameEvidence is intentionally public-only. Confidential protocol messages should be represented by hashes or other public inputs, not by plaintext.
Example (Lifecycle) ¶
ExampleBlameEvidence_lifecycle demonstrates the full blame evidence lifecycle: creation from a misbehaving envelope, binary encoding, decoding via UnmarshalBlameEvidence, and self-validation.
Blame evidence captures the evidence needed to attribute a protocol fault to a specific party. It is designed to be stored or transmitted for later dispute resolution.
package main
import (
"bytes"
"fmt"
"github.com/islishude/tss"
)
func main() {
sessionID, err := tss.NewSessionID(bytes.NewReader(bytes.Repeat([]byte{0x33}, 32)))
if err != nil {
panic(err)
}
// --- 1. Construct the envelope that triggered the fault ---
envelope := tss.Envelope{
Protocol: "example",
SessionID: sessionID,
Round: 1,
From: 1,
PayloadType: "example.payload",
Payload: []byte("bad partial"),
}
// --- 2. Create blame evidence binding the envelope to a fault ---
// EvidenceKind describes the protocol phase where the fault occurred.
// EvidenceFields carry structured key-value metadata (e.g., hashes,
// party sets) that verifiers can cross-check.
evidence, err := tss.NewBlameEvidence(
envelope,
tss.EvidenceKindSignPartial,
"invalid partial signature",
[]tss.EvidenceField{
{Key: "public_hash", Value: []byte{1, 2, 3}},
},
)
if err != nil {
panic(err)
}
// --- 3. Serialize blame evidence for storage or transmission ---
encoded, err := evidence.MarshalBinary()
if err != nil {
panic(err)
}
// --- 4. Deserialize using the typed unmarshaler ---
// UnmarshalBlameEvidence returns a *BlameEvidence (not a raw struct)
// so the Validate method is available on the decoded value.
decoded, err := tss.DecodeBinary[tss.BlameEvidence](encoded)
if err != nil {
panic(err)
}
// --- 5. Validate structural integrity ---
// Validate checks that Kind is a known evidence kind and that From is
// non-zero. Additional context-dependent checks (session ID, party
// membership) are performed by protocol-specific verifiers.
fmt.Println(decoded.Kind, decoded.From, decoded.Validate() == nil)
}
Output: sign_partial 1 true
func NewBlameEvidence ¶
func NewBlameEvidence(env Envelope, kind EvidenceKind, reason string, inputs []EvidenceField) (*BlameEvidence, error)
NewBlameEvidence builds a public evidence record bound to an envelope hash. PublicInputs are stored in canonical order so that logically equivalent evidence records produce identical hashes regardless of caller-provided slice ordering.
func NewBlameEvidenceWithLimits ¶
func NewBlameEvidenceWithLimits(env Envelope, kind EvidenceKind, reason string, inputs []EvidenceField, limits EvidenceLimits) (*BlameEvidence, error)
NewBlameEvidenceWithLimits builds public evidence using explicit resource limits. This is intended for protocol phases whose canonical public proof is deliberately larger than the conservative default; it does not widen any default decoder or encoder.
func UnmarshalBlameEvidenceWithLimits ¶
func UnmarshalBlameEvidenceWithLimits(in []byte, l EvidenceLimits) (*BlameEvidence, error)
UnmarshalBlameEvidenceWithLimits decodes and validates public blame evidence with explicit size limits.
func (*BlameEvidence) BeforeMarshalWire ¶
func (e *BlameEvidence) BeforeMarshalWire() error
BeforeMarshalWire canonicalizes the PublicInputs field ordering before encoding, so that logically equivalent evidence records produce identical wire representations regardless of caller-provided slice ordering.
func (*BlameEvidence) Field ¶
func (e *BlameEvidence) Field(key string) ([]byte, bool)
Field returns a copy of a named public input field.
func (*BlameEvidence) Hash ¶
func (e *BlameEvidence) Hash() ([]byte, error)
Hash returns the SHA-256 digest of the deterministic evidence encoding.
func (*BlameEvidence) MarshalBinary ¶
func (e *BlameEvidence) MarshalBinary() ([]byte, error)
MarshalBinary encodes BlameEvidence using the object-level wire codec with conservative default limits. Use MarshalEvidenceWithLimits for explicit control.
func (*BlameEvidence) MarshalBinaryWithLimits ¶
func (e *BlameEvidence) MarshalBinaryWithLimits(l EvidenceLimits) ([]byte, error)
MarshalBinaryWithLimits encodes BlameEvidence using the object-level wire codec with explicit limits.
func (*BlameEvidence) UnmarshalBinary ¶
func (e *BlameEvidence) UnmarshalBinary(in []byte) error
UnmarshalBinary decodes and validates public blame evidence using conservative default limits.
func (*BlameEvidence) UnmarshalBinaryWithLimits ¶
func (e *BlameEvidence) UnmarshalBinaryWithLimits(in []byte, l EvidenceLimits) error
UnmarshalBinaryWithLimits decodes and validates public blame evidence into the receiver with explicit size limits.
func (*BlameEvidence) Validate ¶
func (e *BlameEvidence) Validate() error
Validate checks structural invariants for a public blame evidence record using conservative default limits. Use BlameEvidence.ValidateWithLimits for explicit control.
func (*BlameEvidence) ValidateWithLimits ¶
func (e *BlameEvidence) ValidateWithLimits(l EvidenceLimits) error
ValidateWithLimits checks structural invariants for a public blame evidence record against the provided limits. Canonical ordering of PublicInputs is handled by BlameEvidence.BeforeMarshalWire, which is called automatically by wire.Marshal before encoding.
func (BlameEvidence) WireType ¶
func (BlameEvidence) WireType() string
WireType returns the canonical wire type identifier for BlameEvidence.
func (BlameEvidence) WireVersion ¶
func (BlameEvidence) WireVersion() uint16
WireVersion returns the wire format version for BlameEvidence.
type BroadcastAck ¶
type BroadcastAck struct {
Party PartyID `wire:"1,u32"`
PayloadHash [32]byte `wire:"2,bytes,len=32"`
EnvelopeDigest EnvelopeDigest `wire:"3,bytes,len=32"`
Signature []byte `wire:"4,bytes,max_bytes=broadcast_signature"`
}
BroadcastAck is one party's signed acknowledgment of a broadcast message.
func SignBroadcastAck ¶
func SignBroadcastAck(env Envelope, party PartyID, signer BroadcastAckSigner) (BroadcastAck, error)
SignBroadcastAck produces a signed BroadcastAck for a party over an envelope. The caller must provide a signer bound to the party's identity key.
func (BroadcastAck) Clone ¶
func (a BroadcastAck) Clone() BroadcastAck
Clone returns a deep copy of the broadcast ack.
func (BroadcastAck) Equal ¶
func (a BroadcastAck) Equal(b BroadcastAck) bool
Equal reports whether a and other are the same BroadcastAck.
func (BroadcastAck) MarshalBinary ¶
func (a BroadcastAck) MarshalBinary() ([]byte, error)
MarshalBinary encodes the broadcast acknowledgment using canonical TLV.
func (*BroadcastAck) UnmarshalBinary ¶
func (a *BroadcastAck) UnmarshalBinary(in []byte) error
UnmarshalBinary decodes a canonical broadcast acknowledgment.
func (BroadcastAck) Validate ¶
func (a BroadcastAck) Validate() error
Validate checks the broadcast acknowledgment's structural invariants.
func (BroadcastAck) WireType ¶
func (BroadcastAck) WireType() string
WireType returns the canonical wire type identifier for BroadcastAck.
func (BroadcastAck) WireVersion ¶
func (BroadcastAck) WireVersion() uint16
WireVersion returns the wire format version for BroadcastAck.
type BroadcastAckSigner ¶
type BroadcastAckSigner interface {
// SignAck returns a cryptographic signature over the canonical ack digest.
SignAck(digest [32]byte) (signature []byte, err error)
}
BroadcastAckSigner produces a signature over a broadcast ack digest. Implementations bind an identity key to a PartyID.
type BroadcastAckVerifier ¶
type BroadcastAckVerifier interface {
// VerifyAck returns nil when signature is a valid signature by party over digest.
VerifyAck(party PartyID, digest [32]byte, signature []byte) error
}
BroadcastAckVerifier checks that a broadcast ack signature is valid for a party.
type BroadcastCertificate ¶
type BroadcastCertificate struct {
Protocol ProtocolID `wire:"1,string,max_bytes=protocol_name"`
SessionID SessionID `wire:"2,bytes,len=32"`
Round uint8 `wire:"3,u8"`
From PartyID `wire:"4,u32"`
PayloadType PayloadType `wire:"5,string,max_bytes=payload_type"`
PayloadHash [32]byte `wire:"6,bytes,len=32"`
EnvelopeDigest EnvelopeDigest `wire:"7,bytes,len=32"`
Recipients PartySet `wire:"8,u32list,max_items=broadcast_recipients"`
Acks []BroadcastAck `wire:"9,recordlist,max_items=broadcast_recipients"`
}
BroadcastCertificate proves that all parties received the same broadcast payload.
func NewBroadcastCertificate ¶
func NewBroadcastCertificate(env Envelope, recipients PartySet, acks []BroadcastAck) (*BroadcastCertificate, error)
NewBroadcastCertificate constructs a certificate from an envelope and a complete set of signed acks. It verifies that every ack covers the same digest and that every party in recipients contributed exactly one ack.
Callers must have already verified each individual ack signature via BroadcastAckVerifier before calling this constructor.
func (*BroadcastCertificate) BeforeMarshalWire ¶
func (c *BroadcastCertificate) BeforeMarshalWire() error
BeforeMarshalWire canonicalizes recipient and acknowledgment ordering.
func (*BroadcastCertificate) Clone ¶
func (c *BroadcastCertificate) Clone() *BroadcastCertificate
Clone returns a deep copy of the broadcast certificate.
func (*BroadcastCertificate) Equal ¶
func (a *BroadcastCertificate) Equal(b *BroadcastCertificate) bool
Equal reports whether r and other are the same BroadcastCertificate. Both nil receivers compare equal. A nil receiver and a non-nil other are not equal.
func (*BroadcastCertificate) MarshalBinary ¶
func (c *BroadcastCertificate) MarshalBinary() ([]byte, error)
MarshalBinary encodes the broadcast certificate using canonical TLV.
func (*BroadcastCertificate) UnmarshalBinary ¶
func (c *BroadcastCertificate) UnmarshalBinary(in []byte) error
UnmarshalBinary decodes a canonical broadcast certificate.
func (*BroadcastCertificate) Validate ¶
func (c *BroadcastCertificate) Validate() error
Validate checks the broadcast certificate's canonical structural invariants.
func (*BroadcastCertificate) VerifyFull ¶
func (c *BroadcastCertificate) VerifyFull(env Envelope, parties PartySet, verifier BroadcastAckVerifier) error
VerifyFull performs complete certificate validation: structure checks plus individual ack signature verification against the provided verifier. Production code must use this method; [VerifyStructure] is for tests and low-level parsing only.
func (*BroadcastCertificate) VerifyStructure ¶
func (c *BroadcastCertificate) VerifyStructure(env Envelope, parties PartySet) error
VerifyStructure checks that the certificate binds to env and that every party acknowledged the same digest. It does NOT verify individual ack signatures — use [VerifyFull] for production paths that require signature verification.
func (BroadcastCertificate) WireType ¶
func (BroadcastCertificate) WireType() string
WireType returns the canonical wire type identifier for BroadcastCertificate.
func (BroadcastCertificate) WireVersion ¶
func (BroadcastCertificate) WireVersion() uint16
WireVersion returns the wire format version for BroadcastCertificate.
type BroadcastConsistency ¶
type BroadcastConsistency struct {
// contains filtered or unexported fields
}
BroadcastConsistency tracks the collection of broadcast acks for one (session, round, from, payloadType) and detects equivocation.
It is safe for concurrent use.
func NewBroadcastConsistency ¶
func NewBroadcastConsistency(protocol ProtocolID, sessionID SessionID, round uint8, from PartyID, payloadType PayloadType, recipients PartySet, verifier BroadcastAckVerifier) (*BroadcastConsistency, error)
NewBroadcastConsistency starts tracking a new broadcast consistency session. The verifier is used to check each ack signature as it arrives. It must not be nil — a nil verifier causes a panic in AddAck.
func (*BroadcastConsistency) AckCount ¶
func (bc *BroadcastConsistency) AckCount() int
AckCount returns the number of verified acks collected so far.
func (*BroadcastConsistency) AddAck ¶
func (bc *BroadcastConsistency) AddAck(env Envelope, ack BroadcastAck) error
AddAck records a party's broadcast acknowledgment. It verifies the ack signature, checks for digest consistency, and returns an error on:
- signature verification failure
- digest mismatch (equivocation)
- duplicate ack
- unknown party
func (*BroadcastConsistency) Certificate ¶
func (bc *BroadcastConsistency) Certificate() (*BroadcastCertificate, error)
Certificate builds the BroadcastCertificate from collected acks. It returns an error if not all acks have been collected.
func (*BroadcastConsistency) Commit ¶
func (bc *BroadcastConsistency) Commit(env Envelope) (bool, error)
Commit records the canonical broadcast digest for this consistency session. Any subsequent ack with a different digest is treated as equivocation.
The first call to Commit returns (true, nil). Subsequent calls with the same digest return (false, nil). A call with a different digest returns (false, ErrBroadcastEquivocation).
func (*BroadcastConsistency) Complete ¶
func (bc *BroadcastConsistency) Complete() bool
Complete returns true when every recipient has submitted a valid ack.
type BroadcastConsistencyPolicy ¶
type BroadcastConsistencyPolicy uint8
BroadcastConsistencyPolicy specifies whether broadcast messages require a consistency certificate.
const ( // BroadcastConsistencyNone means no broadcast certificate is required. BroadcastConsistencyNone BroadcastConsistencyPolicy = iota // BroadcastConsistencyRequired means a valid BroadcastCertificate must be present. BroadcastConsistencyRequired )
type ChannelProtection ¶
type ChannelProtection uint8
ChannelProtection describes the channel protection actually observed by the receive transport. The zero value is invalid and fails closed.
const ( // ChannelProtectionUnknown means the receive path did not report channel protection. ChannelProtectionUnknown ChannelProtection = iota // ChannelPlaintext means the receive path explicitly observed plaintext delivery. ChannelPlaintext // ChannelConfidential means the receive path explicitly observed confidential delivery. ChannelConfidential )
type ConfidentialityPolicy ¶
type ConfidentialityPolicy uint8
ConfidentialityPolicy specifies whether a message must be encrypted in transit.
const ( // ConfidentialityForbidden means the message must NOT be sent over a confidential channel. // Prefer ConfidentialityOptional for most non-secret payloads; use Forbidden only when // confidential transport would actively break the protocol (e.g. audit logging that // requires visibility into plaintext). ConfidentialityForbidden ConfidentialityPolicy = iota // ConfidentialityOptional means either plaintext or confidential transport is acceptable. // This is the safe default for payloads that contain no secret material (commitments, // public keys, ciphertexts). TLS/mTLS deployments can safely mark transport as // Confidential=true without triggering policy rejection. ConfidentialityOptional // ConfidentialityRequired means the message MUST be sent over a confidential channel. // Use for payloads that contain secret shares, nonces, or other material that must // never appear in plaintext. ConfidentialityRequired )
type DeliveryMode ¶
type DeliveryMode uint8
DeliveryMode classifies an envelope delivery path.
const ( // DeliveryDirect is a point-to-point message addressed to a single recipient. DeliveryDirect DeliveryMode = iota // DeliveryBroadcast is a message sent to all parties. DeliveryBroadcast )
type DeliveryPolicy ¶
type DeliveryPolicy struct {
Protocol ProtocolID
Round uint8
PayloadType PayloadType
Mode DeliveryMode
Confidentiality ConfidentialityPolicy
BroadcastConsistency BroadcastConsistencyPolicy
// RequireSenderSignature requires portable sender authentication in
// addition to transport authentication.
RequireSenderSignature bool
}
DeliveryPolicy defines the transport requirements for one protocol message kind.
type DerivationPath ¶
type DerivationPath []uint32
DerivationPath is a non-hardened HD derivation path. Nil and empty paths are the master path "m".
func MustParseDerivationPath ¶
func MustParseDerivationPath(s string) DerivationPath
MustParseDerivationPath parses s and panics on error.
func NewDerivationPath ¶
func NewDerivationPath(pathes ...uint32) DerivationPath
NewDerivationPath returns a DerivationPath containing bip32 pathes in the given order.
func ParseDerivationPath ¶
func ParseDerivationPath(s string) (DerivationPath, error)
ParseDerivationPath parses paths in the form "m" or "m/0/1/2".
func (DerivationPath) Clone ¶
func (p DerivationPath) Clone() DerivationPath
Clone returns a caller-owned copy of the path.
func (DerivationPath) IsMaster ¶
func (p DerivationPath) IsMaster() bool
IsMaster reports whether the path is the master path.
func (DerivationPath) String ¶
func (p DerivationPath) String() string
String returns the canonical path string, using "m" for the master path.
func (DerivationPath) ValidateNonHardened ¶
func (p DerivationPath) ValidateNonHardened() error
ValidateNonHardened rejects paths deeper than BIP32 permits and hardened indices.
type DerivationRequest ¶
type DerivationRequest struct {
Scheme DerivationScheme `json:"scheme" wire:"1,string"`
Path DerivationPath `json:"path" wire:"2,u32list"`
InvalidChildMode InvalidChildMode `json:"invalid_child_mode" wire:"3,u8"`
ResolvedPath DerivationPath `json:"resolved_path,omitempty" wire:"4,u32list"`
}
DerivationRequest describes a requested public child-key derivation.
func (DerivationRequest) Clone ¶
func (r DerivationRequest) Clone() DerivationRequest
Clone returns a caller-owned copy of the request.
type DerivationResult ¶
type DerivationResult struct {
Scheme DerivationScheme `json:"scheme" wire:"1,string"`
ChildPublicKey []byte `json:"child_public_key" wire:"2,bytes"`
ChildChainCode []byte `json:"child_chain_code" wire:"3,bytes,len=32"`
RequestedPath DerivationPath `json:"requested_path" wire:"4,u32list"`
ResolvedPath DerivationPath `json:"resolved_path" wire:"5,u32list"`
Depth uint8 `json:"depth" wire:"6,u8"`
ParentFingerprint [4]byte `json:"parent_fingerprint" wire:"7,bytes,len=4"`
ChildNumber uint32 `json:"child_number" wire:"8,u32"`
AdditiveShift []byte `json:"additive_shift,omitempty" wire:"9,bytes"`
}
DerivationResult is the result of resolving a public child-key derivation.
func (*DerivationResult) Clone ¶
func (r *DerivationResult) Clone() *DerivationResult
Clone returns a caller-owned copy of the derivation result.
func (*DerivationResult) Destroy ¶
func (r *DerivationResult) Destroy()
Destroy clears derivation result buffers and resets metadata in place.
func (*DerivationResult) Equal ¶
func (r *DerivationResult) Equal(other *DerivationResult) bool
Equal reports whether r and other are the same derivation result. Both nil receivers compare equal. A nil receiver and a non-nil other are not equal.
func (*DerivationResult) MarshalBinary ¶
func (r *DerivationResult) MarshalBinary() ([]byte, error)
MarshalBinary encodes the derivation result using the object-level wire codec.
func (*DerivationResult) UnmarshalBinary ¶
func (r *DerivationResult) UnmarshalBinary(in []byte) error
UnmarshalBinary decodes a canonical derivation result record.
func (*DerivationResult) Validate ¶
func (r *DerivationResult) Validate() error
Validate checks structural invariants for a derivation result.
func (*DerivationResult) VerificationKeyBytes ¶
func (r *DerivationResult) VerificationKeyBytes() []byte
VerificationKeyBytes returns a copy of ChildPublicKey.
func (DerivationResult) WireType ¶
func (DerivationResult) WireType() string
WireType returns the canonical wire type identifier for DerivationResult.
func (DerivationResult) WireVersion ¶
func (DerivationResult) WireVersion() uint16
WireVersion returns the wire format version for DerivationResult.
type DerivationScheme ¶
type DerivationScheme string
DerivationScheme identifies the public child-key derivation algorithm.
const ( // DerivationSchemeBIP32Secp256k1 is standard non-hardened BIP32 CKDpub over secp256k1. DerivationSchemeBIP32Secp256k1 DerivationScheme = "bip32-secp256k1" // DerivationSchemeEd25519KhovratovichLaw is the Cardano/Khovratovich-Law Ed25519-BIP32 public derivation scheme. DerivationSchemeEd25519KhovratovichLaw DerivationScheme = "ed25519-bip32-khovratovich-law" )
type DeriveConfig ¶
type DeriveConfig struct {
InvalidChildMode InvalidChildMode
// HMACFunc is an optional custom HMAC-SHA512 function. When nil (the default),
// the normal crypto/hmac-based SHA512 implementation is used.
// The function must return exactly 64 bytes.
HMACFunc func(key, data []byte) []byte
}
DeriveConfig is the resolved configuration for HD public derivation.
func ResolveDeriveConfig ¶
func ResolveDeriveConfig(opts []DeriveOption) DeriveConfig
ResolveDeriveConfig resolves derivation options into a concrete config.
type DeriveOption ¶
type DeriveOption interface {
// contains filtered or unexported methods
}
DeriveOption is a functional option for HD public derivation.
func WithHMACFunc ¶
func WithHMACFunc(fn func(key, data []byte) []byte) DeriveOption
WithHMACFunc sets a custom HMAC-SHA512 function for BIP32 public derivation. When fn is nil or the option is not passed, the default crypto/hmac-based SHA512 implementation is used.
func WithInvalidChildMode ¶
func WithInvalidChildMode(mode InvalidChildMode) DeriveOption
WithInvalidChildMode sets the invalid child handling strategy.
type Envelope ¶
type Envelope struct {
Protocol ProtocolID `wire:"1,string"`
SessionID SessionID `wire:"2,bytes,len=32"`
Round uint8 `wire:"3,u8"`
From PartyID `wire:"4,u32"`
To PartyID `wire:"5,u32"` // zero means broadcast
PayloadType PayloadType `wire:"6,string"`
Payload []byte `wire:"7,bytes"`
// SenderSignature authenticates EnvelopeSigningDigest. The optional field
// remains absent for protocols whose policy does not require it.
SenderSignature []byte `wire:"8,bytes"`
}
Envelope is a transport-neutral protocol wire message.
Example (Roundtrip) ¶
ExampleEnvelope_roundtrip demonstrates the full lifecycle of an Envelope: construction via NewEnvelope, binary encoding, decoding, and validation. Envelopes carry protocol messages between parties; each envelope identifies the protocol, session, round, sender, and recipient for routing and duplicate detection.
package main
import (
"fmt"
"github.com/islishude/tss"
)
func main() {
// --- 1. Create a session ID that binds all messages in this run ---
sessionID, err := tss.NewSessionID(nil)
if err != nil {
panic(err)
}
// --- 2. Construct an envelope with the NewEnvelope constructor ---
// NewEnvelope validates fields, copies the payload, and returns a
// ready-to-send envelope. Always prefer NewEnvelope over
// constructing the struct directly.
envelope, err := tss.NewEnvelope(tss.EnvelopeInput{
Protocol: "example",
SessionID: sessionID,
Round: 1,
From: 1,
PayloadType: "example.payload",
Payload: []byte("roundtrip test"),
})
if err != nil {
panic(err)
}
// --- 3. Serialize the envelope for transport ---
encoded, err := envelope.MarshalBinary()
if err != nil {
panic(err)
}
// --- 4. Deserialize on the receiving side ---
var decoded tss.Envelope
if err := decoded.UnmarshalBinary(encoded); err != nil {
panic(err)
}
fmt.Println(string(decoded.Payload))
}
Output: roundtrip test
func NewEnvelope ¶
func NewEnvelope(input EnvelopeInput) (Envelope, error)
NewEnvelope constructs an envelope from caller-provided fields using conservative default limits. Use NewEnvelopeWithLimits for explicit control.
func NewEnvelopeWithLimits ¶
func NewEnvelopeWithLimits(input EnvelopeInput, limits EnvelopeLimits) (Envelope, error)
NewEnvelopeWithLimits constructs an envelope from caller-provided fields, enforcing the provided size limits. It validates basic fields and copies the payload.
func SignEnvelope ¶
func SignEnvelope(e Envelope, signer EnvelopeSigner) (Envelope, error)
SignEnvelope returns an independently owned envelope carrying a portable sender signature.
func UnmarshalEnvelopeWithLimits ¶
func UnmarshalEnvelopeWithLimits(in []byte, limits EnvelopeLimits) (Envelope, error)
UnmarshalEnvelopeWithLimits decodes a canonical TLV envelope enforcing the provided size limits. It returns a decoded envelope or an error.
func (Envelope) Digest ¶
func (e Envelope) Digest() EnvelopeDigest
Digest computes the domain-separated digest of the envelope metadata and payload. This digest is used for envelope equality checks and not for signing. For the digest that the sender signs, use SigningDigest.
func (Envelope) MarshalBinary ¶
MarshalBinary encodes the envelope using the object-level wire codec with conservative default limits. Use MarshalEnvelopeWithLimits for explicit control.
func (Envelope) MarshalBinaryWithLimits ¶
func (e Envelope) MarshalBinaryWithLimits(limits EnvelopeLimits) ([]byte, error)
MarshalBinaryWithLimits encodes the envelope using the object-level wire codec, enforcing the provided size limits.
func (Envelope) SigningDigest ¶
SigningDigest computes the domain-separated digest of the envelope metadata and payload, excluding the sender signature. This is the digest that the sender signs to produce SenderSignature.
func (*Envelope) UnmarshalBinary ¶
UnmarshalBinary decodes a canonical TLV envelope using the object-level wire codec with conservative default limits. Use UnmarshalEnvelopeWithLimits for explicit control.
func (*Envelope) UnmarshalBinaryWithLimits ¶
func (e *Envelope) UnmarshalBinaryWithLimits(in []byte, limits EnvelopeLimits) error
UnmarshalBinaryWithLimits decodes a canonical TLV envelope into the receiver, enforcing the provided size limits.
func (Envelope) WireVersion ¶
WireVersion returns the wire format version for Envelope.
type EnvelopeDigest ¶
type EnvelopeDigest [32]byte
EnvelopeDigest is the domain-separated digest of one envelope.
type EnvelopeGuard ¶
type EnvelopeGuard struct {
// contains filtered or unexported fields
}
EnvelopeGuard validates incoming envelopes against protocol, transport, and session policies. Every protocol handler must run Validate before processing the envelope.
func NewEnvelopeGuard ¶
func NewEnvelopeGuard(self PartyID, parties PartySet, protocol ProtocolID, sessionID SessionID, policies PolicySet, cache ReplayCache) (*EnvelopeGuard, error)
NewEnvelopeGuard constructs a guard with the required security configuration. It returns an error if parties is empty, Self is not in Parties, or if the SessionID is invalid.
func NewTestEnvelopeGuard ¶
func NewTestEnvelopeGuard(self PartyID, parties PartySet, protocol ProtocolID, sessionID SessionID, policies PolicySet) *EnvelopeGuard
NewTestEnvelopeGuard constructs a guard suitable for tests. It uses an in-memory replay cache and a no-op ack verifier. This function MUST NOT be used in production code — production callers must use GuardConfig.BuildGuard with a real verifier.
It panics when not running under "go test" to prevent accidental production use.
func NewTestEnvelopeGuardWithCache ¶
func NewTestEnvelopeGuardWithCache(self PartyID, parties PartySet, protocol ProtocolID, sessionID SessionID, policies PolicySet, cache ReplayCache) *EnvelopeGuard
NewTestEnvelopeGuardWithCache is NewTestEnvelopeGuard with an explicit replay cache for bounded-cache and failure-injection tests.
func (*EnvelopeGuard) AckVerifier ¶
func (g *EnvelopeGuard) AckVerifier() BroadcastAckVerifier
AckVerifier returns the guard's broadcast acknowledgement verifier.
func (*EnvelopeGuard) EnvelopeVerifier ¶
func (g *EnvelopeGuard) EnvelopeVerifier() EnvelopeSignatureVerifier
EnvelopeVerifier returns the guard's portable sender-signature verifier.
func (*EnvelopeGuard) Parties ¶
func (g *EnvelopeGuard) Parties() PartySet
Parties returns a caller-owned copy of the guard's construction-time party universe.
func (*EnvelopeGuard) Policies ¶
func (g *EnvelopeGuard) Policies() PolicySet
Policies returns the guard's immutable policy set.
func (*EnvelopeGuard) PolicyDigest ¶
func (g *EnvelopeGuard) PolicyDigest() [32]byte
PolicyDigest returns the canonical delivery-policy digest bound at construction.
func (*EnvelopeGuard) Protocol ¶
func (g *EnvelopeGuard) Protocol() ProtocolID
Protocol returns the protocol bound to the guard.
func (*EnvelopeGuard) ReplayCache ¶
func (g *EnvelopeGuard) ReplayCache() ReplayCache
ReplayCache returns the guard's replay cache authority.
func (*EnvelopeGuard) RequiresSenderSignatures ¶
func (g *EnvelopeGuard) RequiresSenderSignatures() bool
RequiresSenderSignatures reports whether any delivery policy configured on the guard requires canonical sender signatures.
func (*EnvelopeGuard) Self ¶
func (g *EnvelopeGuard) Self() PartyID
Self returns the local party bound to the guard.
func (*EnvelopeGuard) SessionID ¶
func (g *EnvelopeGuard) SessionID() SessionID
SessionID returns the session identifier bound to the guard.
func (*EnvelopeGuard) Validate ¶
func (g *EnvelopeGuard) Validate(env InboundEnvelope) error
Validate executes the full security validation sequence on an incoming envelope against the guard's configured party set. It returns nil only when the envelope passes all checks.
func (*EnvelopeGuard) ValidateForRound ¶
func (g *EnvelopeGuard) ValidateForRound(env InboundEnvelope, allowedSenders PartySet) error
ValidateForRound validates an incoming envelope against the sender set allowed by the current protocol round or payload. The guard's configured Parties field remains the construction-time party universe; allowedSenders is the lifecycle-specific sender set for this message.
func (*EnvelopeGuard) ValidateWithParties ¶
func (g *EnvelopeGuard) ValidateWithParties(env InboundEnvelope, parties PartySet) error
ValidateWithParties is like Validate but validates sender membership and broadcast certificates against the provided party set instead of the guard's configured set. This is used by sessions (e.g. reshare) that accept messages from different participant subsets depending on payload type.
func (*EnvelopeGuard) ValidateWithoutReplay ¶
func (g *EnvelopeGuard) ValidateWithoutReplay(env InboundEnvelope, parties PartySet) error
ValidateWithoutReplay performs all transport, identity, delivery-policy, confidentiality, signature, and broadcast-certificate checks without reserving a replay slot. It is intended only for protocol messages that are explicitly rejected as too early and may be retried after readiness changes.
type EnvelopeInput ¶
type EnvelopeInput struct {
Protocol ProtocolID
SessionID SessionID
Round uint8
From PartyID
To PartyID
PayloadType PayloadType
Payload []byte
// SenderSignature is optional at generic construction time. Delivery
// policies decide whether portable sender authentication is required.
SenderSignature []byte
}
EnvelopeInput carries the caller-provided fields for constructing an Envelope.
type EnvelopeLimits ¶
type EnvelopeLimits struct {
MaxBytes int
MaxPayloadBytes int
MaxPayloadTypeBytes int
MaxProtocolNameBytes int
MaxSignatureBytes int
TLV TLVLimits
}
EnvelopeLimits caps envelope encoding and metadata sizes.
func DefaultEnvelopeLimits ¶
func DefaultEnvelopeLimits() EnvelopeLimits
DefaultEnvelopeLimits returns a caller-owned copy of the conservative production envelope limits used by NewEnvelope, MarshalBinary, and UnmarshalBinary.
type EnvelopeSignatureVerifier ¶
type EnvelopeSignatureVerifier interface {
VerifyEnvelopeSignature(party PartyID, digest [32]byte, signature []byte) error
}
EnvelopeSignatureVerifier verifies a canonical envelope signature for party.
type EnvelopeSigner ¶
EnvelopeSigner signs a canonical envelope digest with the local party's transport identity key.
type EvidenceField ¶
type EvidenceField struct {
Key string `wire:"1,max_bytes=evidence_field_key"`
Value []byte `wire:"2,max_bytes=evidence_field_value"`
}
EvidenceField carries one public input or public-input hash for blame evidence.
func IdentificationEvidenceField ¶
func IdentificationEvidenceField(record *IdentificationRecord) (EvidenceField, error)
IdentificationEvidenceField encodes record under the fixed evidence key.
func IdentificationEvidenceFieldWithLimits ¶
func IdentificationEvidenceFieldWithLimits(record *IdentificationRecord, limits IdentificationRecordLimits) (EvidenceField, error)
IdentificationEvidenceFieldWithLimits encodes a record under the fixed evidence key using explicit resource limits.
func (EvidenceField) Clone ¶
func (f EvidenceField) Clone() EvidenceField
Clone returns a deep copy of an evidence field.
type EvidenceKind ¶
type EvidenceKind string
EvidenceKind names the protocol failure class captured in blame evidence.
const ( // EvidenceKindKeygenCommitment marks an invalid keygen public commitment. EvidenceKindKeygenCommitment EvidenceKind = "keygen_commitment" // EvidenceKindPaillierAux marks invalid Paillier, Ring-Pedersen, or // receiver-specific factor-proof auxiliary material in any lifecycle. EvidenceKindPaillierAux EvidenceKind = "paillier_aux" EvidenceKindKeygenShare EvidenceKind = "keygen_share" EvidenceKindRefreshShare EvidenceKind = "refresh_share" // EvidenceKindRefreshCommitment marks invalid proactive-refresh polynomial commitments. EvidenceKindRefreshCommitment EvidenceKind = "refresh_commitment" EvidenceKindReshareShare EvidenceKind = "reshare_share" EvidenceKindReshareCommitment EvidenceKind = "reshare_commitment" // EvidenceKindPresignRound1 marks invalid presign nonce commitment material. EvidenceKindPresignRound1 EvidenceKind = "presign_round1" // EvidenceKindPresignRound2 marks invalid pairwise MtA response material. EvidenceKindPresignRound2 EvidenceKind = "presign_round2" // EvidenceKindPresignRound3 marks invalid presign delta broadcast material. EvidenceKindPresignRound3 EvidenceKind = "presign_round3" // EvidenceKindPresignRedAlert marks an invalid Figure 9 presign red-alert proof. EvidenceKindPresignRedAlert EvidenceKind = "presign_red_alert" // EvidenceKindSignPartial marks invalid online signing partial material. EvidenceKindSignPartial EvidenceKind = "sign_partial" // EvidenceKindAggregateSign marks a final aggregate signature verification failure. EvidenceKindAggregateSign EvidenceKind = "aggregate_signature" EvidenceKindFrostKeygenShare EvidenceKind = "frost_keygen_share" // EvidenceKindFrostKeygenCommitment marks invalid public FROST DKG commitment or proof material. EvidenceKindFrostKeygenCommitment EvidenceKind = "frost_keygen_commitment" EvidenceKindFrostReshareShare EvidenceKind = "frost_reshare_share" // EvidenceKindFrostNonceCommitment marks an invalid FROST signing nonce commitment. EvidenceKindFrostNonceCommitment EvidenceKind = "frost_nonce_commitment" // EvidenceKindFrostPartialSignature marks an invalid FROST partial signature. EvidenceKindFrostPartialSignature EvidenceKind = "frost_partial_signature" // EvidenceKindFrostAggregateSignature marks a failed FROST aggregate Ed25519 signature. EvidenceKindFrostAggregateSignature EvidenceKind = "frost_aggregate_signature" )
type EvidenceLimits ¶
type EvidenceLimits struct {
MaxBytes int
MaxReasonBytes int
MaxFieldCount int
MaxFieldKeyBytes int
MaxFieldValueBytes int
MaxPayloadTypeBytes int
TLV TLVLimits
}
EvidenceLimits caps blame evidence encoding and field sizes.
func DefaultEvidenceLimits ¶
func DefaultEvidenceLimits() EvidenceLimits
DefaultEvidenceLimits returns a caller-owned copy of the conservative production limits used by NewBlameEvidence and BlameEvidence.MarshalBinary.
type GuardConfig ¶
type GuardConfig struct {
Self PartyID
Parties PartySet
Protocol ProtocolID
SessionID SessionID
Policies PolicySet
Cache ReplayCache
// AckVerifier, when non-nil, enables broadcast ack signature verification
// during guard validation. Production deployments SHOULD set this.
AckVerifier BroadcastAckVerifier
// EnvelopeVerifier verifies portable sender signatures required by policy.
EnvelopeVerifier EnvelopeSignatureVerifier
}
GuardConfig carries the guard configuration for protocol sessions that process inbound envelopes. It is required for production sessions.
func TestGuardConfig ¶
func TestGuardConfig(self PartyID, parties PartySet, protocol ProtocolID, sessionID SessionID, policies PolicySet) GuardConfig
TestGuardConfig returns a GuardConfig suitable for tests using an in-memory replay cache. The caller must provide the protocol-specific PolicySet.
func (GuardConfig) BuildGuard ¶
func (c GuardConfig) BuildGuard() (*EnvelopeGuard, error)
BuildGuard constructs an EnvelopeGuard from the configuration or returns an error. Production deployments must provide a non-nil AckVerifier; test code should use NewTestEnvelopeGuard instead.
type IdentificationRecord ¶
type IdentificationRecord struct {
FailureClass string `wire:"1,string,max_bytes=identification_class"`
AlertDigest []byte `wire:"2,bytes,len=32"`
Accused PartyID `wire:"3,u32"`
SignedEnvelopeA []byte `wire:"4,bytes,max_bytes=envelope"`
SignedEnvelopeB []byte `wire:"5,bytes,max_bytes=envelope"`
BroadcastCertificate []byte `wire:"6,bytes,max_bytes=broadcast_certificate"`
Statement []byte `wire:"7,bytes,max_bytes=identification_statement"`
Proof []byte `wire:"8,bytes,max_bytes=zk_proof"`
TranscriptHashes []EvidenceField `wire:"9,recordlist,max_items=identification_hashes"`
}
IdentificationRecord contains the public statement needed to verify one identifiable-abort accusation. It must never contain protocol witnesses.
func (*IdentificationRecord) BeforeMarshalWire ¶
func (r *IdentificationRecord) BeforeMarshalWire() error
BeforeMarshalWire canonicalizes named transcript hashes.
func (IdentificationRecord) Clone ¶
func (r IdentificationRecord) Clone() IdentificationRecord
Clone returns an independently owned record.
func (IdentificationRecord) ComputeAlertDigest ¶
func (r IdentificationRecord) ComputeAlertDigest() [32]byte
ComputeAlertDigest hashes the public failure class, artifacts, and trusted transcript hashes that existed before the identification proof was made.
func (*IdentificationRecord) MarshalBinary ¶
func (r *IdentificationRecord) MarshalBinary() ([]byte, error)
MarshalBinary returns the strict canonical wire encoding.
func (*IdentificationRecord) MarshalBinaryWithLimits ¶
func (r *IdentificationRecord) MarshalBinaryWithLimits(limits IdentificationRecordLimits) ([]byte, error)
MarshalBinaryWithLimits returns the strict canonical wire encoding under explicit resource limits.
func (*IdentificationRecord) UnmarshalBinary ¶
func (r *IdentificationRecord) UnmarshalBinary(in []byte) error
UnmarshalBinary decodes a strict canonical wire record.
func (*IdentificationRecord) UnmarshalBinaryWithLimits ¶
func (r *IdentificationRecord) UnmarshalBinaryWithLimits(in []byte, limits IdentificationRecordLimits) error
UnmarshalBinaryWithLimits decodes a strict canonical identification record under explicit resource limits.
func (*IdentificationRecord) Validate ¶
func (r *IdentificationRecord) Validate() error
Validate rejects incomplete, non-public, or non-canonical record shapes.
func (*IdentificationRecord) ValidateWithLimits ¶
func (r *IdentificationRecord) ValidateWithLimits(limits IdentificationRecordLimits) error
ValidateWithLimits rejects incomplete, non-public, or non-canonical record shapes using explicit resource limits.
func (IdentificationRecord) WireType ¶
func (IdentificationRecord) WireType() string
WireType returns the canonical wire type identifier.
func (IdentificationRecord) WireVersion ¶
func (IdentificationRecord) WireVersion() uint16
WireVersion returns the canonical wire version.
type IdentificationRecordLimits ¶
type IdentificationRecordLimits struct {
MaxBytes int
MaxFailureClassBytes int
MaxEnvelopeBytes int
MaxBroadcastCertificateBytes int
MaxStatementBytes int
MaxProofBytes int
MaxTranscriptHashCount int
MaxTranscriptHashKeyBytes int
TLV TLVLimits
}
IdentificationRecordLimits caps one portable identifiable-abort record. The conservative defaults remain suitable for ordinary protocol evidence; protocols with intentionally larger public proofs must opt in explicitly.
func DefaultIdentificationRecordLimits ¶
func DefaultIdentificationRecordLimits() IdentificationRecordLimits
DefaultIdentificationRecordLimits returns a caller-owned copy of the conservative limits used by IdentificationRecord.MarshalBinary and IdentificationRecord.UnmarshalBinary.
type InMemoryAckSigner ¶
type InMemoryAckSigner struct {
// contains filtered or unexported fields
}
InMemoryAckSigner is a simple BroadcastAckSigner that uses an in-memory mapping from PartyID to an Ed25519-like signing function. It is intended for tests and single-process deployments.
func NewInMemoryAckSigner ¶
func NewInMemoryAckSigner(party PartyID, signFn func(digest [32]byte) ([]byte, error)) *InMemoryAckSigner
NewInMemoryAckSigner creates a signer bound to a party.
type InMemoryAckVerifier ¶
type InMemoryAckVerifier struct {
// contains filtered or unexported fields
}
InMemoryAckVerifier is a simple BroadcastAckVerifier that uses an in-memory mapping from PartyID to a verification function. It is intended for tests and single-process deployments.
func NewInMemoryAckVerifier ¶
func NewInMemoryAckVerifier(verifyFn func(party PartyID, digest [32]byte, signature []byte) error) *InMemoryAckVerifier
NewInMemoryAckVerifier creates a verifier.
type InMemoryReplayCache ¶
type InMemoryReplayCache struct {
// contains filtered or unexported fields
}
InMemoryReplayCache is a simple mutex-protected ReplayCache for use in tests and single-process deployments. Production multi-process deployments should use a durable shared cache (e.g. Redis) keyed by session ID + slot key.
MaxEntries limits the number of cached slots (0 = use default of 100000). The cache fails closed with ErrReplayCacheFull instead of evicting security state that may still be needed to reject a replay or equivocation.
func NewBoundedReplayCache ¶
func NewBoundedReplayCache(maxEntries int) *InMemoryReplayCache
NewBoundedReplayCache returns a bounded in-memory replay cache. Once full, new slots fail with ErrReplayCacheFull; existing slots remain available for duplicate and equivocation checks.
maxEntries must be positive. Values <= 0 are replaced with the default of [defaultReplayCacheMaxEntries]. The default is intentionally large enough to accommodate normal protocol message volumes; callers operating in constrained environments should pick an explicit value based on expected throughput.
func NewInMemoryReplayCache ¶
func NewInMemoryReplayCache() *InMemoryReplayCache
NewInMemoryReplayCache returns an initialized in-memory replay cache with a default bound of 100000 entries to prevent unbounded memory growth in long-running processes. For an explicit bound, use NewBoundedReplayCache.
func (*InMemoryReplayCache) CheckAndStore ¶
func (c *InMemoryReplayCache) CheckAndStore(slot MessageSlotKey, payloadHash [32]byte) error
CheckAndStore implements ReplayCache. It atomically checks whether a message slot has been seen and returns nil on first use, ErrDuplicateMessage when the same payload hash is replayed, or ErrEquivocation when a different payload hash occupies the same slot.
A nil receiver returns ErrMissingReplayCache (fail-closed) — callers must initialize the cache.
func (*InMemoryReplayCache) RetireSession ¶
func (c *InMemoryReplayCache) RetireSession(protocol ProtocolID, sessionID SessionID) error
RetireSession removes replay history for a terminal session. Callers must durably prevent the session ID from being reused before retiring its state.
type InMemoryTransport ¶
type InMemoryTransport struct {
// contains filtered or unexported fields
}
InMemoryTransport is a reference implementation of Transport that uses Go channels for in-process message delivery. Each party gets its own transport instance. Messages are opened with authenticated ReceiveInfo.
Direct messages are delivered only to the addressed recipient. Broadcast messages are delivered to all parties.
Broadcast certificates are NOT generated automatically.
func NewInMemoryTransport ¶
func NewInMemoryTransport(self PartyID, parties PartySet, policies PolicySet) *InMemoryTransport
NewInMemoryTransport creates a transport for one party.
func (*InMemoryTransport) Broadcast ¶
func (t *InMemoryTransport) Broadcast(_ context.Context, env Envelope) error
Broadcast delivers an envelope to all parties.
func (*InMemoryTransport) ConnectOutbox ¶
func (t *InMemoryTransport) ConnectOutbox(party PartyID, outbox chan<- InboundEnvelope)
ConnectOutbox registers the outbox channel for a remote party. In a real deployment this would be a network connection.
func (*InMemoryTransport) Inbox ¶
func (t *InMemoryTransport) Inbox() <-chan InboundEnvelope
Inbox returns the receive channel for this transport.
func (*InMemoryTransport) Parties ¶
func (t *InMemoryTransport) Parties() PartySet
Parties returns the party set for this transport instance.
func (*InMemoryTransport) Receive ¶
func (t *InMemoryTransport) Receive(ctx context.Context) (InboundEnvelope, error)
Receive returns the next envelope from the inbox.
type InboundEnvelope ¶
type InboundEnvelope struct {
// contains filtered or unexported fields
}
InboundEnvelope is a received envelope bound to transport-verified facts.
Its fields are intentionally unexported so callers cannot mutate wire data or receive facts after opening and validation.
func OpenEnvelope ¶
func OpenEnvelope(raw []byte, info ReceiveInfo, opts ...OpenOption) (InboundEnvelope, error)
OpenEnvelope decodes a wire envelope and binds it to transport-verified receive facts. Protocol policy checks are performed later by EnvelopeGuard.
func OpenEnvelopeWithLimits ¶
func OpenEnvelopeWithLimits(raw []byte, info ReceiveInfo, limits EnvelopeLimits, opts ...OpenOption) (InboundEnvelope, error)
OpenEnvelopeWithLimits decodes a wire envelope with explicit limits and binds it to transport-verified receive facts.
func (InboundEnvelope) BroadcastCertificate ¶
func (in InboundEnvelope) BroadcastCertificate() *BroadcastCertificate
BroadcastCertificate returns a deep copy of the attached broadcast certificate.
func (InboundEnvelope) Digest ¶
func (in InboundEnvelope) Digest() EnvelopeDigest
Digest computes the domain-separated digest of the inbound envelope.
func (InboundEnvelope) Envelope ¶
func (in InboundEnvelope) Envelope() Envelope
Envelope returns a deep copy of the inbound wire envelope.
func (InboundEnvelope) From ¶
func (in InboundEnvelope) From() PartyID
From returns the sender party ID from the wire envelope.
func (InboundEnvelope) Payload ¶
func (in InboundEnvelope) Payload() []byte
Payload returns a copy of the envelope payload bytes.
func (InboundEnvelope) PayloadType ¶
func (in InboundEnvelope) PayloadType() PayloadType
PayloadType returns the payload type name.
func (InboundEnvelope) Protocol ¶
func (in InboundEnvelope) Protocol() ProtocolID
Protocol returns the envelope protocol identifier.
func (InboundEnvelope) ReceiveInfo ¶
func (in InboundEnvelope) ReceiveInfo() ReceiveInfo
ReceiveInfo returns a copy of the transport receive facts.
func (InboundEnvelope) Round ¶
func (in InboundEnvelope) Round() uint8
Round returns the protocol round.
func (InboundEnvelope) SessionID ¶
func (in InboundEnvelope) SessionID() SessionID
SessionID returns the envelope session ID.
func (InboundEnvelope) To ¶
func (in InboundEnvelope) To() PartyID
To returns the recipient party ID from the wire envelope, or zero for broadcast.
type InvalidChildMode ¶
type InvalidChildMode uint8
InvalidChildMode controls behavior when public derivation produces an invalid child.
const ( // ErrorOnInvalidChild returns an error immediately when an invalid child is encountered. ErrorOnInvalidChild InvalidChildMode = iota // SkipInvalidChild increments the index and retries until a valid child or hardened range. SkipInvalidChild )
func (InvalidChildMode) Valid ¶
func (m InvalidChildMode) Valid() bool
Valid reports whether mode is a defined invalid-child handling strategy.
type KeyShare ¶
type KeyShare interface {
}
KeyShare is the common interface implemented by algorithm-specific shares.
type LocalConfig ¶
type LocalConfig struct {
Self PartyID
Rand io.Reader `json:"-"`
Context context.Context `json:"-"`
Log Logger `json:"-"`
EnvelopeSigner EnvelopeSigner `json:"-"`
}
LocalConfig contains per-process runtime configuration for one protocol participant. Consensus parameters such as threshold, party set, session ID, signer set, derivation context, and HD enablement belong in protocol-specific plan objects, not in LocalConfig.
func (LocalConfig) Ctx ¶
func (c LocalConfig) Ctx() context.Context
Ctx returns the local configuration context or context.Background when unset.
func (LocalConfig) Logger ¶
func (c LocalConfig) Logger() Logger
Logger returns the configured Logger or a no-op implementation when unset.
func (LocalConfig) Reader ¶
func (c LocalConfig) Reader() io.Reader
Reader returns the configured randomness source or crypto/rand.
type Logger ¶
type Logger interface {
Debug(ctx context.Context, msg string, fields ...any)
Info(ctx context.Context, msg string, fields ...any)
Warn(ctx context.Context, msg string, fields ...any)
Error(ctx context.Context, msg string, fields ...any)
}
Logger is the logging interface used by protocol sessions. The zero-value is a no-op implementation that discards all messages.
type MaliciousTransport ¶
type MaliciousTransport struct {
// contains filtered or unexported fields
}
MaliciousTransport wraps an InMemoryTransport and applies a specified transport-layer attack for security testing. Every attack mode must be caught by EnvelopeGuard.Validate before reaching the protocol handler.
func NewMaliciousTransport ¶
func NewMaliciousTransport(inner *InMemoryTransport, mode AttackMode) *MaliciousTransport
NewMaliciousTransport creates a transport that applies the given attack.
func (*MaliciousTransport) Broadcast ¶
func (m *MaliciousTransport) Broadcast(ctx context.Context, env Envelope) error
Broadcast applies the attack mode and delegates to the inner transport.
func (*MaliciousTransport) Receive ¶
func (m *MaliciousTransport) Receive(ctx context.Context) (InboundEnvelope, error)
Receive delegates to the inner transport.
type MessageSlotKey ¶
type MessageSlotKey struct {
Protocol ProtocolID
SessionID SessionID
Round uint8
From PartyID
To PartyID
PayloadType PayloadType
}
MessageSlotKey identifies a unique protocol message slot for equivocation detection. It does not include the payload hash: two different payloads occupying the same slot constitute equivocation.
func SlotKeyFromEnvelope ¶
func SlotKeyFromEnvelope(env Envelope) MessageSlotKey
SlotKeyFromEnvelope constructs a MessageSlotKey from the envelope's identifying fields. The payload is excluded so that different payloads for the same slot are detected as equivocation.
type OpenOption ¶
type OpenOption func(*openOptions)
OpenOption configures OpenEnvelope.
func WithBroadcastCertificate ¶
func WithBroadcastCertificate(cert *BroadcastCertificate) OpenOption
WithBroadcastCertificate attaches a transport-collected broadcast certificate to the opened inbound envelope. OpenEnvelope deep-clones the certificate before storing it, so the caller retains ownership of the original.
func WithEnvelopeLimits ¶
func WithEnvelopeLimits(limits EnvelopeLimits) OpenOption
WithEnvelopeLimits configures explicit envelope size limits while opening.
type PartyID ¶
type PartyID = uint32
PartyID identifies a protocol participant. The zero value is reserved to mean unset and broadcast mode for Envelope.
const BroadcastPartyId PartyID = 0
BroadcastPartyId is the receiver of broadcast mode
type PartySet ¶
type PartySet []PartyID
PartySet is an ordered set of protocol participants.
func MergePartySet ¶
MergePartySet takes a set slice and returns a new sorted set containing elements which are in either or both of this set and the given set
func NewPartySet ¶
NewPartySet returns a PartySet containing parties in the given order.
func SortParties ¶
SortParties returns a sorted copy of parties.
type PassphraseParams ¶
type PassphraseParams struct {
// Time is the number of Argon2id iterations (passes).
// RFC 9106 §7.3 recommends 3 for non-interactive use.
Time uint32
// Memory is the memory cost in kibibytes.
// RFC 9106 §7.3 recommends at least 65536 (64 MiB) for non-interactive use.
Memory uint32
// Threads is the degree of parallelism.
// RFC 9106 §7.3 recommends 4 for non-interactive use.
Threads uint8
}
PassphraseParams holds Argon2id parameters for passphrase-based key derivation. The zero value is not valid; use DefaultPassphraseParams or populate every field.
func DefaultPassphraseParams ¶
func DefaultPassphraseParams() *PassphraseParams
DefaultPassphraseParams returns RFC 9106 recommended Argon2id parameters for non-interactive passphrase-based key derivation (time=3, memory=64 MiB, threads=4).
type PolicySet ¶
type PolicySet struct {
// contains filtered or unexported fields
}
PolicySet is a collection of delivery policies with O(1) lookup by (protocol, round, payloadType). Use NewPolicySet to construct. It must return ErrUnknownPayloadPolicy for unregistered payload types.
func MustNewPolicySet ¶
func MustNewPolicySet(policies ...DeliveryPolicy) PolicySet
MustNewPolicySet is like NewPolicySet but panics on duplicate keys or when a broadcast-mode policy does not require BroadcastConsistencyRequired. It is intended for package-level var initialization where errors are a programmer mistake.
func NewPolicySet ¶
func NewPolicySet(policies ...DeliveryPolicy) (PolicySet, error)
NewPolicySet builds a PolicySet from a list of delivery policies. It clones the input slice so callers cannot mutate the policy entries after construction. Duplicate keys are rejected.
func NewTestPolicySet ¶
func NewTestPolicySet(policies ...DeliveryPolicy) (PolicySet, error)
NewTestPolicySet builds a structurally valid policy set whose mandatory broadcast-consistency or sender-signature requirements may be relaxed for deterministic tests. It panics outside a Go test binary and production guards reject the returned set.
func (PolicySet) Digest ¶
Digest returns the canonical delivery-policy digest. Registration order does not affect the result; every field that changes guard behavior is bound.
func (PolicySet) Entries ¶
func (ps PolicySet) Entries() []DeliveryPolicy
Entries returns a copy of the policy entries in registration order.
func (PolicySet) Match ¶
func (ps PolicySet) Match(protocol ProtocolID, round uint8, payloadType PayloadType) (DeliveryPolicy, error)
Match returns the policy for a given message kind or ErrUnknownPayloadPolicy.
func (PolicySet) ValidateBroadcastConsistency ¶
ValidateBroadcastConsistency checks that every broadcast-mode DeliveryPolicy requires BroadcastConsistencyRequired. It returns an error listing any broadcast policy that does not. Production callers should invoke this once during initialization.
type ProtocolError ¶
ProtocolError is the stable error shape returned by protocol state machines.
func NewProtocolError ¶
func NewProtocolError(code string, round uint8, party PartyID, err error) *ProtocolError
NewProtocolError constructs a ProtocolError without blame evidence.
func (*ProtocolError) Error ¶
func (e *ProtocolError) Error() string
Error formats the protocol code with optional round, party, and wrapped error.
func (*ProtocolError) Unwrap ¶
func (e *ProtocolError) Unwrap() error
Unwrap returns the underlying error for errors.Is/errors.As callers.
type ProtocolID ¶
type ProtocolID string
ProtocolID names a threshold signature protocol implemented by this module.
const ( // ProtocolCGGMP21Secp256k1 identifies the CGGMP21-style threshold ECDSA protocol. ProtocolCGGMP21Secp256k1 ProtocolID = "cggmp21-secp256k1" // ProtocolFROSTEd25519 identifies the FROST-style threshold Ed25519 protocol. ProtocolFROSTEd25519 ProtocolID = "frost-ed25519" )
type ReceiveInfo ¶
type ReceiveInfo struct {
Peer PartyID
Protection ChannelProtection
ChannelID string
PeerKeyID string
ReceivedAt time.Time
}
ReceiveInfo records transport-verified facts for a received envelope.
type RefreshRunConfig ¶
type RefreshRunConfig struct {
SessionID SessionID
ReplayCache ReplayCache
AckVerifier BroadcastAckVerifier
EnvelopeSigner EnvelopeSigner
EnvelopeVerifier EnvelopeSignatureVerifier
}
RefreshRunConfig carries the security configuration for one refresh run.
type RefreshRunner ¶
type RefreshRunner[K KeyShare] interface { // Protocol returns the protocol whose replay state the runner uses. Protocol() ProtocolID // StartRefresh constructs one algorithm-specific refresh session. StartRefresh(context.Context, K, RefreshRunConfig) (RefreshSession[K], []Envelope, error) }
RefreshRunner adapts an algorithm-specific, externally committed refresh protocol to the shared scheduler. Protocols whose session owns a durable lifecycle lease or cutover transaction must be driven through their native lifecycle API instead.
type RefreshScheduler ¶
type RefreshScheduler[K KeyShare] struct { // contains filtered or unexported fields }
RefreshScheduler periodically drives proactive refresh protocols that use an external compare-and-swap commit callback. It does not support protocols whose session owns its lifecycle cutover. A scheduler permits only one active Run or RunOnce call at a time.
func NewRefreshScheduler ¶
func NewRefreshScheduler[K KeyShare](opts RefreshSchedulerOptions[K]) (*RefreshScheduler[K], error)
NewRefreshScheduler constructs a proactive refresh scheduler.
func (*RefreshScheduler[K]) Run ¶
func (s *RefreshScheduler[K]) Run(ctx context.Context) error
Run executes refresh periodically until ctx is cancelled or a run fails. The first refresh starts after one interval.
func (*RefreshScheduler[K]) RunOnce ¶
func (s *RefreshScheduler[K]) RunOnce(ctx context.Context) error
RunOnce immediately executes one refresh run.
Example ¶
ExampleRefreshScheduler_RunOnce demonstrates an operationally triggered refresh with an atomic compare-and-swap commit callback.
package main
import (
"context"
"errors"
"fmt"
"time"
"github.com/islishude/tss"
)
type exampleRefreshShare struct {
generation int
}
func (*exampleRefreshShare) Algorithm() tss.Algorithm { return tss.AlgorithmFROSTEd25519 }
func (*exampleRefreshShare) PartyID() tss.PartyID { return 1 }
func (*exampleRefreshShare) PublicKeyBytes() []byte { return []byte("group-public-key") }
func (*exampleRefreshShare) ChainCodeBytes() []byte { return make([]byte, 32) }
func (*exampleRefreshShare) Derive(path tss.DerivationPath, opts ...tss.DeriveOption) (*tss.DerivationResult, error) {
return &tss.DerivationResult{
Scheme: tss.DerivationSchemeEd25519KhovratovichLaw,
ChildPublicKey: []byte("group-public-key"),
ChildChainCode: make([]byte, 32),
RequestedPath: path.Clone(),
ResolvedPath: path.Clone(),
AdditiveShift: make([]byte, 32),
}, nil
}
func (*exampleRefreshShare) MarshalBinary() ([]byte, error) { return []byte("example-share"), nil }
func (*exampleRefreshShare) Destroy() {}
type exampleRefreshRunner struct{}
func (exampleRefreshRunner) Protocol() tss.ProtocolID { return tss.ProtocolFROSTEd25519 }
func (exampleRefreshRunner) StartRefresh(context.Context, *exampleRefreshShare, tss.RefreshRunConfig) (tss.RefreshSession[*exampleRefreshShare], []tss.Envelope, error) {
return exampleRefreshSession{refreshed: &exampleRefreshShare{generation: 2}}, nil, nil
}
type exampleRefreshSession struct {
refreshed *exampleRefreshShare
}
func (exampleRefreshSession) Handle(context.Context, tss.InboundEnvelope) ([]tss.Envelope, error) {
return nil, errors.New("example refresh is already complete")
}
func (s exampleRefreshSession) KeyShare() (*exampleRefreshShare, bool) {
return s.refreshed, true
}
func (exampleRefreshSession) Close(context.Context) error { return nil }
type exampleRefreshTransport struct{}
func (exampleRefreshTransport) Send(context.Context, tss.Envelope) error { return nil }
func (exampleRefreshTransport) Broadcast(context.Context, tss.Envelope) error { return nil }
func (exampleRefreshTransport) Receive(context.Context) (tss.InboundEnvelope, error) {
return tss.InboundEnvelope{}, errors.New("example refresh is already complete")
}
type exampleAckVerifier struct{}
func (exampleAckVerifier) VerifyAck(tss.PartyID, [32]byte, []byte) error { return nil }
// ExampleRefreshScheduler_RunOnce demonstrates an operationally triggered
// refresh with an atomic compare-and-swap commit callback.
func main() {
current := &exampleRefreshShare{generation: 1}
scheduler, err := tss.NewRefreshScheduler(tss.RefreshSchedulerOptions[*exampleRefreshShare]{
Interval: 24 * time.Hour,
Transport: exampleRefreshTransport{},
Runner: exampleRefreshRunner{},
ReplayCache: tss.NewInMemoryReplayCache(),
AckVerifier: exampleAckVerifier{},
LoadKeyShare: func(context.Context) (*exampleRefreshShare, error) {
return current, nil
},
SessionIDSource: func(context.Context, *exampleRefreshShare) (tss.SessionID, error) {
return tss.SessionID{1}, nil
},
ClaimSessionID: func(context.Context, tss.SessionID) error {
return nil
},
CommitKeyShare: func(_ context.Context, previous, refreshed *exampleRefreshShare) error {
if current != previous {
return errors.New("key share changed concurrently")
}
current = refreshed
return nil
},
})
if err != nil {
panic(err)
}
if err := scheduler.RunOnce(context.Background()); err != nil {
panic(err)
}
fmt.Println(current.generation)
}
Output: 2
type RefreshSchedulerOptions ¶
type RefreshSchedulerOptions[K KeyShare] struct { // Interval is the delay before the first refresh and between successful runs. Interval time.Duration // Transport delivers protocol envelopes with authenticated receive metadata. Transport Transport // Runner starts algorithm-specific refresh sessions. Runner RefreshRunner[K] // ReplayCache stores seen refresh envelopes across scheduler runs. ReplayCache ReplayCache // AckVerifier verifies broadcast consistency certificates. AckVerifier BroadcastAckVerifier // EnvelopeSigner authenticates local direct refresh envelopes. EnvelopeSigner EnvelopeSigner // EnvelopeVerifier authenticates direct refresh envelopes from peers. EnvelopeVerifier EnvelopeSignatureVerifier LoadKeyShare func(context.Context) (K, error) // SessionIDSource returns the externally coordinated unique session ID for // the next run. Every participant in one run must receive the same ID. SessionIDSource func(context.Context, K) (SessionID, error) // ClaimSessionID durably and atomically records first use of a session ID. // A claimed ID remains unavailable even if this refresh later fails. ClaimSessionID func(context.Context, SessionID) error // atomically persists and installs refreshed if previous is still current. // The Runner and RefreshSession must not perform this commit themselves. A // nil result transfers ownership of refreshed to the callback. On a normal // error the scheduler destroys refreshed. If the error wraps // ErrRefreshCommitOutcomeUnknown, the callback retains ownership because the // durable commit may have succeeded. CommitKeyShare func(context.Context, K, K) error }
RefreshSchedulerOptions configures periodic proactive key-share refresh.
type RefreshSession ¶
type RefreshSession[K KeyShare] interface { // Handle validates and applies one inbound refresh envelope. Handle(context.Context, InboundEnvelope) ([]Envelope, error) // returned share must remain valid after Close is called on the session. KeyShare() (K, bool) // Close clears secret material retained by the session and reports cleanup failures. Close(context.Context) error }
RefreshSession is the protocol-independent surface needed to drive one externally committed key-share refresh session. Implementations must not install or otherwise durably commit their candidate share themselves.
type ReplayCache ¶
type ReplayCache interface {
CheckAndStore(slot MessageSlotKey, payloadHash [32]byte) error
RetireSession(protocol ProtocolID, sessionID SessionID) error
}
ReplayCache detects replayed and equivocating protocol messages. CheckAndStore atomically checks whether a message slot has been seen and:
- Stores the payload hash and returns nil when the slot is new.
- Returns ErrDuplicateMessage when the slot exists with the same payload hash.
- Returns ErrEquivocation when the slot exists with a different payload hash.
RetireSession removes replay state only after the identified session is terminal and its session ID is durably unavailable for reuse.
type SLogger ¶
SLogger adapts log/slog.Logger to the Logger interface.
func NewSLogger ¶
NewSLogger returns an SLogger that wraps sl.
type SessionConfig ¶
type SessionConfig struct {
Self PartyID
Parties PartySet
SessionID SessionID
PolicySet PolicySet
ReplayCache ReplayCache
}
SessionConfig carries the security configuration required to construct a protocol session.
type SessionID ¶
type SessionID [sessionIDSize]byte
SessionID is a 32-byte nonce that separates independent protocol executions.
func NewSessionID ¶
NewSessionID returns a random session identifier from reader or crypto/rand.
Example ¶
ExampleNewSessionID demonstrates how to generate a unique session identifier from a cryptographic random source. A nil reader uses crypto/rand.Reader. Session IDs are used to bind all messages in a protocol run together, preventing cross-session replay attacks.
package main
import (
"bytes"
"fmt"
"github.com/islishude/tss"
)
func main() {
sessionID, err := tss.NewSessionID(bytes.NewReader(bytes.Repeat([]byte{0x11}, 32)))
if err != nil {
panic(err)
}
fmt.Println(sessionID.String())
}
Output: 1111111111111111111111111111111111111111111111111111111111111111
func SessionIDFromBytes ¶
SessionIDFromBytes parses a 32-byte session identifier.
func (SessionID) MarshalText ¶
MarshalText encodes the session identifier as hex text.
func (*SessionID) UnmarshalText ¶
UnmarshalText decodes a hex session identifier.
type SignIntent ¶
type SignIntent struct {
SessionID SessionID
Context SigningContext
Message []byte
Signers PartySet
}
SignIntent is the protocol-independent shared intent that signers authorize before producing protocol messages.
func (SignIntent) Clone ¶
func (i SignIntent) Clone() SignIntent
Clone returns an independently owned copy of the signing intent.
func (SignIntent) Request ¶
func (i SignIntent) Request() SignRequest
Request returns the context-bound request represented by the intent.
type SignRequest ¶
type SignRequest struct {
Context SigningContext `json:"context"`
Message []byte `json:"message"`
}
SignRequest is a context-bound message supplied for signature creation or verification. Protocols decide how the context and message are hashed.
func (SignRequest) Clone ¶
func (r SignRequest) Clone() SignRequest
Clone returns an independently owned copy of the signing request.
type SigningContext ¶
type SigningContext struct {
KeyID string `json:"key_id" wire:"1,string"`
ChainID string `json:"chain_id" wire:"2,string"`
Derivation DerivationRequest `json:"derivation" wire:"3,record"`
PolicyDomain string `json:"policy_domain" wire:"4,string"`
MessageDomain string `json:"message_domain" wire:"5,string"`
}
SigningContext binds a signing request to key, chain, derivation, policy, and message domains without changing the message bytes being signed.
func (SigningContext) Clone ¶
func (c SigningContext) Clone() SigningContext
Clone returns a caller-owned copy of the context.
func (SigningContext) DerivationPath ¶
func (c SigningContext) DerivationPath() DerivationPath
DerivationPath returns a caller-owned copy of the requested path.
func (SigningContext) MarshalBinary ¶
func (c SigningContext) MarshalBinary() ([]byte, error)
MarshalBinary encodes the signing context using canonical TLV.
func (*SigningContext) UnmarshalBinary ¶
func (c *SigningContext) UnmarshalBinary(in []byte) error
UnmarshalBinary decodes a canonical signing context.
func (SigningContext) Validate ¶
func (c SigningContext) Validate() error
Validate checks required context fields and the non-hardened derivation path.
func (SigningContext) WireType ¶
func (SigningContext) WireType() string
WireType returns the canonical wire type identifier for SigningContext.
func (SigningContext) WireVersion ¶
func (SigningContext) WireVersion() uint16
WireVersion returns the wire format version for SigningContext.
type ThresholdConfig ¶
type ThresholdConfig struct {
Threshold int
Parties PartySet
Self PartyID
SessionID SessionID
Rand io.Reader `json:"-"`
Context context.Context `json:"-"`
Log Logger `json:"-"`
EnvelopeSigner EnvelopeSigner `json:"-"`
}
ThresholdConfig contains local participant configuration for a protocol run.
func (ThresholdConfig) Ctx ¶
func (c ThresholdConfig) Ctx() context.Context
Ctx returns the configuration context or context.Background when unset.
func (ThresholdConfig) Logger ¶
func (c ThresholdConfig) Logger() Logger
Logger returns the configured Logger or a no-op implementation when unset.
func (ThresholdConfig) Reader ¶
func (c ThresholdConfig) Reader() io.Reader
Reader returns the configured randomness source or crypto/rand.
func (ThresholdConfig) SortedParties ¶
func (c ThresholdConfig) SortedParties() PartySet
SortedParties returns the configured party set in ascending order.
func (ThresholdConfig) Validate ¶
func (c ThresholdConfig) Validate() error
Validate checks threshold, party-set, and local-party invariants using conservative default limits. Callers that know the algorithm should prefer ValidateWithLimits with algorithm-specific limits.
func (ThresholdConfig) ValidateWithLimits ¶
func (c ThresholdConfig) ValidateWithLimits(l ThresholdLimits) error
ValidateWithLimits checks threshold, party-set, and local-party invariants against the provided ThresholdLimits. It enforces hard caps on party count and threshold to prevent unbounded resource consumption.
type ThresholdLimits ¶
type ThresholdLimits struct {
MaxParties int
MaxThreshold int
MaxSigners int
MinProductionThreshold int
AllowOneOfOne bool
AllowOversizedSignerSet bool
}
ThresholdLimits defines finite caps for threshold protocol parameters.
func (ThresholdLimits) ValidateThreshold ¶
func (l ThresholdLimits) ValidateThreshold(threshold, nParties int) error
ValidateThreshold checks that threshold and party count comply with the configured production minimum and AllowOneOfOne policy.
type Transport ¶
type Transport interface {
// Send delivers a direct (point-to-point) envelope to its recipient.
Send(ctx context.Context, env Envelope) error
// Broadcast delivers an envelope to all parties.
Broadcast(ctx context.Context, env Envelope) error
// Receive blocks until the next envelope is available and returns it
// with transport-verified receive facts bound to the wire envelope.
Receive(ctx context.Context) (InboundEnvelope, error)
}
Transport abstracts the network layer used to deliver protocol envelopes. Implementations receive raw wire bytes, authenticate the peer, classify the actual channel protection, and return an InboundEnvelope opened with ReceiveInfo.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cggmp21
|
|
|
secp256k1
Package secp256k1 exposes the CGGMP21/secp256k1 threshold ECDSA API.
|
Package secp256k1 exposes the CGGMP21/secp256k1 threshold ECDSA API. |
|
frost
|
|
|
ed25519
Package ed25519 implements a FROST-style threshold Ed25519 flow with dealerless DKG, explicitly authorized trusted-dealer import, and threshold secret reconstruction.
|
Package ed25519 implements a FROST-style threshold Ed25519 flow with dealerless DKG, explicitly authorized trusted-dealer import, and threshold secret reconstruction. |
|
internal
|
|
|
clone
Package clone provides internal helpers for making independently owned copies.
|
Package clone provides internal helpers for making independently owned copies. |
|
fiat/secp256k1field
Code generated by Fiat Cryptography.
|
Code generated by Fiat Cryptography. |
|
fiat/secp256k1scalar
Code generated by Fiat Cryptography.
|
Code generated by Fiat Cryptography. |
|
inmemoryrun
Package inmemoryrun provides a private authenticated router for production helpers that deliberately execute a complete multi-party protocol in one process.
|
Package inmemoryrun provides a private authenticated router for production helpers that deliberately execute a complete multi-party protocol in one process. |
|
oneuse
Package oneuse provides small lifecycle guards for secret-bearing values that may be claimed once and must be destroyed when consumed.
|
Package oneuse provides small lifecycle guards for secret-bearing values that may be claimed once and must be destroyed when consumed. |
|
paillier/paillierct
Package paillierct provides constant-time modular exponentiation for Paillier private-key operations.
|
Package paillierct provides constant-time modular exponentiation for Paillier private-key operations. |
|
plantranscript
Package plantranscript centralizes transcript fragments shared by protocol plans without sharing protocol-specific transcript domains or field order.
|
Package plantranscript centralizes transcript fragments shared by protocol plans without sharing protocol-specific transcript domains or field order. |
|
planvalidation
Package planvalidation centralizes lifecycle-plan validation shared by protocol packages.
|
Package planvalidation centralizes lifecycle-plan validation shared by protocol packages. |
|
secret
Package secret provides fixed-length scalar types for cryptographic secrets.
|
Package secret provides fixed-length scalar types for cryptographic secrets. |
|
shamir
Package shamir implements Shamir secret sharing over the secp256k1 scalar field for CGGMP21.
|
Package shamir implements Shamir secret sharing over the secp256k1 scalar field for CGGMP21. |
|
testharness
Package testharness provides reusable test infrastructure for TSS protocol tests: deterministic RNG, party factories, envelope mutation, network fault simulation, state snapshots, protocol runners, and crash-store helpers.
|
Package testharness provides reusable test infrastructure for TSS protocol tests: deterministic RNG, party factories, envelope mutation, network fault simulation, state snapshots, protocol runners, and crash-store helpers. |
|
testutil
Package testutil provides shared test helpers used across TSS protocol tests.
|
Package testutil provides shared test helpers used across TSS protocol tests. |
|
testutil/cmd/testbudget
command
testbudget parses `go test -json` output from stdin and flags individual tests that exceed their tier's runtime budget.
|
testbudget parses `go test -json` output from stdin and flags individual tests that exceed their tier's runtime budget. |
|
testvectors
Package testvectors provides shared helpers for reading, locating, and validating the repository's committed test-vector files.
|
Package testvectors provides shared helpers for reading, locating, and validating the repository's committed test-vector files. |
|
testvectors/cmd/tvgen
command
|
|
|
transcript
Package transcript provides canonical labeled SHA-256 transcripts.
|
Package transcript provides canonical labeled SHA-256 transcripts. |
|
wire
Package wire provides a strict canonical TLV binary encoding for cryptographic protocol messages.
|
Package wire provides a strict canonical TLV binary encoding for cryptographic protocol messages. |
|
zk/challenge
Package challenge derives canonical Fiat-Shamir challenges from transcript roots.
|
Package challenge derives canonical Fiat-Shamir challenges from transcript roots. |
|
zk/paillier
Package paillier contains Paillier zero-knowledge proofs used by the CGGMP21-style secp256k1 signing path.
|
Package paillier contains Paillier zero-knowledge proofs used by the CGGMP21-style secp256k1 signing path. |
|
zk/schnorred25519
Package schnorred25519 implements non-interactive Schnorr proofs of knowledge in the prime-order Ed25519 subgroup.
|
Package schnorred25519 implements non-interactive Schnorr proofs of knowledge in the prime-order Ed25519 subgroup. |
|
Package tssrun defines the production integration contract for TSS protocol runs.
|
Package tssrun defines the production integration contract for TSS protocol runs. |
|
conformance
Package conformance provides reusable tests for tssrun integration stores.
|
Package conformance provides reusable tests for tssrun integration stores. |