Skip to content
This repository has been archived by the owner on Oct 3, 2024. It is now read-only.

Return groups for elements and scalars #66

Merged
merged 6 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
go: [ '1.22', '1.21' ]
go: [ '1.23.2', '1.22.8', '1.21.13' ]
uses: bytemare/workflows/.github/workflows/test-go.yml@f572ea606a74fe011e68a23c19f8d4f5daf58488
with:
command: cd .github && make test
Expand Down
5 changes: 5 additions & 0 deletions element.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ func newPoint(p internal.Element) *Element {
return &Element{Element: p}
}

// Group returns the group's Identifier.
func (e *Element) Group() Group {
return Group(e.Element.Group())
}

// Base sets the element to the group's base point a.k.a. canonical generator.
func (e *Element) Base() *Element {
return &Element{Element: e.Element.Base()}
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/bytemare/crypto

go 1.22.2
go 1.23.1

require (
filippo.io/edwards25519 v1.1.0
Expand All @@ -12,6 +12,6 @@ require (

require (
github.com/bytemare/hash v0.3.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/sys v0.25.0 // indirect
)
12 changes: 4 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ github.com/bytemare/secp256k1 v0.1.4 h1:6F1yP6RiUiWwH7AsGHsHktmHm24QcetdDcc39roB
github.com/bytemare/secp256k1 v0.1.4/go.mod h1:Pxb9miDs8PTt5mOktvvXiRflvLxI1wdxbXrc6IYsaho=
github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc=
github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
2 changes: 1 addition & 1 deletion groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const (
// Edwards25519Sha512 identifies the Edwards25519 group with SHA2-512 hash-to-group hashing.
Edwards25519Sha512

// Secp256k1 identifies the Secp256k1 group with SHA2-256 hash-to-group hashing.
// Secp256k1 identifies the SECp256k1 group with SHA2-256 hash-to-group hashing.
Secp256k1

maxID
Expand Down
5 changes: 5 additions & 0 deletions internal/edwards25519/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ func checkElement(element internal.Element) *Element {
return ec
}

// Group returns the group's Identifier.
func (e *Element) Group() byte {
return Identifier
}

// Base sets the element to the group's base point a.k.a. canonical generator.
func (e *Element) Base() internal.Element {
e.element.Set(ed.NewGeneratorPoint())
Expand Down
3 changes: 3 additions & 0 deletions internal/edwards25519/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import (
)

const (
// Identifier distinguishes this group from the others by a byte representation.
Identifier = byte(6)

canonicalEncodingLength = 32
orderPrime = "7237005577332262213973186563042994240857116359379907606001950938285454250989"
)
Expand Down
9 changes: 6 additions & 3 deletions internal/edwards25519/scalar.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ import (
"github.com/bytemare/crypto/internal"
)

const (
inputLength = 64
)
const inputLength = 64

var (
scZero Scalar
Expand Down Expand Up @@ -69,6 +67,11 @@ func (s *Scalar) set(scalar *ed.Scalar) {
s.scalar = *scalar
}

// Group returns the group's Identifier.
func (s *Scalar) Group() byte {
return Identifier
}

// Zero sets the scalar to 0, and returns it.
func (s *Scalar) Zero() internal.Scalar {
s.scalar = *ed.NewScalar()
Expand Down
3 changes: 3 additions & 0 deletions internal/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ package internal

// Element interface abstracts common operations on an Element in a prime-order Group.
type Element interface {
// Group returns the group's Identifier.
Group() byte

// Base sets the element to the group's base point a.k.a. canonical generator.
Base() Element

Expand Down
28 changes: 5 additions & 23 deletions internal/field/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ import (
"math/big"
)

var (
zero = big.NewInt(0)
one = big.NewInt(1)
)

// String2Int returns a big.Int representation of the integer s.
func String2Int(s string) big.Int {
if p, _ := new(big.Int).SetString(s, 0); p != nil {
Expand All @@ -35,6 +30,7 @@ type Field struct {
pMinus1div2 *big.Int // used in IsSquare
pMinus2 *big.Int // used for Field big.Int inversion
exp *big.Int
byteLen int
}

// NewField returns a newly instantiated field for the given prime order.
Expand All @@ -58,19 +54,10 @@ func NewField(prime *big.Int) Field {
pMinus1div2: pMinus1div2,
pMinus2: pMinus2,
exp: exp,
byteLen: (prime.BitLen() + 7) / 8,
}
}

// Zero returns the zero big.Int of the finite Field.
func (f Field) Zero() *big.Int {
return zero
}

// One returns one big.Int of the finite Field.
func (f Field) One() *big.Int {
return one
}

// Random sets res to a random big.Int in the Field.
func (f Field) Random(res *big.Int) *big.Int {
tmp, err := rand.Int(rand.Reader, f.order)
Expand All @@ -89,14 +76,9 @@ func (f Field) Order() *big.Int {
return f.order
}

// BitLen of the order.
func (f Field) BitLen() int {
return f.order.BitLen()
}

// AreEqual returns whether both elements are equal.
func (f Field) AreEqual(f1, f2 *big.Int) bool {
return f.IsZero(f.Sub(&big.Int{}, f1, f2))
// ByteLen returns the length of the field order in bytes.
func (f Field) ByteLen() int {
return f.byteLen
}

// IsZero returns whether the big.Int is equivalent to zero.
Expand Down
2 changes: 1 addition & 1 deletion internal/nist/curve.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ var (
func (c *curve[point]) affineToPoint(pxc, pyc *big.Int) point {
var decompressed []byte

byteLen := (c.field.BitLen() + 7) / 8
byteLen := c.field.ByteLen()
switch byteLen {
case 32:
decompressed = decompressed256[:]
Expand Down
19 changes: 18 additions & 1 deletion internal/nist/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"crypto/subtle"
"encoding/hex"
"fmt"
"reflect"

"filippo.io/nistec"

"github.com/bytemare/crypto/internal"
)
Expand Down Expand Up @@ -41,6 +44,20 @@
return ec
}

// Group returns the group's Identifier.
func (e *Element[Point]) Group() byte {
switch any(e.p).(type) {
case *nistec.P256Point:
return IdentifierP256
case *nistec.P384Point:
return IdentifierP384
case *nistec.P521Point:
return IdentifierP521
}

panic(fmt.Sprintf("invalid point type %v", reflect.TypeFor[Point]()))

Check warning on line 58 in internal/nist/element.go

View check run for this annotation

Codecov / codecov/patch

internal/nist/element.go#L58

Added line #L58 was not covered by tests
}

// Base sets the element to the group's base point a.k.a. canonical generator.
func (e *Element[Point]) Base() internal.Element {
e.p.SetGenerator()
Expand All @@ -67,7 +84,7 @@
return e
}

// negateSmall returns the compressed byte encoding of the negated element e with 5 allocs in 13000 ns/op.
// negateSmall returns the compressed byte encoding of the negated element e with 5 allocations in 13000 ns/op.
func (e *Element[Point]) negateSmall() []byte {
enc := e.p.BytesCompressed()

Expand Down
18 changes: 13 additions & 5 deletions internal/nist/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
// LICENSE file in the root directory of this source tree or at
// https://spdx.org/licenses/MIT.html

// Package nist allows simple and abstracted operations in the NIST P-256, P-384, and P-521 groups.
// Package nist allows simple and abstracted operations in the NIST P-256, P-384, and
// P-521 groups, wrapping filippo.io/nistec.
package nist

import (
Expand Down Expand Up @@ -39,6 +40,15 @@ const (

// E2CP521 represents the encode-to-curve string identifier for P521.
E2CP521 = "P521_XMD:SHA-512_SSWU_NU_"

// IdentifierP256 distinguishes this group from the others by a byte representation.
IdentifierP256 = byte(3)

// IdentifierP384 distinguishes this group from the others by a byte representation.
IdentifierP384 = byte(4)

// IdentifierP521 distinguishes this group from the others by a byte representation.
IdentifierP521 = byte(5)
)

// P256 returns the single instantiation of the P256 Group.
Expand Down Expand Up @@ -140,14 +150,12 @@ func (g Group[P]) Ciphersuite() string {

// ScalarLength returns the byte size of an encoded element.
func (g Group[P]) ScalarLength() int {
byteLen := (g.scalarField.BitLen() + 7) / 8
return byteLen
return g.scalarField.ByteLen()
}

// ElementLength returns the byte size of an encoded element.
func (g Group[P]) ElementLength() int {
byteLen := (g.curve.field.BitLen() + 7) / 8
return 1 + byteLen
return 1 + g.scalarField.ByteLen()
}

// Order returns the order of the canonical group of scalars.
Expand Down
31 changes: 20 additions & 11 deletions internal/nist/scalar.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
field: f,
scalar: big.Int{},
}
s.scalar.Set(s.field.Zero())

return s
}
Expand All @@ -48,15 +47,29 @@
return _sc
}

// Group returns the group's Identifier.
func (s *Scalar) Group() byte {
switch *s.field {
case p256.scalarField:
return IdentifierP256
case p384.scalarField:
return IdentifierP384
case p521.scalarField:
return IdentifierP521
}

panic(fmt.Sprintf("invalid field order for scalar %s", s.field.Order().String()))

Check warning on line 61 in internal/nist/scalar.go

View check run for this annotation

Codecov / codecov/patch

internal/nist/scalar.go#L61

Added line #L61 was not covered by tests
}

// Zero sets s to 0, and returns it.
func (s *Scalar) Zero() internal.Scalar {
s.scalar.Set(s.field.Zero())
s.scalar.Set(big.NewInt(0))
return s
}

// One sets s to 1, and returns it.
func (s *Scalar) One() internal.Scalar {
s.scalar.Set(s.field.One())
s.scalar.Set(big.NewInt(1))
return s
}

Expand Down Expand Up @@ -168,7 +181,7 @@

// IsZero returns whether the scalar is 0.
func (s *Scalar) IsZero() bool {
return s.field.AreEqual(&s.scalar, s.field.Zero())
return s.field.IsZero(&s.scalar)
}

// Set sets the receiver to the value of the argument scalar, and returns the receiver.
Expand All @@ -194,7 +207,7 @@
func (s *Scalar) UInt64() (uint64, error) {
b := s.Encode()
overflows := byte(0)
scalarLength := (s.field.BitLen() + 7) / 8
scalarLength := s.field.ByteLen()

for _, bx := range b[:scalarLength-8] {
overflows |= bx
Expand All @@ -217,20 +230,16 @@

// Encode returns the compressed byte encoding of the scalar.
func (s *Scalar) Encode() []byte {
byteLen := (s.field.BitLen() + 7) / 8
scalar := make([]byte, byteLen)

scalar := make([]byte, s.field.ByteLen())
return s.scalar.FillBytes(scalar)
}

// Decode sets the receiver to a decoding of the input data, and returns an error on failure.
func (s *Scalar) Decode(in []byte) error {
expectedLength := (s.field.BitLen() + 7) / 8

switch len(in) {
case 0:
return internal.ErrParamNilScalar
case expectedLength:
case s.field.ByteLen():
break
default:
return internal.ErrParamScalarLength
Expand Down
5 changes: 5 additions & 0 deletions internal/ristretto/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ func checkElement(element internal.Element) *Element {
return ec
}

// Group returns the group's Identifier.
func (e *Element) Group() byte {
return Identifier
}

// Base sets the element to the group's base point a.k.a. canonical generator.
func (e *Element) Base() internal.Element {
e.element.Base()
Expand Down
3 changes: 3 additions & 0 deletions internal/ristretto/ristretto.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import (
)

const (
// Identifier distinguishes this group from the others by a byte representation.
Identifier = byte(1)

inputLength = 64

// H2C represents the hash-to-curve string identifier.
Expand Down
5 changes: 5 additions & 0 deletions internal/ristretto/scalar.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ func (s *Scalar) set(scalar *ristretto255.Scalar) {
s.scalar = *ristretto255.NewScalar().Add(&scZero.scalar, scalar)
}

// Group returns the group's Identifier.
func (s *Scalar) Group() byte {
return Identifier
}

// Zero sets the scalar to 0, and returns it.
func (s *Scalar) Zero() internal.Scalar {
s.scalar.Zero()
Expand Down
3 changes: 3 additions & 0 deletions internal/scalar.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ package internal

// Scalar interface abstracts common operations on scalars in a prime-order Group.
type Scalar interface {
// Group returns the group's Identifier.
Group() byte

// Zero sets the scalar to 0, and returns it.
Zero() Scalar

Expand Down
Loading
Loading