Skip to content

Commit

Permalink
refactor: optimized
Browse files Browse the repository at this point in the history
  • Loading branch information
donutnomad committed Oct 16, 2024
1 parent 8d05387 commit f3d2c54
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 44 deletions.
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ go 1.23.0

require (
filippo.io/edwards25519 v1.1.0
github.com/decred/dcrd/dcrec/edwards/v2 v2.0.3
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0
github.com/samber/lo v1.47.0
)

require golang.org/x/text v0.19.0 // indirect
require (
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
golang.org/x/text v0.19.0 // indirect
)
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/edwards/v2 v2.0.3 h1:l/lhv2aJCUignzls81+wvga0TFlyoZx8QxRMQgXpZik=
github.com/decred/dcrd/dcrec/edwards/v2 v2.0.3/go.mod h1:AKpV6+wZ2MfPRJnTbQ6NPgWrKzbe9RCIlCF/FKzMtM8=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
48 changes: 24 additions & 24 deletions xcurve25519/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import (
"github.com/donutnomad/blockchain-alg/internal/hashs"
"github.com/donutnomad/blockchain-alg/xed25519"
"github.com/samber/lo"
"strconv"
)

type PublicKey []byte
type PublicKey = xed25519.PublicKey

const SignatureSize = 64

Expand All @@ -19,40 +18,36 @@ func Sign(priKey [32]byte, message []byte, random []byte) [64]byte {
priKey[0] &= 248
priKey[31] &= 127
priKey[31] |= 64

pubBs := scalarBaseMult(priKey)
signature := xed25519.SignFromScalar(priKey, pubBs, generateNonce(priKey, message, random), message, "", "")
return UniformSignature(pubBs[31], signature)
var ed25519PriKey = priKey
var ed25519PubKey = scalarBaseMult(ed25519PriKey)
var nonce = generateNonce(ed25519PriKey, message, random)
var signature = xed25519.SignFromScalar(ed25519PriKey, ed25519PubKey, nonce, message, "", "")
return UniformSignature(ed25519PubKey[31], signature)
}

func Verify(pubCurve25519 PublicKey, message, sig []byte) bool {
if l := len(pubCurve25519); l != ed25519.PublicKeySize {
panic("ed25519: bad public key length: " + strconv.Itoa(l))
}
if len(sig) != ed25519.SignatureSize {
return false
}
sig[63] &= 127
return ed25519.Verify(ed25519.PublicKey(pubCurve25519), message, sig)
func Verify(pubCurve25519 PublicKey, message []byte, sig [64]byte) bool {
return VerifyByEd25519(pubCurve25519.ToEd25519WithSig(sig[63]), message, sig)
}

// SignByEd25519 signs a message using an Ed25519 private key and converts the resulting signature to Curve25519 format.
func SignByEd25519(priEd25519 ed25519.PrivateKey, message []byte) Signature {
pubEd25519 := priEd25519[32:64]
signature := [64]byte(xed25519.Sign(priEd25519[:], message))
return UniformSignature(pubEd25519[31], signature)
signature := xed25519.Sign(priEd25519[:], message)
return UniformSignature(priEd25519[63], [64]byte(signature))
}

// VerifyByEd25519 verifies a message signature using an Ed25519 public key.
// It checks if the provided signature, which is in Curve25519 format, is valid for the given message.
func VerifyByEd25519(pubEd25519 ed25519.PublicKey, message []byte, sig Signature) bool {
if l := len(pubEd25519); l != ed25519.PublicKeySize {
panic("ed25519: bad public key length: " + strconv.Itoa(l))
}
func VerifyByEd25519(pubEd25519 xed25519.PublicKey, message []byte, sig Signature) bool {
orig := sig[63]
defer func() {
sig[63] = orig
}()
sig[63] &= 127
return ed25519.Verify(pubEd25519[:], message, sig[:])
}

func GenPubKey(pri [32]byte) [32]byte {
return scalarBaseMultMontgomery(pri)
}

var magic = [32]byte{0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}

// signs a message 'hash' using the given private scalar priv.
Expand All @@ -70,6 +65,11 @@ func scalarBaseMult(v [32]byte) [32]byte {
return [32]byte(new(edwards25519.Point).ScalarBaseMult(scalar).Bytes())
}

func scalarBaseMultMontgomery(v [32]byte) [32]byte {
scalar := lo.Must1(edwards25519.NewScalar().SetBytesWithClamping(v[:]))
return [32]byte(new(edwards25519.Point).ScalarBaseMult(scalar).BytesMontgomery())
}

func mod(v [64]byte) (*edwards25519.Scalar, [32]byte) {
scalar := lo.Must1(edwards25519.NewScalar().SetUniformBytes(v[:]))
return scalar, [32]byte(scalar.Bytes())
Expand Down
7 changes: 4 additions & 3 deletions xcurve25519/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"crypto/ed25519"
"crypto/rand"
"github.com/donutnomad/blockchain-alg/internal/utils"
"github.com/donutnomad/blockchain-alg/xed25519"
"github.com/samber/lo"
"io"
"testing"
Expand Down Expand Up @@ -33,10 +34,10 @@ func TestSign2(t *testing.T) {
message := []byte("data to be sign")
for i := 0; i < 10000; i++ {
var priBs = [32]byte(randBs(32))
var pub = scalarBaseMult(priBs)
var pub = GenPubKey(priBs)
var random = randBs(64)
var sig = Sign(priBs, message, random)
if !Verify(pub[:], message, sig[:]) {
if !Verify(pub, message, sig) {
panic("invalid signature")
}
}
Expand All @@ -47,7 +48,7 @@ func TestSignByEd25519Key(t *testing.T) {
for i := 0; i < 1; i++ {
publicKey, privateKey := lo.Must2(ed25519.GenerateKey(rand.Reader))
sig := SignByEd25519(privateKey, message)
if !VerifyByEd25519(publicKey[:], message, sig) {
if !VerifyByEd25519(xed25519.PublicKey(publicKey), message, sig) {
panic("invalid signature")
}
}
Expand Down
6 changes: 6 additions & 0 deletions xcurve25519/signature.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package xcurve25519

import "github.com/donutnomad/blockchain-alg/xed25519"

func UniformSignature(pubEndByte byte, signature [64]byte) Signature {
signature[63] &= 127 /*bbbbbbbb & 01111111 ==> clear first byte*/
signature[63] |= pubEndByte & 128 /*endByte & 10000000 ==> keep the first byte when it is 0*/
return signature
}

func ConvertEd25519PubKeyAndSig(pub xed25519.PublicKey, sig [64]byte) (pubCurve25519 PublicKey, _ Signature) {
return pub.ToEd25519(), UniformSignature(pub[len(pub)-1], sig)
}
14 changes: 0 additions & 14 deletions xed25519/edwards.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,6 @@ import (
"filippo.io/edwards25519/field"
)

type PublicKey [32]byte

// ToCurve25519 Ed25519's PublicKey to Curve25519
func (pub PublicKey) ToCurve25519() (PublicKey, error) {
return edwardsToMontgomery(pub)
}

// ToEd25519 Curve25519's PublicKey to Ed25519
func (pub PublicKey) ToEd25519() (out PublicKey) {
res := montgomeryToEdwards(pub)
copy(out[:], res)
return out
}

var one = new(field.Element).One()

func edwardsToMontgomery(publicKey [32]byte) (out [32]byte, _ error) {
Expand Down
50 changes: 50 additions & 0 deletions xed25519/pubkey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package xed25519

import (
"errors"
"github.com/decred/dcrd/dcrec/edwards/v2"
"github.com/donutnomad/blockchain-alg/xasn1"
)

var BadFormatPublicKeyErr = errors.New("bad format")

type PublicKey [32]byte

// ToCurve25519 Ed25519's PublicKey to Curve25519
func (pub PublicKey) ToCurve25519() (PublicKey, error) {
return edwardsToMontgomery(pub)
}

// ToEd25519 Curve25519's PublicKey to Ed25519
func (pub PublicKey) ToEd25519() (out PublicKey) {
res := montgomeryToEdwards(pub)
copy(out[:], res)
return out
}

// ToEd25519WithSig Curve25519's PublicKey to Ed25519 with last signature byte
func (pub PublicKey) ToEd25519WithSig(sigEndByte byte) PublicKey {
res := pub.ToEd25519()
res[31] &= 127
res[31] |= sigEndByte & 128
return res
}

func ParsePubKey(serialized [32]byte) (key PublicKey, err error) {
pubKey, err := edwards.ParsePubKey(serialized[:])
if err != nil {
return PublicKey{}, err
}
return PublicKey(pubKey.Serialize()), nil
}

func ParsePubKeyASN1(bs []byte) (key PublicKey, err error) {
serialized, err := xasn1.ParsePKIXPublicKey(bs)
if err != nil {
return PublicKey{}, err
}
if len(serialized) != 32 {
return PublicKey{}, BadFormatPublicKeyErr
}
return ParsePubKey([32]byte(serialized))
}
4 changes: 4 additions & 0 deletions xed25519/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func SignFromScalar(privateKey, publicKey, r [32]byte, message []byte, domPrefix
return signature
}

func Verify(publicKey PublicKey, message, sig []byte) bool {
return ed25519.Verify(publicKey[:], message, sig)
}

func must[T any](v T, err error) T {
if err != nil {
panic(err)
Expand Down
File renamed without changes.

0 comments on commit f3d2c54

Please sign in to comment.