Skip to content

Commit

Permalink
no more ecdsa
Browse files Browse the repository at this point in the history
  • Loading branch information
mj850 committed Dec 8, 2024
1 parent 8d08733 commit f379d04
Show file tree
Hide file tree
Showing 14 changed files with 142 additions and 136 deletions.
18 changes: 16 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,27 +1,41 @@
module github.com/sei-protocol/sei-cryptography

go 1.21
go 1.22

toolchain go1.23.3

require (
github.com/bwesterb/go-ristretto v1.2.3
github.com/coinbase/kryptology v1.8.0
github.com/ethereum/go-ethereum v1.13.15
github.com/ethereum/go-ethereum v1.14.12
github.com/gtank/merlin v0.1.1
github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.27.0
)

require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect
github.com/holiman/uint256 v1.3.1 // indirect
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/supranational/blst v0.3.13 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.25.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)

replace github.com/coinbase/kryptology => github.com/sei-protocol/coinbase-kryptology v0.0.0-20241015231206-08f61b7965cd
28 changes: 28 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,38 @@ filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmG
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/bwesterb/go-ristretto v1.2.3 h1:1w53tCkGhCQ5djbat3+MH0BAQ5Kfgbt56UZQ/JMzngw=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M=
github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I=
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs=
github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI=
github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA=
github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
github.com/ethereum/go-ethereum v1.13.15 h1:U7sSGYGo4SPjP6iNIifNoyIAiNjrmQkz6EwQG+/EZWo=
github.com/ethereum/go-ethereum v1.13.15/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU=
github.com/ethereum/go-ethereum v1.14.12 h1:8hl57x77HSUo+cXExrURjU/w1VhL+ShCTJrTwcCQSe4=
github.com/ethereum/go-ethereum v1.14.12/go.mod h1:RAC2gVMWJ6FkxSPESfbshrcKpIokgQKsVKmAuqdekDY=
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A=
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is=
github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs=
github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
Expand All @@ -24,6 +43,9 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM=
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -34,12 +56,18 @@ github.com/sei-protocol/coinbase-kryptology v0.0.0-20241015231206-08f61b7965cd h
github.com/sei-protocol/coinbase-kryptology v0.0.0-20241015231206-08f61b7965cd/go.mod h1:vAKKp7/qgfMtPXMseamOlZMqK7BytjfOm0rFKWph5c4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk=
github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
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/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=
25 changes: 8 additions & 17 deletions pkg/encryption/aes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package encryption
import (
"crypto/aes"
"crypto/cipher"
"crypto/ecdsa"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
Expand All @@ -12,33 +11,25 @@ import (
"io"
"math/big"

"github.com/ethereum/go-ethereum/crypto/secp256k1"

"golang.org/x/crypto/hkdf"
)

// GenerateKey generates a new ECDSA private key using the secp256k1 curve.
func GenerateKey() (*ecdsa.PrivateKey, error) {
return ecdsa.GenerateKey(secp256k1.S256(), rand.Reader)
}

// GetAESKey derives a 32-byte AES key using the provided ECDSA private key and denomination string.
// It employs HKDF with SHA-256, using the ECDSA private key bytes and a SHA-256 hash of the denom as salt.
func GetAESKey(privKey ecdsa.PrivateKey, denom string) ([]byte, error) {
if privKey.D == nil {
return nil, fmt.Errorf("private key D is nil")
}
// GetAESKey derives a 32-byte AES key using the provided bytes and denomination string.
// The bytes can be anything, but we strongly suggest using something that is private to the use, such as the ecdas Private Key or a signed message.
// It employs HKDF with SHA-256, using the private key bytes and a SHA-256 hash of the denom as salt.
func GetAESKey(privateBytes []byte, denom string) ([]byte, error) {
if len(denom) == 0 {
return nil, fmt.Errorf("denom is empty")
}
// Convert the ECDSA private key to bytes
privKeyBytes := privKey.D.Bytes()
if len(privateBytes) == 0 {
return nil, fmt.Errorf("bytes is empty")
}

// Use a SHA-256 hash of the denom string as the salt
salt := sha256.Sum256([]byte(denom))

// Create an HKDF reader using SHA-256
hkdf := hkdf.New(sha256.New, privKeyBytes, salt[:], []byte("aes key derivation"))
hkdf := hkdf.New(sha256.New, privateBytes, salt[:], []byte("aes key derivation"))

// Allocate a 32-byte array for the AES key
aesKey := make([]byte, 32)
Expand Down
41 changes: 18 additions & 23 deletions pkg/encryption/aes_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package encryption

import (
"crypto/ecdsa"
"math/big"
"testing"
"time"

"github.com/stretchr/testify/require"
)
Expand All @@ -16,57 +16,57 @@ const (
func TestGetAESKey(t *testing.T) {
tests := []struct {
name string
privateKey *ecdsa.PrivateKey
privateKey []byte
denom string
expectEqual bool
anotherKey *ecdsa.PrivateKey
anotherKey []byte
anotherDenom string
}{
{
name: "Deterministic Key Generation",
privateKey: generateTestKey(t),
privateKey: generateTestKey(),
denom: TestDenom,
expectEqual: true,
},
{
name: "Different Denom (Salt) Generates Different Key",
privateKey: generateTestKey(t),
privateKey: generateTestKey(),
denom: TestDenom,
anotherDenom: TestDenom + "1",
expectEqual: false,
},
{
name: "Different Denom (Salt) of same length Generates Different Key",
privateKey: generateTestKey(t),
privateKey: generateTestKey(),
denom: TestDenom + "1",
anotherDenom: TestDenom + "2",
expectEqual: false,
},
{
name: "Different PrivateKey Generates Different Key",
privateKey: generateTestKey(t),
privateKey: generateTestKey(),
denom: TestDenom + "N",
anotherKey: generateTestKey(t),
anotherKey: generateTestKey(),
expectEqual: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
aesPK, err := GetAESKey(*tt.privateKey, tt.denom)
aesPK, err := GetAESKey(tt.privateKey, tt.denom)
require.Nil(t, err, "Should not have error here")

if tt.anotherKey != nil {
aesPKDiff, err := GetAESKey(*tt.anotherKey, tt.denom)
aesPKDiff, err := GetAESKey(tt.anotherKey, tt.denom)
require.Nil(t, err)
require.NotEqual(t, aesPK, aesPKDiff, "PK should be different for different private keys")
} else if tt.anotherDenom != "" {
aesPKDiff, err := GetAESKey(*tt.privateKey, tt.anotherDenom)
aesPKDiff, err := GetAESKey(tt.privateKey, tt.anotherDenom)
require.Nil(t, err)
require.NotEqual(t, aesPK, aesPKDiff, "PK should be different for different salts")
} else {

aesPKAgain, err := GetAESKey(*tt.privateKey, tt.denom)
aesPKAgain, err := GetAESKey(tt.privateKey, tt.denom)
require.Nil(t, err, "Should not have error here")
if tt.expectEqual {
require.Equal(t, aesPK, aesPKAgain, "PK should be deterministically generated")
Expand All @@ -80,15 +80,11 @@ func TestGetAESKey(t *testing.T) {

func TestGetAESKey_InvalidInput(t *testing.T) {
// Nil private key
_, err := GetAESKey(*new(ecdsa.PrivateKey), TestDenom)
_, err := GetAESKey([]byte{}, TestDenom)
require.Error(t, err, "Should return error for nil private key")

invalidPrivateKey := &ecdsa.PrivateKey{ /* Invalid key data */ }
_, err = GetAESKey(*invalidPrivateKey, TestDenom)
require.Error(t, err, "Should return error for invalid private key")

validPrivateKey := generateTestKey(t)
_, err = GetAESKey(*validPrivateKey, "")
validPrivateKey := generateTestKey()
_, err = GetAESKey(validPrivateKey, "")
require.Error(t, err, "Should not allow empty denom(salt)")
}

Expand Down Expand Up @@ -218,8 +214,7 @@ func TestDecryptAESGCM_InvalidCiphertext(t *testing.T) {
}

// Helper function to generate a test private key
func generateTestKey(t *testing.T) *ecdsa.PrivateKey {
privateKey, err := GenerateKey()
require.Nil(t, err, "Failed to generate private key")
return privateKey
func generateTestKey() []byte {
randomString := time.Now()
return []byte(randomString.String())
}
15 changes: 5 additions & 10 deletions pkg/encryption/elgamal/common.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package elgamal

import (
"crypto/ecdsa"
"crypto/sha256"
"io"

Expand All @@ -13,11 +12,12 @@ import (
const H_STRING = "gPt25pi0eDphSiXWu0BIeIvyVATCtwhslTqfqvNhW2c"

// KeyGen generates a new key pair for the Twisted ElGamal encryption scheme.
func (teg TwistedElGamal) KeyGen(privateKey ecdsa.PrivateKey, denom string) (*KeyPair, error) {
// The private key is derived from the provided privateBytes and denom string. Ensure that the privateBytes passed is not exposed.
func (teg TwistedElGamal) KeyGen(privateBytes []byte, denom string) (*KeyPair, error) {
// Fixed base point H
H := teg.GetH()

s, err := teg.getPrivateKey(privateKey, denom)
s, err := teg.getPrivateKeyFromBytes(privateBytes, denom)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -47,17 +47,12 @@ func (teg TwistedElGamal) GetH() curves.Point {
return teg.curve.Point.Hash(bytes)
}

// getPrivateKey derives a private key for the ElGamal cryptosystem.
// It takes an ECDSA private key and a denomination string to generate the scalar.
func (teg TwistedElGamal) getPrivateKey(privateKey ecdsa.PrivateKey, denom string) (curves.Scalar, error) {
// Convert the ECDSA private key to bytes
privKeyBytes := privateKey.D.Bytes()

func (teg TwistedElGamal) getPrivateKeyFromBytes(privateBytes []byte, denom string) (curves.Scalar, error) {
// Hash the denom to get a salt.
salt := sha256.Sum256([]byte(denom))

// Create an HKDF reader using SHA-256
hkdf := hkdf.New(sha256.New, privKeyBytes, salt[:], []byte("elgamal scalar derivation"))
hkdf := hkdf.New(sha256.New, privateBytes, salt[:], []byte("elgamal scalar derivation"))

// Generate 64 bytes of randomness from HKDF output
var scalarBytes [64]byte
Expand Down
Loading

0 comments on commit f379d04

Please sign in to comment.