--- title: Getting started description: Install the module, choose a curve, and learn the conventions — constructors, round-based protocols, serialization, and error handling — that every package in this library shares. sidebar: label: Getting started order: 1 icon: rocket --- ## Install ```bash go get github.com/sonr-io/crypto ``` Requires **Go 1.24.7 or newer**. Every package is imported under the module path `github.com/sonr-io/crypto/`: ```go import ( "github.com/sonr-io/crypto/core/curves" "github.com/sonr-io/crypto/sharing" "github.com/sonr-io/crypto/mpc" ) ``` There is no top-level façade package — the module root holds only a cross-package security test suite. Import the specific primitive you need. ## Pick a curve first Most constructors take a `*curves.Curve`. That single argument determines the group, the scalar field, and the serialization width of everything downstream, so it is the first decision you make: ```go curve := curves.K256() // secp256k1 — Bitcoin, Ethereum, Cosmos curve := curves.P256() // NIST P-256 — WebAuthn, FIDO2, TLS curve := curves.ED25519() // Ed25519 — Sonr identity keys ``` Some primitives need a **pairing-friendly** curve instead, because they rely on a bilinear map. BBS+ signatures and the accumulator both fall in this group and take a `*curves.PairingCurve`: ```go pairingCurve := curves.BLS12381(curves.BLS12381G1().NewGeneratorPoint()) ``` Passing a plain `*curves.Curve` where a `*curves.PairingCurve` is required will not compile, which is the intended guardrail. See [Curves](/foundations/curves) for the full catalog and interface reference. :::note Curve choice is rarely free to change later. A key generated on secp256k1 has no meaning on Ed25519, and stored shares, commitments, and serialized proofs are all curve-specific. ::: ## Conventions worth knowing ### Constructors validate, so check the error Constructors do real work — parameter validation, generator derivation, table precomputation — and return an `error` rather than panicking on bad input. A `NewShamir` with a threshold above its limit fails at construction, not at `Split` time: ```go scheme, err := sharing.NewShamir(3, 5, curves.K256()) if err != nil { return fmt.Errorf("invalid sharing parameters: %w", err) } ``` ### Two generations of API coexist The library carries an older, curve-specific API alongside the modern generic one. You will meet both in `go doc` output, and mixing them does not type-check: | Modern | Legacy | Used by | | --- | --- | --- | | `curves.Point`, `curves.Scalar` | `curves.EcPoint`, `curves.EcScalar` | `sharing/v1`, `dkg/gennaro` | | `sharing` | `sharing/v1` | `dkg/gennaro`, `dkg/gennaro2p` | | operates on `curves.Scalar` | operates on `[]byte` and `curves.Element` | — | Prefer the modern API for new code. Reach for the legacy layer only when a package you depend on forces it. [Foundations](/foundations) explains the split in detail. ### Multi-party protocols are explicit round objects Nothing in this library hides the network. A multi-party protocol is a stateful object whose methods are the rounds, and you move the messages between parties yourself. Two shapes appear: Each round is a distinct method. You call them in order and route the outputs — some broadcast to everyone, some point-to-point to one peer. Used by [`dkg/frost`](/threshold/dkg), [`dkg/gennaro`](/threshold/dkg), and [`ted25519/frost`](/threshold/threshold-ed25519). ```go bcast, p2p, err := participant.Round1(secret) // broadcast `bcast` to all; send p2p[peerID] privately to each peer ``` The protocol is a `protocol.Iterator`: you feed it the counterparty's message and it returns the next one, until it signals completion and you read `Result`. Used by [`tecdsa/dklsv1`](/threshold/threshold-ecdsa) and, wrapped up entirely, by [`mpc`](/identity/mpc-enclave). ```go msg, err := alice.Next(bobMsg) ``` Calling rounds out of order is an error, not undefined behavior — the objects track their own state. See [Protocol messages](/foundations/protocol) for the iterator contract. ### Serialization is per-type, not reflective Keys, shares, proofs, and signatures implement their own codecs — usually `MarshalBinary`/`UnmarshalBinary`, sometimes `MarshalJSON`/`UnmarshalJSON`, and in the DKG packages `Encode`/`Decode`. Use them rather than reflecting over struct fields with `encoding/gob` or a generic JSON marshal, because unexported field state and curve identity would be lost. Unmarshalling frequently needs to know the curve up front, since the wire bytes alone do not identify it. The idiom is to initialize an empty value on the right curve, then unmarshal into it: ```go sig := new(bbs.Signature).Init(pairingCurve) if err := sig.UnmarshalBinary(data); err != nil { return err } ``` ### Randomness is injected Anything that consumes entropy takes an `io.Reader`, so tests can be deterministic and production code is explicit about its source. Pass `crypto/rand.Reader` unless you have a specific reason not to: ```go shares, err := scheme.Split(secret, rand.Reader) ``` :::danger A deterministic or repeated reader in production is a key-recovery bug, not a performance optimization. Several protocols here — Ed25519 nonce generation especially — leak the signing key outright if the same randomness is used for two different messages. ::: ## Where to next The curve, point, and scalar model that the rest of the library is written against. Every importable package and the page that documents it. Stubs, known defects, and non-constant-time paths found while documenting the code. The highest-level entry point: threshold ECDSA as a single value.