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

Commit

Permalink
Add Secp256k1 (#29)
Browse files Browse the repository at this point in the history
* Add Secp256k1

Signed-off-by: bytemare <[email protected]>
  • Loading branch information
bytemare authored Apr 16, 2023
1 parent de52f48 commit 7fe5a68
Show file tree
Hide file tree
Showing 49 changed files with 1,955 additions and 555 deletions.
5 changes: 0 additions & 5 deletions .github/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ test:
@echo "Running all tests ..."
@go test -v -vet=all ../...

# .PHONY: vectors
# vectors:
# @echo "Testing vectors ..."
# @go test -v ../tests/...

.PHONY: cover
cover:
@echo "Testing with coverage ..."
Expand Down
2 changes: 1 addition & 1 deletion .github/licence-header.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
SPDX-License-Identifier: MIT

Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.

This source code is licensed under the MIT license found in the
LICENSE file in the root directory of this source tree or at
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 Bytemare
Copyright (c) 2020-2023 Bytemare

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion element.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
Expand Down
8 changes: 7 additions & 1 deletion groups.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Group: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
Expand All @@ -21,6 +21,7 @@ import (
"github.com/bytemare/crypto/internal/edwards25519"
"github.com/bytemare/crypto/internal/nist"
"github.com/bytemare/crypto/internal/ristretto"
"github.com/bytemare/crypto/internal/secp256k1"
)

// Group identifies prime-order groups over elliptic curves with hash-to-group operations.
Expand All @@ -45,6 +46,9 @@ 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

maxID

dstfmt = "%s-V%02d-CS%02d-%s"
Expand Down Expand Up @@ -163,6 +167,8 @@ func (g Group) init() {
g.initGroup(nist.P521)
case Edwards25519Sha512:
g.initGroup(edwards25519.New)
case Secp256k1:
g.initGroup(secp256k1.New)
case maxID:
fallthrough
default:
Expand Down
2 changes: 1 addition & 1 deletion internal/edwards25519/element.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
Expand Down
2 changes: 1 addition & 1 deletion internal/edwards25519/group.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
Expand Down
2 changes: 1 addition & 1 deletion internal/edwards25519/map.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
Expand Down
2 changes: 1 addition & 1 deletion internal/edwards25519/scalar.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
Expand Down
2 changes: 1 addition & 1 deletion internal/element.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
Expand Down
217 changes: 217 additions & 0 deletions internal/field/field.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
// https://spdx.org/licenses/MIT.html

// Package field provides modular operations over very high integers.
package field

import (
"crypto/rand"
"fmt"
"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 {
return *p
}

panic("invalid string to convert")
}

// Field represents a Gaulois Field.
type Field struct {
order big.Int
pMinus1div2 big.Int // used in IsSquare
pMinus2 big.Int // used for Field big.Int inversion
exp big.Int
}

// NewField returns a newly instantiated field for the given prime order.
func NewField(prime *big.Int) Field {
// pMinus1div2 is used to determine whether a big Int is a quadratic square.
pMinus1div2 := big.NewInt(1)
pMinus1div2.Sub(prime, pMinus1div2)
pMinus1div2.Rsh(pMinus1div2, 1)

// pMinus2 is used for modular inversion.
pMinus2 := big.NewInt(2)
pMinus2.Sub(prime, pMinus2)

// precompute e = (p + 1) / 4
exp := big.NewInt(1)
exp.Add(prime, exp)
exp.Rsh(exp, 2)

return Field{
order: *prime,
pMinus1div2: *pMinus1div2,
pMinus2: *pMinus2,
exp: *exp,
}
}

// 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)
if err != nil {
// We can as well not panic and try again in a loop
panic(fmt.Errorf("unexpected error in generating random bytes : %w", err))
}

res.Set(tmp)

return res
}

// Order returns the size of the Field.
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))
}

// IsZero returns whether the big.Int is equivalent to zero.
func (f Field) IsZero(e *big.Int) bool {
return e.Sign() == 0
}

// Inv sets res to the modular inverse of x mod field order.
func (f Field) Inv(res, x *big.Int) {
f.Exponent(res, x, &f.pMinus2)
}

// LegendreSymbol applies the Legendre symbole on (a/p) and returns either {-1, 0, 1} mod field order.
func (f Field) LegendreSymbol(a *big.Int) *big.Int {
var res big.Int
return f.Exponent(&res, a, &f.pMinus1div2)
}

// Exponent returns x^n mod field order.
func (f Field) Exponent(res, x, n *big.Int) *big.Int {
return res.Exp(x, n, &f.order)
}

// IsSquare returns whether e is a quadratic square.
func (f Field) IsSquare(e *big.Int) bool {
return f.AreEqual(f.LegendreSymbol(e), f.One())
}

// IsEqual returns whether the two fields have the same order.
func (f Field) IsEqual(f2 *Field) bool {
return f.order.Cmp(&f2.order) == 0
}

// Mod reduces x modulo the field order.
func (f Field) Mod(x *big.Int) *big.Int {
return x.Mod(x, &f.order)
}

// Neg sets res to the -x modulo the field order.
func (f Field) Neg(res, x *big.Int) *big.Int {
return f.Mod(res.Neg(x))
}

// CondNeg sets res to -x if cond == 1.
func (f Field) CondNeg(res, x *big.Int, cond int) {
var neg, cpy big.Int
cpy.Set(x)
f.Neg(&neg, x)

if cond == 1 {
res.Set(&neg)
} else {
res.Set(&cpy)
}
}

// Add sets res to x + y modulo the field order.
func (f Field) Add(res, x, y *big.Int) {
f.Mod(res.Add(x, y))
}

// Sub sets res to x - y modulo the field order.
func (f Field) Sub(res, x, y *big.Int) *big.Int {
return f.Mod(res.Sub(x, y))
}

// Lsh sets res to the left shift of n bits on x modulo the field order.
func (f Field) Lsh(res, x *big.Int, n uint) {
f.Mod(res.Lsh(x, n))
}

// Mul sets res to the multiplication of x and y modulo the field order.
func (f Field) Mul(res, x, y *big.Int) {
f.Mod(res.Mul(x, y))
}

// Square sets res to the square of x modulo the field order.
func (f Field) Square(res, x *big.Int) {
f.Mod(res.Mul(x, x))
}

// CondMov sets res to y if b true, and to x otherwise.
func (f Field) CondMov(res, x, y *big.Int, b bool) {
if b {
res.Set(y)
} else {
res.Set(x)
}
}

// Sgn0 returns the first bit in the big-endian representation.
func (f Field) Sgn0(x *big.Int) int {
return int(x.Bit(0))
}

func (f Field) sqrt3mod4(res, e *big.Int) *big.Int {
return f.Exponent(res, e, &f.exp)
}

// SquareRoot sets res to a square root of e mod the field's order, if such a square root exists.
func (f Field) SquareRoot(res, e *big.Int) *big.Int {
return f.sqrt3mod4(res, e)
}

// SqrtRatio res result to the square root of (e/v), and indicates whether (e/v) is a square.
func (f Field) SqrtRatio(res, zMapConstant, e, v *big.Int) bool {
f.Inv(res, v)
f.Mul(res, res, e)

square := f.IsSquare(res)
if !square {
f.Mul(res, res, zMapConstant)
}

f.SquareRoot(res, res)

return square
}
2 changes: 1 addition & 1 deletion internal/group.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
Expand Down
52 changes: 52 additions & 0 deletions internal/h2c/sswu.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C)2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
// https://spdx.org/licenses/MIT.html

// Package h2c provides hash-to-curve primitives and mapping.
package h2c

import (
"math/big"

"github.com/bytemare/crypto/internal/field"
)

// MapToCurveSSWU implements the Simplified SWU method for Weierstrass curves for any base field.
func MapToCurveSSWU(f *field.Field, a, b, z, fe *big.Int) (x, y *big.Int) {
var tv1, tv2, tv3, tv4, tv5, tv6, _y1, _px, _py big.Int

f.Square(&tv1, fe) // 1. tv1 = u^2
f.Mul(&tv1, z, &tv1) // 2. tv1 = Z * tv1
f.Square(&tv2, &tv1) // 3. tv2 = tv1^2
f.Add(&tv2, &tv2, &tv1) // 4. tv2 = tv2 + tv1
f.Add(&tv3, &tv2, f.One()) // 5. tv3 = tv2 + 1
f.Mul(&tv3, b, &tv3) // 6. tv3 = B * tv3
f.CondMov(&tv4, z,
f.Neg(&big.Int{}, &tv2),
!f.IsZero(&tv2)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
f.Mul(&tv4, a, &tv4) // 8. tv4 = A * tv4
f.Square(&tv2, &tv3) // 9. tv2 = tv3^2
f.Square(&tv6, &tv4) // 10. tv6 = tv4^2
f.Mul(&tv5, a, &tv6) // 11. tv5 = A * tv6
f.Add(&tv2, &tv2, &tv5) // 12. tv2 = tv2 + tv5
f.Mul(&tv2, &tv2, &tv3) // 13. tv2 = tv2 * tv3
f.Mul(&tv6, &tv6, &tv4) // 14. tv6 = tv6 * tv4
f.Mul(&tv5, b, &tv6) // 15. tv5 = B * tv6
f.Add(&tv2, &tv2, &tv5) // 16. tv2 = tv2 + tv5
f.Mul(&_px, &tv1, &tv3) // 17. x = tv1 * tv3
isGx1Square := f.SqrtRatio(&_y1, z, &tv2, &tv6) // 18. isGx1Square, y1 = sqrt_ratio(tv2, tv6)
f.Mul(&_py, &tv1, fe) // 19. y = tv1 * u
f.Mul(&_py, &_py, &_y1) // 20. y = y * y1
f.CondMov(&_px, &_px, &tv3, isGx1Square) // 21. x = CMOV(x, tv3, isGx1Square)
f.CondMov(&_py, &_py, &_y1, isGx1Square) // 22. y = CMOV(y, y1, isGx1Square)
e1 := f.Sgn0(fe) == f.Sgn0(&_py) // 23. e1 = sgn0(u) == sgn0(y)
f.CondMov(&_py, f.Neg(&big.Int{}, &_py), &_py, e1) // 24. y = CMOV(-y, y, e1)
f.Inv(&tv4, &tv4) // 25. 1 / tv4
f.Mul(&_px, &_px, &tv4) // 26. x = x / tv4

return &_px, &_py
}
2 changes: 1 addition & 1 deletion internal/misc.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved.
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree or at
Expand Down
Loading

0 comments on commit 7fe5a68

Please sign in to comment.