Skip to content

Commit

Permalink
update some dependencies and use scalarbasemult for nist curves when …
Browse files Browse the repository at this point in the history
…posssible (#43)

* update some dependencies and use scalarbasemult for nist curves when posssible
* update to go 1.21 in workflow
* some linting
* add tests

Signed-off-by: bytemare <3641580+bytemare@users.noreply.github.com>
  • Loading branch information
bytemare committed Nov 27, 2023
1 parent 8b2734a commit 88de307
Show file tree
Hide file tree
Showing 14 changed files with 109 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ linters:
- contextcheck
- cyclop
- decorder
- depguard
#- depguard
- dogsled
- dupl
- durationcheck
Expand Down
3 changes: 2 additions & 1 deletion .github/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ update:
.PHONY: update-linters
update-linters:
@echo "Updating linters..."
@go install golang.org/x/tools/cmd/goimports@latest
@go install mvdan.cc/gofumpt@latest
@go install github.com/daixiang0/gci@latest
@go install github.com/segmentio/golines@latest
Expand All @@ -20,7 +21,7 @@ fmt:
@echo "Formatting ..."
@go mod tidy
@go fmt ../...
#@golines -m 120 -t 4 -w ../
@golines -m 120 -t 4 -w ../
@gofumpt -w -extra ../
@gci write -s Standard -s Default -s "Prefix($(shell go list -m))" ../
@fieldalignment -fix ../...
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
strategy:
fail-fast: false
matrix:
go: [ '1.20', '1.19' ]
go: [ '1.21', '1.20' ]
steps:
- name: Checkout repo
uses: actions/checkout@27135e314dd1818f797af1db9dae03a9f045786b # pin@master
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/snyk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
steps:
- uses: actions/checkout@61b9e3751b92087fd0b06925ba6dd6314e06f089 # pin@master
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/golang@806182742461562b67788a64410098c9d9b96adb # pin@master
uses: snyk/actions/golang@3e2680e8df93a24b52d119b1305fb7cedc60ceae # pin@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
module github.com/bytemare/crypto

go 1.20
go 1.21

require (
filippo.io/edwards25519 v1.0.0
filippo.io/nistec v0.0.2
filippo.io/nistec v0.0.3
github.com/bytemare/hash2curve v0.2.2
github.com/bytemare/secp256k1 v0.1.0
github.com/gtank/ristretto255 v0.1.2
)

require (
github.com/bytemare/hash v0.1.5 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/crypto v0.15.0 // indirect
golang.org/x/sys v0.14.0 // indirect
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
filippo.io/nistec v0.0.2 h1:/NIXTUimcHIh0E2DsYucHlICvUisgj28/XEnKSEptUs=
filippo.io/nistec v0.0.2/go.mod h1:84fxC9mi+MhC2AERXI4LSa8cmSVOzrFikg6hZ4IfCyw=
filippo.io/nistec v0.0.3 h1:h336Je2jRDZdBCLy2fLDUd9E2unG32JLwcJi0JQE9Cw=
filippo.io/nistec v0.0.3/go.mod h1:84fxC9mi+MhC2AERXI4LSa8cmSVOzrFikg6hZ4IfCyw=
github.com/bytemare/hash v0.1.5 h1:VW+X1YQ2b3chjRFHkRUnO42uclsQjXimdBCPOgIobR4=
github.com/bytemare/hash v0.1.5/go.mod h1:+QmWXTky/2b63ngqM5IYezGydn9UTFDhpX7mLYwYxCA=
github.com/bytemare/hash2curve v0.2.2 h1:zaGx6Z4/N4Pl9B7aGNtpbZ09vu1NNJGoJRRtHHl8oTw=
Expand All @@ -10,7 +10,7 @@ github.com/bytemare/secp256k1 v0.1.0 h1:kjVJ06GAHSa+EJ7Rz1LdVgE0DQWdvUT77tmcGf7e
github.com/bytemare/secp256k1 v0.1.0/go.mod h1:hzquMsr3GXhVcqL9qFX7GGjmcT5dlQldKrArd7tcXHE=
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.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
4 changes: 3 additions & 1 deletion groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func (g Group) init() {
case Ristretto255Sha512:
g.initGroup(ristretto.New)
case decaf448Shake256:
panic("Decaf is not yet supported")
panic("decaf is not yet supported")
case P256Sha256:
g.initGroup(nist.P256)
case P384Sha384:
Expand All @@ -169,6 +169,8 @@ func (g Group) init() {
g.initGroup(edwards25519.New)
case Secp256k1:
g.initGroup(secp256k1.New)
case maxID:
panic("group not recognized")
default:
panic("group not recognized")
}
Expand Down
17 changes: 15 additions & 2 deletions internal/nist/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,21 @@ func (e *Element[P]) Subtract(element internal.Element) internal.Element {
return e
}

func (e *Element[P]) isGenerator() bool {
b := e.new().SetGenerator().BytesCompressed()
return subtle.ConstantTimeCompare(b, e.Encode()) == 1
}

// Multiply sets the receiver to the scalar multiplication of the receiver with the given Scalar, and returns it.
func (e *Element[P]) Multiply(scalar internal.Scalar) internal.Element {
if _, err := e.p.ScalarMult(e.p, scalar.Encode()); err != nil {
panic(err)
if e.isGenerator() {
if _, err := e.p.ScalarBaseMult(scalar.Encode()); err != nil {
panic(err)
}
} else {
if _, err := e.p.ScalarMult(e.p, scalar.Encode()); err != nil {
panic(err)
}
}

return e
Expand Down Expand Up @@ -183,6 +194,8 @@ func encodeInfinity[Point nistECPoint[Point]](element *Element[Point]) []byte {
encodedLength = p384CompressedEncodingLength
case "P521":
encodedLength = p521CompressedEncodingLength
default:
panic("could not infer nist curve")
}

return make([]byte, encodedLength)
Expand Down
10 changes: 5 additions & 5 deletions internal/nist/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func initP256() {
nistec.NewP256Point,
)
p256.curve.setMapping(crypto.SHA256, "-10", 48)
p256.setScalarField("0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551")
setScalarField(&p256, "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551")
}

func initP384() {
Expand All @@ -185,7 +185,7 @@ func initP384() {
nistec.NewP384Point,
)
p384.curve.setMapping(crypto.SHA384, "-12", 72)
p384.setScalarField(
setScalarField(&p384,
"0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973",
)
}
Expand All @@ -202,13 +202,13 @@ func initP521() {
nistec.NewP521Point,
)
p521.curve.setMapping(crypto.SHA512, "-4", 98)
p521.setScalarField(
"0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" +
setScalarField(&p521,
"0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"+
"a51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
)
}

func (g *Group[Point]) setScalarField(order string) {
func setScalarField[Point nistECPoint[Point]](g *Group[Point], order string) {
prime := field.String2Int(order)
g.scalarField = field.NewField(&prime)
}
1 change: 1 addition & 0 deletions internal/nist/point.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package nist

type nistECPoint[point any] interface {
Add(p1, p2 point) point
Negate(p point) point
BytesCompressed() []byte
BytesX() ([]byte, error)
Double(p point) point
Expand Down
33 changes: 25 additions & 8 deletions tests/element_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,25 +96,30 @@ func TestElement_WrongInput(t *testing.T) {
t.Fatalf("Invalid group id %d", group.group)
}

if err := testPanic(errWrongGroup, internal.ErrCastElement, exec(element.Add, alternativeGroup.NewElement())); err != nil {
if err := testPanic(errWrongGroup, internal.ErrCastElement,
exec(element.Add, alternativeGroup.NewElement())); err != nil {
t.Fatal(err)
}

if err := testPanic(errWrongGroup, internal.ErrCastElement, exec(element.Subtract, alternativeGroup.NewElement())); err != nil {
if err := testPanic(errWrongGroup, internal.ErrCastElement,
exec(element.Subtract, alternativeGroup.NewElement())); err != nil {
t.Fatal(err)
}

if err := testPanic(errWrongGroup, internal.ErrCastElement, exec(element.Set, alternativeGroup.NewElement())); err != nil {
if err := testPanic(errWrongGroup, internal.ErrCastElement,
exec(element.Set, alternativeGroup.NewElement())); err != nil {
t.Fatal(err)
}

if err := testPanic(errWrongGroup, internal.ErrCastElement, equal(element.Equal, alternativeGroup.NewElement())); err != nil {
if err := testPanic(errWrongGroup, internal.ErrCastElement,
equal(element.Equal, alternativeGroup.NewElement())); err != nil {
t.Fatal(err)
}
})

// Specifically test Ristretto
if err := testPanic(errWrongGroup, internal.ErrCastScalar, mult(crypto.Ristretto255Sha512.NewElement().Multiply, crypto.P384Sha384.NewScalar())); err != nil {
if err := testPanic(errWrongGroup, internal.ErrCastScalar,
mult(crypto.Ristretto255Sha512.NewElement().Multiply, crypto.P384Sha384.NewScalar())); err != nil {
t.Fatal(err)
}
}
Expand All @@ -123,17 +128,29 @@ func TestElement_EncodedLength(t *testing.T) {
testAll(t, func(t2 *testing.T, group *testGroup) {
id := group.group.NewElement().Identity().Encode()
if len(id) != group.elementLength {
t.Fatalf("Encode() of the identity element is expected to return %d bytes, but returned %d bytes", group.elementLength, len(id))
t.Fatalf(
"Encode() of the identity element is expected to return %d bytes, but returned %d bytes",
group.elementLength,
len(id),
)
}

encodedID := hex.EncodeToString(id)
if encodedID != group.identity {
t.Fatalf("Encode() of the identity element is unexpected.\n\twant: %v\n\tgot : %v", group.identity, encodedID)
t.Fatalf(
"Encode() of the identity element is unexpected.\n\twant: %v\n\tgot : %v",
group.identity,
encodedID,
)
}

encodedElement := group.group.NewElement().Base().Multiply(group.group.NewScalar().Random()).Encode()
if len(encodedElement) != group.elementLength {
t.Fatalf("Encode() is expected to return %d bytes, but returned %d bytes", group.elementLength, encodedElement)
t.Fatalf(
"Encode() is expected to return %d bytes, but returned %d bytes",
group.elementLength,
encodedElement,
)
}
})
}
Expand Down
19 changes: 19 additions & 0 deletions tests/groups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package group_test

import (
"encoding/hex"
"errors"
"testing"

"github.com/bytemare/crypto"
Expand All @@ -26,6 +27,8 @@ func TestAvailability(t *testing.T) {
}

func TestNonAvailability(t *testing.T) {
errInvalidID := errors.New("invalid group identifier")

oob := crypto.Group(0)
if oob.Available() {
t.Errorf(consideredAvailableFmt, oob)
Expand All @@ -36,10 +39,26 @@ func TestNonAvailability(t *testing.T) {
t.Errorf(consideredAvailableFmt, d)
}

if err := testPanic("decaf availability", errInvalidID,
func() { _ = d.String() }); err != nil {
t.Fatal(err)
}

oob = crypto.Secp256k1 + 1
if oob.Available() {
t.Errorf(consideredAvailableFmt, oob)
}

if err := testPanic("oob availability", errInvalidID,
func() { _ = oob.String() }); err != nil {
t.Fatal(err)
}

oob++
if err := testPanic("oob availability", errInvalidID,
func() { _ = oob.String() }); err != nil {
t.Fatal(err)
}
}

func TestGroup_Base(t *testing.T) {
Expand Down
23 changes: 17 additions & 6 deletions tests/h2c_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"crypto/elliptic"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"math/big"
"os"
Expand Down Expand Up @@ -135,21 +136,31 @@ func (v *h2cVector) run(t *testing.T) {
switch v.Ciphersuite[len(v.Ciphersuite)-3:] {
case "RO_":
p := v.group.HashToGroup([]byte(v.Msg), []byte(v.Dst))

if hex.EncodeToString(p.Encode()) != expected {
t.Fatalf("Unexpected HashToGroup output.\n\tExpected %q\n\tgot \t%q", expected, hex.EncodeToString(p.Encode()))
if err := verifyEncoding(p, "HashToGroup", expected); err != nil {
t.Fatal(err)
}
case "NU_":
p := v.group.EncodeToGroup([]byte(v.Msg), []byte(v.Dst))

if hex.EncodeToString(p.Encode()) != expected {
t.Fatalf("Unexpected EncodeToGroup output.\n\tExpected %q\n\tgot %q", expected, hex.EncodeToString(p.Encode()))
if err := verifyEncoding(p, "EncodeToGroup", expected); err != nil {
t.Fatal(err)
}
default:
t.Fatal("ciphersuite not recognized")
}
}

func verifyEncoding(p *crypto.Element, function, expected string) error {
if hex.EncodeToString(p.Encode()) != expected {
return fmt.Errorf("Unexpected %s output.\n\tExpected %q\n\tgot %q",
function,
expected,
hex.EncodeToString(p.Encode()),
)
}

return nil
}

func (v *h2cVectors) runCiphersuite(t *testing.T) {
for _, vector := range v.Vectors {
vector.h2cVectors = v
Expand Down
11 changes: 9 additions & 2 deletions tests/scalar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,11 @@ func TestScalar_EncodedLength(t *testing.T) {
testAll(t, func(t2 *testing.T, group *testGroup) {
encodedScalar := group.group.NewScalar().Random().Encode()
if len(encodedScalar) != group.scalarLength {
t.Fatalf("Encode() is expected to return %d bytes, but returned %d bytes", group.scalarLength, encodedScalar)
t.Fatalf(
"Encode() is expected to return %d bytes, but returned %d bytes",
group.scalarLength,
encodedScalar,
)
}
})
}
Expand Down Expand Up @@ -368,7 +372,10 @@ func scalarTestPow(t *testing.T, g crypto.Group) {
}
res = s.Pow(exp)
if res.Equal(result) != 1 {
t.Fatal("expected 3**255 = 11F1B08E87EC42C5D83C3218FC83C41DCFD9F4428F4F92AF1AAA80AA46162B1F71E981273601F4AD1DD4709B5ACA650265A6AB")
t.Fatal(
"expected 3**255 = " +
"11F1B08E87EC42C5D83C3218FC83C41DCFD9F4428F4F92AF1AAA80AA46162B1F71E981273601F4AD1DD4709B5ACA650265A6AB",
)
}

// 7945232487465**513
Expand Down

0 comments on commit 88de307

Please sign in to comment.