Curves
Every named curve constructor in core/curves, the complete Point and Scalar method sets, pairing curves, and a map of the low-level native field arithmetic underneath.
core/curves is the catalog. It exposes one constructor per supported group, all of which hand back a *curves.Curve (or a *curves.PairingCurve for the pairing-friendly ones). Everything on this page was read out of go doc github.com/sonr-io/crypto/core/curves.
Reach for this page when you need to know which curve a package will accept, what a serialized point looks like on the wire, or which method on Point/Scalar does the thing you want. You do not need this page if you are just passing a curve through — curves.K256() and go.
Named curves
| Constructor | Name value |
Constant | Notes |
|---|---|---|---|
curves.K256() |
secp256k1 |
K256Name |
Bitcoin/Ethereum curve. 33-byte compressed points. |
curves.P256() |
P-256 |
P256Name |
NIST P-256 / secp256r1. |
curves.ED25519() |
ed25519 |
ED25519Name |
Edwards curve; 32-byte compressed points. |
curves.BLS12381G1() |
BLS12381G1 |
BLS12381G1Name |
G1 of BLS12-381; 48-byte compressed points. |
curves.BLS12381G2() |
BLS12381G2 |
BLS12381G2Name |
G2 of BLS12-381; 96-byte compressed points. |
curves.BLS12377G1() |
BLS12377G1 |
BLS12377G1Name |
G1 of BLS12-377 (gnark-crypto backed). |
curves.BLS12377G2() |
BLS12377G2 |
BLS12377G2Name |
G2 of BLS12-377. |
curves.PALLAS() |
pallas |
PallasName |
Pasta/Pallas curve. |
Two extra string constants exist for “the pairing construction, group unspecified”: BLS12831Name = "BLS12831" and BLS12377Name = "BLS12377".
Lookup by name
curve := curves.GetCurveByName(curves.K256Name)
if curve == nil {
return fmt.Errorf("unsupported curve")
}
GetCurveByName accepts every constant above. BLS12831Name and BLS12377Name both resolve to the G1 curve. Anything else returns nil.
Pairing curves
BBS+ and the accumulator need a pairing, so they take a *curves.PairingCurve — a different type from *curves.Curve. Passing curves.BLS12381G1() where a *PairingCurve is wanted will not compile.
type PairingCurve struct {
Scalar PairingScalar
PointG1 PairingPoint
PointG2 PairingPoint
GT Scalar
Name string
}
BLS12381(preferredPoint Point)?*PairingCurve
Builds the BLS12-381 pairing curve. The argument selects which group the curve's scalars prefer to project into — pass BLS12381G1().NewIdentityPoint() or the G2 equivalent.
*PairingCurveGetPairingCurveByName(name string)?*PairingCurve
Accepts BLS12381G1Name, BLS12381G2Name, or BLS12831Name. Returns nil for anything else.
*PairingCurveNewG1GeneratorPoint() / NewG2GeneratorPoint()?PairingPoint
Generators of G1 and G2.
PairingPointNewG1IdentityPoint() / NewG2IdentityPoint()?PairingPoint
Identity elements of G1 and G2.
PairingPointNewScalar()?PairingScalar
Zero scalar carrying the preferred-point projection.
PairingScalarScalarG1BaseMult(sc) / ScalarG2BaseMult(sc)?PairingPoint
Fixed-base multiplication in G1 or G2 respectively.
PairingPointPairingPoint and PairingScalar are extensions of the ordinary interfaces, so every Point/Scalar method is still available:
type PairingPoint interface {
Point
OtherGroup() PairingPoint // G1 <-> G2
Pairing(rhs PairingPoint) Scalar // e(self, rhs) as a GT element
MultiPairing(...PairingPoint) Scalar
}
type PairingScalar interface {
Scalar
SetPoint(p Point) PairingScalar
}
Note that Pairing returns a Scalar, not a distinct GT type — the target group element is modelled as a ScalarBls12381Gt. It supports the Scalar arithmetic surface (Mul, Add, Invert, Bytes) but it is a group element in the target group GT, not a field element mod the group order. Do not feed it back into ScalarBaseMult.
package main
import (
"crypto/rand"
"fmt"
"github.com/sonr-io/crypto/core/curves"
)
func main() {
pc := curves.BLS12381(curves.BLS12381G1().NewIdentityPoint())
s := pc.NewScalar().Random(rand.Reader)
g1 := pc.ScalarG1BaseMult(s) // s·G1
g2 := pc.NewG2GeneratorPoint()
gt := g1.Pairing(g2) // e(s·G1, G2)
fmt.Println(pc.Name, len(gt.Bytes()))
fmt.Println(g1.OtherGroup().CurveName()) // BLS12381G2
}
The Point interface
Twenty methods, no error returns except on the two deserializers and Set.
| Method | Signature | Purpose |
|---|---|---|
Random |
Random(reader io.Reader) Point |
Uniform random group element from the reader. |
Hash |
Hash(bytes []byte) Point |
Hash-to-curve. Deterministic; the domain separation tag is fixed inside each implementation. |
Identity |
Identity() Point |
Point at infinity. |
Generator |
Generator() Point |
Group generator. |
IsIdentity |
IsIdentity() bool |
Identity test. |
IsNegative |
IsNegative() bool |
Sign-of-y test, curve-specific convention. |
IsOnCurve |
IsOnCurve() bool |
Curve-equation check. |
Double |
Double() Point |
2·self. |
Scalar |
Scalar() Scalar |
A zero scalar of the matching field — a convenience constructor, not a discrete log. |
Neg |
Neg() Point |
-self. |
Add / Sub |
Add(rhs Point) Point |
Group law. |
Mul |
Mul(rhs Scalar) Point |
Variable-base scalar multiplication. |
Equal |
Equal(rhs Point) bool |
Group equality (compares in affine, handles differing projective representations). |
Set |
Set(x, y *big.Int) (Point, error) |
Build from affine coordinates; errors if off-curve. |
ToAffineCompressed |
ToAffineCompressed() []byte |
Canonical short encoding. |
ToAffineUncompressed |
ToAffineUncompressed() []byte |
Canonical long encoding. |
FromAffineCompressed |
FromAffineCompressed(bytes []byte) (Point, error) |
Inverse of the above. |
FromAffineUncompressed |
FromAffineUncompressed(bytes []byte) (Point, error) |
Inverse of the above. |
CurveName |
CurveName() string |
The Name string of the owning curve. |
SumOfProducts |
SumOfProducts(points []Point, scalars []Scalar) Point |
Multi-scalar multiplication. |
Serialization
Concrete point types also implement MarshalBinary/UnmarshalBinary, MarshalText/UnmarshalText, and MarshalJSON/UnmarshalJSON — that is how the higher layers (BBS+ proofs, accumulator witnesses, DKG round messages) persist points. The interface itself does not declare them, so if you need marshalling through the interface you type-assert to encoding.BinaryMarshaler.
SumOfProducts — multi-scalar multiplication
This is the MSM entry point, and the reason Bulletproofs and the accumulator are tractable. Call it on the curve’s point prototype; the receiver’s own value is ignored.
// Computes sum(scalars[i] · points[i]) using a 4-bit windowed bucket
// (Pippenger-style) multi-exponentiation, not n independent scalar mults.
result := curve.Point.SumOfProducts(points, scalars)
if result == nil {
return errors.New("length mismatch or foreign point/scalar type")
}
The Scalar interface
The doc comment describes it as “an element of the scalar field F_q of the elliptic curve construction” — that is, arithmetic is mod the group order, not the field characteristic.
| Group | Methods |
|---|---|
| Construction | Random(io.Reader), Hash([]byte), Zero(), One(), New(value int), Clone() |
| Predicates | IsZero(), IsOne(), IsOdd(), IsEven(), Cmp(rhs) int |
| Arithmetic | Add, Sub, Mul, Div, Neg, Double, Square, Cube, MulAdd(y, z) |
| Fallible arithmetic | Invert() (Scalar, error), Sqrt() (Scalar, error) |
| Conversion | SetBigInt(*big.Int) (Scalar, error), BigInt() *big.Int, Bytes() []byte, SetBytes([]byte) (Scalar, error), SetBytesWide([]byte) (Scalar, error) |
| Crossing over | Point() Point — the associated point type’s prototype |
Three behaviours that catch people:
Cmpreturns-2if the two scalars belong to different fields. It is the library’s only cross-curve mismatch signal.-1/0/1are the usual ordering.New(value int)takes a signed int and reduces it, soNew(-1)isq - 1. Sinceqis odd for these curves,New(-1).IsEven()istrue— the parity predicates describe the reduced representative, not the integer you passed.SetBytesdemands the exact width, whileSetBytesWidewants double the width and reduces. UseSetBytesWidewhen converting hash output into a scalar without modulo bias; useHashif you just want “bytes to scalar” done correctly.
// Uniform scalar from arbitrary input, no bias, no length constraints:
s := curve.Scalar.Hash([]byte("some transcript bytes"))
// Exact-width canonical decoding, e.g. reading a stored private key:
s, err := curve.Scalar.SetBytes(keyBytes) // len(keyBytes) must be exactly 32 for K256
The crypto/elliptic bridge
Some code (Go’s crypto/ecdsa, X.509 marshalling, the legacy EcPoint API) needs an elliptic.Curve. Several shims exist, and they are not interchangeable:
| Function | Returns | Backing implementation |
|---|---|---|
curves.K256Curve() |
*Koblitz256 |
native k256 field arithmetic |
curves.NistP256Curve() |
*NistP256 |
native p256 field arithmetic |
curves.SP256() |
elliptic.Curve |
github.com/dustinxie/ecc secp256k1 |
secp256k1.S256() |
*secp256k1.BitCurve |
the vendored Koblitz a=0 implementation |
curves.Pallas() |
*PallasCurve |
Pallas as an elliptic.Curve |
All of them satisfy elliptic.Curve. Curve.ToEllipticCurve() is the generic entry point:
ec, err := curves.K256().ToEllipticCurve() // -> *Koblitz256, nil
ec, err = curves.ED25519().ToEllipticCurve() // -> nil, "can't convert ed25519"
secp256k1.BitCurve additionally offers Marshal(x, y) []byte / Unmarshal(data) (x, y) and exposes its parameters as public fields (P, N, B, Gx, Gy, BitSize).
core/curves/native — the layer below
native is the constant-time-oriented field and point arithmetic that the modern Point/Scalar implementations sit on. It is a building block, and almost nothing outside core/curves should import it.
Fields are represented as four 64-bit limbs in the Montgomery domain:
const (
FieldBytes = 32 // canonical byte width
FieldLimbs = 4 // uint64 limbs
WideFieldBytes = 64 // width for bias-free reduction
MaxDstLen = 255
)
type Field struct {
Value [FieldLimbs]uint64
Params *FieldParams // R, R2, R3, Modulus, BiModulus
Arithmetic FieldArithmetic // per-curve limb routines
}
Field provides Add, Sub, Mul, Square, Double, Neg, Exp, Invert, Sqrt, CMove, Equal, Cmp, plus SetBytes/SetBytesWide/SetBigInt/SetLimbs/SetRaw and their Bytes/BigInt/Raw inverses. EllipticPoint provides Weierstrass point arithmetic in Jacobian coordinates (Add, Double, Generator, Hash, Equal, BigInt, GetX, GetY).
Which fields and groups are actually implemented:
| Package | Contents |
|---|---|
native/bls12381 |
G1, G2, Gt, the pairing Engine, Fq, Bls12381FqNew() |
native/k256 |
K256PointNew(); subpackages k256/fp (base field) and k256/fq (scalar field) |
native/p256 |
P256PointNew(); subpackages p256/fp and p256/fq |
native/pasta |
Pallas/Vesta point code; subpackages pasta/fp and pasta/fq |
Hash-to-curve hashers
EllipticPointHasher bundles a hash function with its expansion mode. It is what Point.Hash uses internally, and the only reason to construct one yourself is if you are calling native.ExpandMsgXmd / native.ExpandMsgXof or EllipticPoint.Hash directly.
| Constructor | Name() |
Type() |
|---|---|---|
EllipticPointHasherSha256() |
SHA-256 |
XMD |
EllipticPointHasherSha512() |
SHA-512 |
XMD |
EllipticPointHasherSha3256() |
SHA3-256 |
XMD |
EllipticPointHasherSha3384() |
SHA3-384 |
XMD |
EllipticPointHasherSha3512() |
SHA3-512 |
XMD |
EllipticPointHasherBlake2b() |
BLAKE2b |
XMD |
EllipticPointHasherShake128() |
SHAKE-128 |
XOF |
EllipticPointHasherShake256() |
SHAKE-256 |
XOF |
ExpandMsgXmd and ExpandMsgXof implement §5.4.1 and §5.4.2 of the CFRG hash-to-curve draft (the source links to draft-irtf-cfrg-hash-to-curve-13). Domain separation tags longer than MaxDstLen are hashed down using the OversizeDstSalt prefix H2C-OVERSIZE-DST-.
Legacy curve types
For completeness, since they show up in go doc next to everything above. These belong to the older API described on the foundations overview and are used by sharing/v1, dkg/gennaro, and ted25519 keygen.
EcPoint{Curve elliptic.Curve; X, Y *big.Int}withNewScalarBaseMult,PointFromBytesUncompressed,Add,Neg,ScalarMult,Bytes,Equals,IsOnCurve,IsIdentity,IsBasePoint,IsValid, and binary/JSON marshalling (plusEcPointJSONas the wire shape).Field/Element— genericbig.Intmodular arithmetic over an explicit modulus, withElementJSONfor serialization.EcScalar— a strategy interface (Add,Sub,Neg,Mul,Div,Hash,Random,IsValid,Bytes) implemented byNewK256Scalar(),NewP256Scalar(),NewEd25519Scalar(),NewBls12381Scalar(), andNewPallasScalar().EcdsaSignature,EcdsaVerify, andVerifyEcdsa(pk *EcPoint, hash []byte, sig *EcdsaSignature) bool— the verification hook used by threshold ECDSA. See ECDSA.Ed25519Order() *big.Int— the Ed25519 group order as abig.Int.