Documentation
¶
Overview ¶
Package blindsig implements blind signature schemes.
Blind signatures allow a signer to sign a message without learning its content. Three schemes are provided:
RSA blind signatures (Chaum, 1983) using full-domain hashing. Non-interactive (1 round). 384-byte signatures. Not quantum-safe.
Schnorr blind signatures over Ed25519. Interactive (3 rounds). 64-byte signatures. Not quantum-safe, but efficient and compact.
Schnorr blind signatures over secp256k1 (BIP-340 compatible). Interactive (3 rounds). 64-byte signatures with x-only R. Not quantum-safe. Compatible with Bitcoin/Decred Schnorr.
BLNS23 lattice-based blind signatures (Beullens-Lyubashevsky-Nguyen-Seiler, ePrint 2023/077) using NTRU pre-image sampling and NIZK proofs. Interactive (2 rounds). ~50 KB signatures. Quantum-resistant.
BDHKE (Blind Diffie-Hellman Key Exchange) over Ed25519. Non-interactive (1 round). 32-byte tokens. Keyed verification (only the mint/signer can verify). Used in Cashu e-cash.
All schemes provide blindness: the signer cannot learn the message. RSA, Ed25519, secp256k1, and BLNS23 provide public verification and full unlinkability. BDHKE provides keyed verification (mint-only).
Index ¶
- Variables
- func BDHKEBlind(secret []byte) (*BDHKEBlindingState, *BDHKEBlindedMessage, error)
- func BDHKEVerify(token *BDHKEToken, sk *BDHKEMintPrivateKey) bool
- func BLNS23UserBlind(message []byte, pk *BLNS23PublicKey) (*BLNS23ClientState, *BLNS23BlindRequest, error)
- func BLNS23Verify(message []byte, sig *BLNS23Signature, pk *BLNS23PublicKey) bool
- func BlindMessage(message []byte, pubKey *rsa.PublicKey) (blinded *big.Int, blindingFactor *big.Int, err error)
- func Ed25519SignerRespond(state *Ed25519SignerState, challenge []byte, sk *Ed25519PrivateKey) ([]byte, error)
- func Ed25519Verify(message []byte, sig *Ed25519Signature, pk *Ed25519PublicKey) bool
- func GenerateBDHKEMintKey() (*BDHKEMintPrivateKey, *BDHKEMintPublicKey, error)
- func GenerateBLNS23Key(params *BLNS23Params) (*BLNS23PrivateKey, *BLNS23PublicKey, error)
- func GenerateBlindSigningKey(bits int) (*rsa.PrivateKey, error)
- func GenerateEd25519Key() (*Ed25519PrivateKey, *Ed25519PublicKey, error)
- func GenerateSecp256k1Key() (*Secp256k1PrivateKey, *Secp256k1PublicKey, error)
- func Secp256k1SignerRespond(state *Secp256k1SignerState, challenge []byte, sk *Secp256k1PrivateKey) ([]byte, error)
- func Secp256k1Verify(hash []byte, sig *Secp256k1Signature, pk *Secp256k1PublicKey) bool
- func SignBlinded(blinded *big.Int, privKey *rsa.PrivateKey) (*big.Int, error)
- func UnblindSignature(blindSig *big.Int, blindingFactor *big.Int, pubKey *rsa.PublicKey) (*big.Int, error)
- func VerifySignature(message []byte, signature *big.Int, pubKey *rsa.PublicKey) bool
- type BDHKEBlindSignature
- type BDHKEBlindedMessage
- type BDHKEBlindingState
- type BDHKEMintPrivateKey
- type BDHKEMintPublicKey
- type BDHKEToken
- type BLNS23BlindRequest
- type BLNS23BlindResponse
- type BLNS23ClientState
- type BLNS23Params
- type BLNS23PrivateKey
- type BLNS23PublicKey
- type BLNS23Signature
- type Ed25519ClientState
- type Ed25519PrivateKey
- type Ed25519PublicKey
- type Ed25519Signature
- type Ed25519SignerState
- type Secp256k1ClientState
- type Secp256k1PrivateKey
- type Secp256k1PublicKey
- type Secp256k1Signature
- type Secp256k1SignerState
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidSignature = errors.New("invalid blind signature")
ErrInvalidSignature is returned when a blind signature fails verification.
Functions ¶
func BDHKEBlind ¶ added in v0.1.1
func BDHKEBlind(secret []byte) (*BDHKEBlindingState, *BDHKEBlindedMessage, error)
BDHKEBlind blinds a secret for sending to the mint. Computes Y = hash_to_curve(secret), B' = Y + rG. Returns the blinded message and the blinding state needed for unblinding.
func BDHKEVerify ¶ added in v0.1.1
func BDHKEVerify(token *BDHKEToken, sk *BDHKEMintPrivateKey) bool
BDHKEVerify verifies a token against the mint's secret key. Checks that C == k·hash_to_curve(secret). This is keyed verification — only the mint (with secret key k) can verify.
func BLNS23UserBlind ¶
func BLNS23UserBlind(message []byte, pk *BLNS23PublicKey) (*BLNS23ClientState, *BLNS23BlindRequest, error)
BLNS23UserBlind creates a blinded commitment for the message (Round 1). Returns the client state (kept secret) and the blind request to send to the signer.
func BLNS23Verify ¶
func BLNS23Verify(message []byte, sig *BLNS23Signature, pk *BLNS23PublicKey) bool
BLNS23Verify verifies a BLNS23 blind signature on the given message.
func BlindMessage ¶
func BlindMessage(message []byte, pubKey *rsa.PublicKey) (blinded *big.Int, blindingFactor *big.Int, err error)
BlindMessage blinds a message so it can be sent to a signer without revealing its content. It returns the blinded value and the blinding factor needed to later unblind the signature.
func Ed25519SignerRespond ¶
func Ed25519SignerRespond(state *Ed25519SignerState, challenge []byte, sk *Ed25519PrivateKey) ([]byte, error)
Ed25519SignerRespond computes the signer's response (Round 3). s = k + e·a mod L.
func Ed25519Verify ¶
func Ed25519Verify(message []byte, sig *Ed25519Signature, pk *Ed25519PublicKey) bool
Ed25519Verify verifies a blind signature on the given message.
func GenerateBDHKEMintKey ¶ added in v0.1.1
func GenerateBDHKEMintKey() (*BDHKEMintPrivateKey, *BDHKEMintPublicKey, error)
GenerateBDHKEMintKey generates a mint key pair for BDHKE.
func GenerateBLNS23Key ¶
func GenerateBLNS23Key(params *BLNS23Params) (*BLNS23PrivateKey, *BLNS23PublicKey, error)
GenerateBLNS23Key generates a BLNS23 key pair.
func GenerateBlindSigningKey ¶
func GenerateBlindSigningKey(bits int) (*rsa.PrivateKey, error)
GenerateBlindSigningKey generates an RSA private key suitable for blind signing. bits must be at least 3072.
func GenerateEd25519Key ¶
func GenerateEd25519Key() (*Ed25519PrivateKey, *Ed25519PublicKey, error)
GenerateEd25519Key generates a key pair for blind signatures over Ed25519.
func GenerateSecp256k1Key ¶
func GenerateSecp256k1Key() (*Secp256k1PrivateKey, *Secp256k1PublicKey, error)
GenerateSecp256k1Key generates a key pair for blind signatures over secp256k1.
func Secp256k1SignerRespond ¶
func Secp256k1SignerRespond(state *Secp256k1SignerState, challenge []byte, sk *Secp256k1PrivateKey) ([]byte, error)
Secp256k1SignerRespond computes the signer's response (Round 3). BIP-340 convention: s = k - e·x (negating k if R.y is odd).
func Secp256k1Verify ¶
func Secp256k1Verify(hash []byte, sig *Secp256k1Signature, pk *Secp256k1PublicKey) bool
Secp256k1Verify verifies a blind secp256k1 signature. BIP-340 verification: R = s·G + e·P, check R.x == sig.R and R.y is even.
func SignBlinded ¶
SignBlinded signs a blinded message using the signer's private key. The signer never sees the original message.
Internally this uses CRT exponentiation with random timing blinding and Shamir fault detection.
Types ¶
type BDHKEBlindSignature ¶ added in v0.1.1
type BDHKEBlindSignature struct {
// contains filtered or unexported fields
}
BDHKEBlindSignature is the mint's blind signature C' = k·B'.
func BDHKESign ¶ added in v0.1.1
func BDHKESign(blinded *BDHKEBlindedMessage, sk *BDHKEMintPrivateKey) (*BDHKEBlindSignature, error)
BDHKESign creates a blind signature on a blinded message. The mint computes C' = k·B' without learning the secret.
func ParseBDHKEBlindSignature ¶ added in v0.1.1
func ParseBDHKEBlindSignature(data []byte) (*BDHKEBlindSignature, error)
ParseBDHKEBlindSignature parses a 32-byte compressed blind signature.
func (*BDHKEBlindSignature) Bytes ¶ added in v0.1.1
func (s *BDHKEBlindSignature) Bytes() []byte
Bytes serializes a blind signature to 32 bytes (compressed point).
type BDHKEBlindedMessage ¶ added in v0.1.1
type BDHKEBlindedMessage struct {
// contains filtered or unexported fields
}
BDHKEBlindedMessage is a blinded token B' = Y + rG sent to the mint.
func ParseBDHKEBlindedMessage ¶ added in v0.1.1
func ParseBDHKEBlindedMessage(data []byte) (*BDHKEBlindedMessage, error)
ParseBDHKEBlindedMessage parses a 32-byte compressed blinded message.
func (*BDHKEBlindedMessage) Bytes ¶ added in v0.1.1
func (b *BDHKEBlindedMessage) Bytes() []byte
Bytes serializes a blinded message to 32 bytes (compressed point).
type BDHKEBlindingState ¶ added in v0.1.1
type BDHKEBlindingState struct {
// contains filtered or unexported fields
}
BDHKEBlindingState holds the client's blinding factor for unblinding.
type BDHKEMintPrivateKey ¶ added in v0.1.1
type BDHKEMintPrivateKey struct {
// contains filtered or unexported fields
}
BDHKEMintPrivateKey is the mint's secret key k.
func (*BDHKEMintPrivateKey) PublicKey ¶ added in v0.1.1
func (sk *BDHKEMintPrivateKey) PublicKey() *BDHKEMintPublicKey
PublicKey returns the mint's public key.
type BDHKEMintPublicKey ¶ added in v0.1.1
type BDHKEMintPublicKey struct {
// contains filtered or unexported fields
}
BDHKEMintPublicKey is the mint's public key K = kG.
func ParseBDHKEMintPublicKey ¶ added in v0.1.1
func ParseBDHKEMintPublicKey(data []byte) (*BDHKEMintPublicKey, error)
ParseBDHKEMintPublicKey parses a 32-byte compressed public key.
func (*BDHKEMintPublicKey) Bytes ¶ added in v0.1.1
func (pk *BDHKEMintPublicKey) Bytes() []byte
Bytes returns the 32-byte compressed public key.
type BDHKEToken ¶ added in v0.1.1
type BDHKEToken struct {
Secret []byte // x — the user's secret
Cx, Cy *big.Int // C = k·Y where Y = hash_to_curve(x)
}
BDHKEToken is an unblinded token (x, C) where C = k·hash_to_curve(x).
func BDHKEUnblind ¶ added in v0.1.1
func BDHKEUnblind(secret []byte, blindSig *BDHKEBlindSignature, state *BDHKEBlindingState, mintPub *BDHKEMintPublicKey) (*BDHKEToken, error)
BDHKEUnblind removes the blinding to produce a valid token. C = C' - r·K where K is the mint's public key.
func (*BDHKEToken) Bytes ¶ added in v0.1.1
func (t *BDHKEToken) Bytes() []byte
Bytes serializes a token: 32-byte C point || secret.
type BLNS23BlindRequest ¶
BLNS23BlindRequest is the user's blinded commitment (Round 1 message).
type BLNS23BlindResponse ¶
type BLNS23BlindResponse struct {
S ring.BigPolyVec // short s with A·s = c
}
BLNS23BlindResponse is the signer's pre-image (Round 2 message).
func BLNS23SignerRespond ¶
func BLNS23SignerRespond(req *BLNS23BlindRequest, sk *BLNS23PrivateKey) (*BLNS23BlindResponse, error)
BLNS23SignerRespond computes the signer's response (Round 2). The signer finds a short pre-image s with A·s = c using the NTRU trapdoor.
type BLNS23ClientState ¶
type BLNS23ClientState struct {
R ring.BigPolyVec // random commitment vector (secret)
Rho []byte // G(r) hash
HTarget ring.BigPoly // H(ρ, μ) — the hash target
Message []byte // original message
}
BLNS23ClientState holds the user's ephemeral state between protocol rounds.
type BLNS23Params ¶
type BLNS23Params struct {
SigRing *ring.BigRing // R_q: d=512, q=7933
ProofRing *ring.BigRing // R_{q̂}: d=512, q̂=q·q2
Q *big.Int
Q2 *big.Int
QHat *big.Int
Sigma float64 // pre-image Gaussian std dev
BetaRSq *big.Int // L2² norm bound on r
BetaSSq *big.Int // L2² norm bound on s
ProofParams *tworing.Params // NIZK parameters
}
BLNS23Params holds the pre-computed scheme parameters.
func BLNS23DefaultParams ¶
func BLNS23DefaultParams() *BLNS23Params
BLNS23DefaultParams returns the default parameters from the paper (Table 2).
type BLNS23PrivateKey ¶
type BLNS23PrivateKey struct {
Params *BLNS23Params
F ring.BigPoly // NTRU secret f
G ring.BigPoly // NTRU secret g
H ring.BigPoly // public h = f^{-1}·g mod q
FInv ring.BigPoly // f^{-1} mod q
FF ring.BigPoly // F from SolveNTRU: fG - gF = q
GG ring.BigPoly // G from SolveNTRU
B ring.BigPolyVec // random blinding vector (same as in public key)
}
BLNS23PrivateKey is the signer's secret key.
func (*BLNS23PrivateKey) PublicKey ¶
func (sk *BLNS23PrivateKey) PublicKey() *BLNS23PublicKey
PublicKey returns the public key corresponding to this private key.
type BLNS23PublicKey ¶
type BLNS23PublicKey struct {
Params *BLNS23Params
A ring.BigPolyVec // [h, 1] — NTRU public key structure
B ring.BigPolyVec // random blinding vector (2 polynomials)
}
BLNS23PublicKey is the signer's public key.
type BLNS23Signature ¶
BLNS23Signature is the blind signature on a message.
func BLNS23BlindSign ¶
func BLNS23BlindSign(message []byte, sk *BLNS23PrivateKey, pk *BLNS23PublicKey) (*BLNS23Signature, error)
BLNS23BlindSign runs the full blind signing protocol locally (convenience).
func BLNS23UserFinalize ¶
func BLNS23UserFinalize(state *BLNS23ClientState, resp *BLNS23BlindResponse, pk *BLNS23PublicKey) (*BLNS23Signature, error)
BLNS23UserFinalize creates the blind signature from the signer's response (Round 3).
type Ed25519ClientState ¶
type Ed25519ClientState struct {
// contains filtered or unexported fields
}
Ed25519ClientState holds the client's state between protocol rounds.
func Ed25519ClientChallenge ¶
func Ed25519ClientChallenge(message, commitment []byte, pk *Ed25519PublicKey) (*Ed25519ClientState, []byte, error)
Ed25519ClientChallenge creates a blinded challenge from the signer's commitment (Round 2). Computes R' = R + αB + βA, e' = H(R' || A || msg), sends e = e' + β.
type Ed25519PrivateKey ¶
type Ed25519PrivateKey struct {
// contains filtered or unexported fields
}
Ed25519PrivateKey is a private key for blind signatures over Ed25519.
func (*Ed25519PrivateKey) PublicKey ¶
func (sk *Ed25519PrivateKey) PublicKey() *Ed25519PublicKey
PublicKey returns the public key for this private key.
type Ed25519PublicKey ¶
type Ed25519PublicKey struct {
// contains filtered or unexported fields
}
Ed25519PublicKey is a public key for blind signatures over Ed25519.
func ParseEd25519PublicKey ¶
func ParseEd25519PublicKey(data []byte) (*Ed25519PublicKey, error)
ParseEd25519PublicKey parses a 32-byte compressed public key.
func (*Ed25519PublicKey) Bytes ¶
func (pk *Ed25519PublicKey) Bytes() []byte
Bytes returns the 32-byte compressed encoding of the public key.
type Ed25519Signature ¶
Ed25519Signature is a blind signature (64 bytes: R' || s').
func Ed25519BlindSign ¶
func Ed25519BlindSign(message []byte, sk *Ed25519PrivateKey) (*Ed25519Signature, error)
Ed25519BlindSign runs the full blind protocol locally (convenience).
func Ed25519ClientUnblind ¶
func Ed25519ClientUnblind(state *Ed25519ClientState, response []byte, pk *Ed25519PublicKey) (*Ed25519Signature, error)
Ed25519ClientUnblind removes the blinding to produce the final signature. s' = s + α mod L. Signature = (R', s').
func ParseEd25519Signature ¶
func ParseEd25519Signature(data []byte) (*Ed25519Signature, error)
ParseEd25519Signature parses a 64-byte signature.
func (*Ed25519Signature) Bytes ¶
func (sig *Ed25519Signature) Bytes() []byte
Bytes returns the 64-byte encoding: R' (32 bytes) || s' (32 bytes).
type Ed25519SignerState ¶
type Ed25519SignerState struct {
// contains filtered or unexported fields
}
Ed25519SignerState holds the signer's ephemeral state for one signing session.
func Ed25519SignerCommit ¶
func Ed25519SignerCommit() (*Ed25519SignerState, []byte, error)
Ed25519SignerCommit starts a blind signing session (Round 1). The signer picks a random nonce k and returns the commitment R = kB (32 bytes).
type Secp256k1ClientState ¶
type Secp256k1ClientState struct {
// contains filtered or unexported fields
}
Secp256k1ClientState holds the client's state between protocol rounds.
func Secp256k1ClientChallenge ¶
func Secp256k1ClientChallenge(hash, commitment []byte, pk *Secp256k1PublicKey) (*Secp256k1ClientState, []byte, error)
Secp256k1ClientChallenge creates a blinded challenge from the signer's commitment (Round 2).
BIP-340 convention: s = k - e·x, verification R = s·G + e·P. Blinding: R' = R - αG - βP, e' = H(R'.x || msg), e = e' + β, s' = s - α. The client retries blinding if R'.y is odd (BIP-340 requires even y).
type Secp256k1PrivateKey ¶
type Secp256k1PrivateKey struct {
// contains filtered or unexported fields
}
Secp256k1PrivateKey is a private key for blind signatures over secp256k1.
func (*Secp256k1PrivateKey) PublicKey ¶
func (sk *Secp256k1PrivateKey) PublicKey() *Secp256k1PublicKey
PublicKey returns the public key for this private key.
type Secp256k1PublicKey ¶
type Secp256k1PublicKey struct {
// contains filtered or unexported fields
}
Secp256k1PublicKey is a public key for blind signatures over secp256k1.
func ParseSecp256k1PublicKey ¶
func ParseSecp256k1PublicKey(data []byte) (*Secp256k1PublicKey, error)
ParseSecp256k1PublicKey parses a 33-byte compressed public key.
func (*Secp256k1PublicKey) Bytes ¶
func (pk *Secp256k1PublicKey) Bytes() []byte
Bytes returns the 33-byte compressed encoding of the public key.
type Secp256k1Signature ¶
type Secp256k1Signature struct {
R secp256k1.FieldVal // R'.x (x-coordinate only)
S secp256k1.ModNScalar // s'
}
Secp256k1Signature is a blind signature (64 bytes: R'.x || s').
func ParseSecp256k1Signature ¶
func ParseSecp256k1Signature(data []byte) (*Secp256k1Signature, error)
ParseSecp256k1Signature parses a 64-byte signature.
func Secp256k1BlindSign ¶
func Secp256k1BlindSign(hash []byte, sk *Secp256k1PrivateKey) (*Secp256k1Signature, error)
Secp256k1BlindSign runs the full blind protocol locally (convenience). hash must be 32 bytes (pre-hashed message).
func Secp256k1ClientUnblind ¶
func Secp256k1ClientUnblind(state *Secp256k1ClientState, response []byte, pk *Secp256k1PublicKey) (*Secp256k1Signature, error)
Secp256k1ClientUnblind removes the blinding to produce the final signature. s' = s - α. Signature = (R'.x, s').
func (*Secp256k1Signature) Bytes ¶
func (sig *Secp256k1Signature) Bytes() []byte
Bytes returns the 64-byte encoding: R'.x (32 bytes) || s' (32 bytes).
type Secp256k1SignerState ¶
type Secp256k1SignerState struct {
R secp256k1.JacobianPoint // commitment R = kG
// contains filtered or unexported fields
}
Secp256k1SignerState holds the signer's ephemeral state for one signing session.
func Secp256k1SignerCommit ¶
func Secp256k1SignerCommit() (*Secp256k1SignerState, []byte, error)
Secp256k1SignerCommit starts a blind signing session (Round 1). The signer picks a random nonce k and returns the commitment R = kG (33 bytes compressed).