Open-source project
Consensys-Incorporated/gnark-crypto avatar
Consensys-Incorporated/gnark-crypto

gnark-crypto generates its field arithmetic because Go generics are not fast enough

gnark-crypto provides elliptic curve and pairing-based cryptography on BN, BLS12, BLS24 and BW6 curves. It also provides various algorithms (algebra, crypto) of particular interest to zero knowledge proof systems

601 stars245 forksGoApache-2.0

At a glance

What is it?
gnark-crypto is the Go library behind gnark, providing pairing-friendly curves, small fields for STARK provers, signatures, hashes and polynomial commitments. Its performance comes from generating strongly typed field code instead of using interfaces or generics, and it ships without constant-time guarantees.
Who is it for?
gnark-crypto fits a Go team building zero knowledge proofs that needs pairing-friendly curves, KZG commitments or STARK-oriented small fields and wants the whole stack in one language. It is the wrong choice for a project that requires constant-time guarantees or side-channel resistance, since the documentation states plainly that neither is provided, and the wrong choice for a general purpose crypto need that a standard library or an audited component already covers.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The library behind gnark, not a general purpose crypto kit

gnark-crypto is described as providing efficient cryptographic primitives in Go, and the documentation states that it is actively developed and maintained by the team behind gnark, a framework to execute and verify algorithms in zero knowledge.

That framing matters, because the scope is narrower than the name suggests. The curve list is exactly what a zk prover needs: the pairing-friendly curves bn254, bls12-381, bls24-317, bls12-377 with bw6-761, and bls24-315 with bw6-633. Alongside them sit the non-pairing-friendly curves secp256r1, secp256k1, grumpkin and stark-curve.

A structural detail that shows up throughout is the companion curve pattern. Each pairing-friendly curve has a twistededwards companion sub-package for efficient elliptic curve cryptography inside zkSNARK circuits, and bls12-381 additionally has the bandersnatch companion curve. That pairing is not decoration: a proof system needs a circuit friendly curve and a native curve for the same security level, and the library ships them together so the two stay consistent.

The repository layout follows the same division. Top-level directories include ecc, algebra, field, hash, signature, kzg, accumulator, fiat-shamir, parallel and utils, so a user looking for a hash function finds it under hash rather than in one large package.

Small fields with hand written vector kernels for STARK provers

The small field section is the newest part of the catalogue and the part aimed at STARK-style provers rather than SNARKs.

KoalaBear and BabyBear are 31-bit fields with AVX-512 and NEON vector kernels, and both have degree-2, degree-4 and degree-6 extensions. MamaBear is a 49-bit field with AVX-512 IFMA kernels and a degree-3 extension. Goldilocks is a 64-bit field with a degree-2 extension.

Each field package ships the same supporting set: fft, poseidon2, sis for Ring-SIS, and iop for polynomial interactive oracle proofs. KoalaBear and MamaBear additionally offer vortex as an experimental commitment scheme.

The design choice in the extension fields is deliberate rather than accidental. A degree-6 extension of a 31-bit prime field is what a hash function such as Poseidon2 needs to operate over a larger domain without leaving the small prime field, and shipping the extension towers pre-built saves every STARK project from writing its own.

These are vectorised implementations rather than portable Go arithmetic, which is why the architecture note in the documentation matters. The packages are optimised for 64-bit architectures, amd64 with AVX-512 where available and arm64 with NEON, and tested on Linux, macOS and Windows, with pure Go fallbacks provided for all other platforms.

Signatures, hashes and the field generator that replaces generics

The signature and hashing layer is conventional in coverage and unconventional in implementation. ECDSA is available on every curve listed, and EdDSA on the twistededwards companion curves. The hash functions are MiMC using the Miyaguchi-Preneel construction, Poseidon2 as both permutation and compression function, and a hash registry of field-typed hash functions.

The interesting mechanism is the field generator. Most of the code, though not all of it, is generated from templates in internal/generator, and the generated code contains little to no interfaces and is strongly typed with a field produced by the gnark-crypto/field package. The documentation gives two reasons for that design.

The first is performance. gnark-crypto algorithms manipulate millions, if not billions, of field elements, and interface indirection at that scale, plus garbage collection indexing, takes a heavy toll on performance. The second is consistency: the aim is to derive mostly identical code for various moduli and curves with consistent APIs, and the documentation states that generics introduce significant performance overhead and are not yet suited for high performance computing.

That is the core engineering decision of the whole library. A generic BigInt-free field type in modern Go would be far more pleasant to write against, and the library trades that away on purpose. To regenerate the files you point the generator at the templates:

bash
go generate ./...

The entry point is internal/generator/main.go. The dependency list supports the story: mmcloughlin/addchain, leanovate/gopter for property based testing, consensys/bavard for template code generation, and bits-and-blooms/bitset.

Commitment schemes and the setup ceremony primitives around them

Polynomial commitments sit at the centre of any modern proof system, and gnark-crypto implements the main ones. KZG is there as kzg, alongside shplonk and fflonk for batched polynomial commitment openings, and Pedersen vector commitments under pedersen.

The multiparty setup ceremony primitives live in mpcsetup, referencing the MMPORPG work. This is the piece that matters for a deployment: a trusted setup for KZG requires contributions from multiple parties so that no single participant can forge proofs. The library gives you the primitives, not the ceremony.

Around those sit the building blocks a circuit needs. There is fft for Fast Fourier Transform, iop for polynomial IOP building blocks covering multilinear, quotients and ratios, permutation for permutation proofs, and fiatshamir as a transcript builder. Merkle tree accumulators are in merkletree, and the eisenstein and lattice packages handle Eisenstein integer arithmetic and lattice reduction for scalar decomposition.

The scalar decomposition detail is worth pausing on. It is the arithmetic step that lets a proof system work with a small prime field internally while still producing signatures in a larger curve group, and getting it wrong is a classic source of subtle bugs. Having it in the library rather than in each application is one of the clearer arguments for depending on gnark-crypto rather than assembling the pieces yourself.

Install, target Go 1.26, and mind the module path casing

The library is a normal Go module. Installation is:

bash
go get github.com/consensys/gnark-crypto

There is a gotcha the documentation calls out explicitly: if you use go modules, the module path is case sensitive, so use consensys and not ConsenSys. The go.mod file in the repository confirms the module path as github.com/consensys/gnark-crypto, and it declares go 1.26.8. The documentation says the library requires Go 1.26 or newer and that CI tests against Go 1.26.x, which is a high floor and one of the first things to check against your own toolchain policy.

The dependency set is modest for a crypto library. golang.org/x/crypto, x/sync and x/sys are present, along with testify for tests and yaml.v2. The go.mod file also declares a tool block with asmfmt and goimports, which is the modern Go convention for pinning formatting tools.

Getting a first useful thing out of the library means picking a curve and a scheme. For a proof system, the pairing side means bn254 or bls12-381 and a KZG commitment. For a STARK-style system, it means one of the small fields and the poseidon2 or vortex commitment. Which one you choose determines which part of the library you will actually use, and the rest stays a dependency.

No constant-time guarantees, and an audit picture that needs reading carefully

The warning section is the most consequential paragraph in the documentation, and any evaluation should start there. It states that gnark-crypto is not fully audited and is provided as-is, use at your own risk, and that in particular gnark-crypto makes no security guarantees such as constant time implementation or side-channel attack resistance.

That is a specific, technical gap, not a legal disclaimer. Constant-time execution is what stops an attacker from recovering a private key by timing how long a scalar multiplication takes. A library that says it makes no such guarantee is telling you that it has not been engineered for the setting where an attacker can measure your operations, which is a different threat model from a typical web service.

The audit situation needs reading carefully too. The features list links an audit report for bn254 and for bls12-381, pointing at a Kudelski audit of gnark-crypto dated 2022-10. The audits section points to a list of audits for gnark and gnark-crypto maintained in the gnark repository. Two audited curves out of a larger catalogue is a partial picture, and the note that the library is not fully audited applies to the whole package.

Bug reports are routed through the gnark Security Policy rather than the library's own repository, which tells you the two projects share a security process.

Release cadence, versioning and the Apache 2 licence

Upkeep is the healthiest part of this picture. The last push was on 2026-10-21, and the release history shows a steady sequence: v0.22.0 on 2026-10-02, v0.21.0 on 2026-08-10 and v0.20.1 on 2026-03-17.

Versioning follows SemVer, with the tags on the repository listing the available versions. The zero major version is the honest signal here: the API is not frozen, and a project consuming gnark-crypto should expect to read the CHANGELOG.md before bumping, because a v0.x release can break a signature that v1 promises not to.

The licence is Apache 2, stated in the documentation and in the LICENSE file at the repository root. That is a permissive licence with an explicit patent grant, which suits a company building a commercial product on top of it. The repository also carries the usual governance files: CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md, CITATION.bib, a.golangci.yml configuration, and a.chglog directory for the changelog tooling.

The citation requirement is a courtesy rather than an obligation: the documentation asks that a citation be used if you use the library in research, and provides a BibTeX entry for the most recent release with a Zenodo DOI and a version field pointing at v0.22.0.

Editorial conclusion

gnark-crypto fits a Go team building zero knowledge proofs that needs pairing-friendly curves, KZG commitments or STARK-oriented small fields and wants the whole stack in one language. It is the wrong choice for a project that requires constant-time guarantees or side-channel resistance, since the documentation states plainly that neither is provided, and the wrong choice for a general purpose crypto need that a standard library or an audited component already covers. Before adopting it, run go get github.com/consensys/gnark-crypto on Go 1.26 or newer, confirm your architecture takes the amd64 AVX-512 or arm64 NEON path, and read the warning section, because the audit situation differs from what the audit badges on individual curve packages suggest.

Frequently asked questions

Which curves does gnark-crypto support?

The pairing-friendly curves are bn254, bls12-381, bls24-317, bls12-377 with bw6-761, and bls24-315 with bw6-633. Additional non-pairing-friendly curves include secp256r1 (P-256), secp256k1, grumpkin and stark-curve, and each pairing-friendly curve has a twistededwards companion sub-package for use in zkSNARK circuits.

Does gnark-crypto provide constant-time implementations?

No. The documentation states explicitly that gnark-crypto is not fully audited and is provided as-is, and that it makes no security guarantees such as constant time implementation or side-channel attack resistance. Security bugs are reported through the gnark Security Policy.

How do I install gnark-crypto and which Go version do I need?

Run go get github.com/consensys/gnark-crypto. The library requires Go 1.26 or newer and CI tests against Go 1.26.x, and the module path is case sensitive, so use consensys rather than ConsenSys in your go.mod.

Official sources

  1. Consensys-Incorporated/gnark-crypto on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/consensys-incorporated-gnark-crypto.svg)](https://hysenlabs.com/projects/consensys-incorporated-gnark-crypto)

Was this useful?