Skip to main content
import "github.com/populist/protocol/signer"

Interface

type Signer interface {
    Sign(ctx context.Context, payload []byte) ([]byte, error)
    PublicKeyDER() []byte
}
The Signer interface decouples the state machine from any particular key management backend. The state machine calls Sign exactly once per poll close, with the canonical tally payload:
SHA-256(VoteMerkleRoot ‖ VoterMerkleRoot ‖ TotalVotes ‖ sorted-counts)
The returned signature and PublicKeyDER() are stored in types.Tally for independent verification.

Managed signing posture

import "github.com/populist/protocol/kms"

signer, err := kms.NewSigner(ctx, os.Getenv("KMS_KEY_ID"))
  • Key type: ECC_NIST_P256 asymmetric key, suitable for the shared managed signing boundary and FIPS 140-3 validated module deployments
  • In the preferred deployment posture, AWS KMS is paired with Azure Managed HSM as the external or attested high-assurance boundary
  • Every Sign call is CloudTrail-audited — immutable signing history
  • Public key is cached at construction time; KMS is not called for PublicKeyDER()
  • kms.Signer.VerifyDER provides local verification without KMS (useful for auditors)
The KMS key ID is configured via app.Config.KMSKeyID. Leave it empty in local development; the state machine falls back to a non-production stub.

Bringing your own signer

Implement the two-method interface to plug in any backend:
type HardwareModuleSigner struct { ... }

func (h *HardwareModuleSigner) Sign(ctx context.Context, payload []byte) ([]byte, error) {
    // call your HSM, Vault, Azure Key Vault, etc.
}

func (h *HardwareModuleSigner) PublicKeyDER() []byte {
    return h.cachedDER
}
Then pass it to state.State via:
// state.State.signer is set in NewState; for custom signers,
// use the app package Config.KMSKeyID="" and inject via a deployment wrapper.
For deployment-specific signers, the deployment wrapper can create the state directly and inject the signer while preserving the same canonical tally payload format. The important invariant is not a specific cloud vendor; it is that canonical tally attestation happens at a managed signing boundary outside validator disk custody.