epr

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README ¶

pkg/crypto/epr

Ephemeral Proof Routines - Two-step cryptographic verification.

Status: 🧪 Experimental

Core cryptographic primitive for proof-of-possession.

What It Does

Implements two-step verification where a master key authorizes ephemeral keys:

flowchart LR
    subgraph "Two-Step Proof"
        Master[Master Key] -->|Signs| Binding[Ephemeral Binding]
        Binding -->|Contains| Ephemeral[Ephemeral Public Key]
        Ephemeral -->|Signs| Request[Actual Request]
    end

    subgraph "Verification"
        V1[Step 1: Verify master signed ephemeral]
        V2[Step 2: Verify ephemeral signed request]
        V1 --> V2
        V2 --> Valid[✓ Valid Proof]
    end

Files

  • proof.go - Proof generation and binding
  • proof_test.go - Test coverage
  • verifier.go - Two-step verification logic

How It Works

// Step 1: Master authorizes ephemeral
binding := createBinding(ephemeralPubKey, expiry, purpose)
masterSig := ed25519.Sign(masterPriv, binding)

// Step 2: Ephemeral signs request
requestSig := ed25519.Sign(ephemeralPriv, requestData)

// Verification checks both steps
valid := verifyMasterBinding(masterPub, binding, masterSig) &&
         verifyRequest(ephemeralPub, requestData, requestSig)

Key Features

  • Domain Separation: Uses "signet-ephemeral-binding-v1:" prefix
  • Forward Secrecy: Ephemeral keys destroyed after use
  • Time-Bound: Each ephemeral has expiry time
  • Purpose-Bound: Ephemeral keys tagged with purpose

Security Properties

  • Ephemeral keys cannot be used without master authorization
  • Master key never signs actual requests (only bindings)
  • Each ephemeral key used once then destroyed
  • Prevents key substitution attacks via domain separation

Documentation ¶

Overview ¶

Package epr provides Ephemeral Proof Routines for Signet authentication. This file implements Ed25519 signature canonicalization to prevent signature malleability attacks.

NOTE: This module is primarily for testing and verification purposes. Production code should use pkg/crypto/keys/signer.go which provides proper lifecycle management with secure memory zeroization.

The functions in this file are designed to demonstrate and verify Ed25519's signature canonicalization properties, particularly for understanding signature malleability prevention.

Index ¶

Constants ¶

View Source
const DomainSeparator = "signet-ephemeral-binding-v1:"

DomainSeparator is the prefix for binding signatures to prevent cross-protocol attacks

Variables ¶

View Source
var (
	// ErrInvalidBinding indicates the binding verification failed
	// Deprecated: Use signetErrors.ErrInvalidBindingSignature instead
	ErrInvalidBinding = signetErrors.ErrInvalidBindingSignature

	// ErrInvalidRequestSignature indicates the per-request signature is invalid
	// Deprecated: Use signetErrors.ErrInvalidRequestSignature instead
	ErrInvalidRequestSignature = signetErrors.ErrInvalidRequestSignature
)

Common verification errors - deprecated, use pkg/errors instead

Functions ¶

func CompareSignatures ¶

func CompareSignatures(a, b []byte) bool

CompareSignatures performs constant-time comparison of signatures

func IsCanonicalSignature ¶

func IsCanonicalSignature(signature []byte) bool

IsCanonicalSignature checks if an Ed25519 signature is in canonical form. A signature is canonical if S < L/2 where L is the Ed25519 group order. This prevents signature malleability where both (R, S) and (R, -S mod L) are valid signatures for the same message.

func MakeCanonical ¶

func MakeCanonical(signature []byte) ([]byte, error)

MakeCanonical ensures a signature is in canonical form. If the signature is already canonical, it returns the original. If the signature is non-canonical (S >= L/2), it returns the canonical form.

NOTE: Go's ed25519.Sign() already produces canonical signatures, so this is primarily for defense-in-depth and handling signatures from external sources.

func Sign ¶

func Sign(privateKey ed25519.PrivateKey, message []byte) ([]byte, error)

Sign creates a standard Ed25519 signature. Note: This produces signatures with S < L (valid) but not necessarily S < L/2 (strict canonical form). About 50% of signatures will NOT pass VerifyCanonical.

For applications requiring strict canonicality, enforce it at verification time using VerifyCanonical() rather than attempting to generate canonical signatures.

func VerifyCanonical ¶

func VerifyCanonical(publicKey ed25519.PublicKey, message, signature []byte) bool

VerifyCanonical performs signature verification with canonical check. It rejects non-canonical signatures to prevent malleability attacks.

Types ¶

type BatchVerifier ¶

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

BatchVerifier verifies multiple proofs efficiently

func NewBatchVerifier ¶

func NewBatchVerifier(options *VerificationOptions) *BatchVerifier

NewBatchVerifier creates a new batch verifier

func (*BatchVerifier) VerifyBatch ¶

func (bv *BatchVerifier) VerifyBatch(ctx context.Context, proofs []*EphemeralProof, masterKeys map[string]crypto.PublicKey, messages map[string][]byte, signatures map[string][]byte) (map[string]*VerificationResult, error)

VerifyBatch verifies multiple proofs in a batch

type EphemeralProof ¶

type EphemeralProof struct {
	// EphemeralPublicKey is the public key of the ephemeral key pair
	EphemeralPublicKey crypto.PublicKey

	// BindingSignature is the signature from the MASTER key over the EphemeralPublicKey
	BindingSignature []byte
}

EphemeralProof represents a proof that a master key has authorized an ephemeral key for a specific purpose and time.

type Generator ¶

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

Generator generates ephemeral proofs of possession

func NewGenerator ¶

func NewGenerator(masterSigner crypto.Signer) *Generator

NewGenerator creates a new ephemeral proof generator

func (*Generator) GenerateProof ¶

func (g *Generator) GenerateProof(ctx context.Context, request *ProofRequest) (*ProofResponse, error)

GenerateProof creates an ephemeral proof of possession

type ProofRequest ¶

type ProofRequest struct {
	// ValidityPeriod specifies how long the proof is valid
	ValidityPeriod time.Duration

	// Purpose describes what this ephemeral key is for (e.g., "git-commit")
	Purpose string
}

ProofRequest contains parameters for generating an ephemeral proof

type ProofResponse ¶

type ProofResponse struct {
	// Proof is the ephemeral proof of possession
	Proof *EphemeralProof

	// EphemeralPrivateKey is the private key wrapped with automatic cleanup.
	// Caller MUST call Destroy() when done, typically with defer:
	//   resp, err := generator.GenerateProof(...)
	//   if err != nil { return err }
	//   defer resp.EphemeralPrivateKey.Destroy()
	EphemeralPrivateKey *keys.SecurePrivateKey
}

ProofResponse contains the generated proof and ephemeral key

type ProofVerifier ¶

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

ProofVerifier provides comprehensive proof verification

func NewProofVerifier ¶

func NewProofVerifier(options *VerificationOptions) *ProofVerifier

NewProofVerifier creates a new proof verifier with options

func (*ProofVerifier) Verify ¶

func (pv *ProofVerifier) Verify(ctx context.Context, proof *EphemeralProof, masterPublicKey crypto.PublicKey, message []byte, signature []byte) (*VerificationResult, error)

Verify performs complete two-step verification of an ephemeral proof

type VerificationOptions ¶

type VerificationOptions struct {
	// SkipBindingVerification skips the binding verification (for testing)
	SkipBindingVerification bool
}

VerificationOptions contains options for proof verification

type VerificationResult ¶

type VerificationResult struct {
	// Valid indicates if the proof is valid
	Valid bool

	// Errors contains any verification errors
	Errors []error
}

VerificationResult contains the result of proof verification

type Verifier ¶

type Verifier struct{}

Verifier verifies ephemeral proofs of possession

func NewVerifier ¶

func NewVerifier() *Verifier

NewVerifier creates a new ephemeral proof verifier

func (*Verifier) VerifyBinding ¶

func (v *Verifier) VerifyBinding(ctx context.Context, proof *EphemeralProof, masterPublicKey crypto.PublicKey, expiresAt int64, purpose string) error

VerifyBinding verifies the binding signature on the ephemeral proof with expiry Step 1 of verification: Verify that the master key authorized the ephemeral key

func (*Verifier) VerifyProof ¶

func (v *Verifier) VerifyProof(ctx context.Context, proof *EphemeralProof, masterPublicKey crypto.PublicKey, expiresAt int64, purpose string, message []byte, signature []byte) error

VerifyProof performs complete two-step verification

func (*Verifier) VerifyRequestSignature ¶

func (v *Verifier) VerifyRequestSignature(ctx context.Context, proof *EphemeralProof, message []byte, signature []byte) error

VerifyRequestSignature verifies a signature created by the ephemeral key Step 2 of verification: Verify the per-request signature

Jump to

Keyboard shortcuts

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