Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Darc ECDSA #2484

Open
wants to merge 11 commits into
base: darc_identity_test
Choose a base branch
from
3 changes: 1 addition & 2 deletions calypso/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package calypso

import (
"encoding/binary"
"go.dedis.ch/kyber/v3/util/key"
"testing"
"time"

"go.dedis.ch/kyber/v3/sign/schnorr"
"go.dedis.ch/kyber/v3/util/key"

"github.com/stretchr/testify/require"
"go.dedis.ch/cothority/v3"
Expand Down Expand Up @@ -167,7 +167,6 @@ func TestClient_Calypso(t *testing.T) {
_, err = calypsoClient.SpawnDarc(admin, adminCt, gDarc, *darc2, 10)
adminCt++
require.NoError(t, err)

//Create a secret key
key1 := []byte("secret key 1")
//Create a Write instance
Expand Down
1 change: 1 addition & 0 deletions calypso/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"go.dedis.ch/cothority/v3"
"go.dedis.ch/cothority/v3/byzcoin"
"go.dedis.ch/cothority/v3/darc"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/onet/v3"
"go.dedis.ch/onet/v3/log"
"go.dedis.ch/onet/v3/network"
Expand Down
2 changes: 1 addition & 1 deletion calypso/protocol/ocs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ func DecodeKey(suite kyber.Group, X kyber.Point, Cs []kyber.Point, XhatEnc kyber
}
key = append(key, keyPart...)
}
return
return
}

// starts a new service. No function needed.
Expand Down
3 changes: 2 additions & 1 deletion calypso/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"crypto/rand"
"crypto/sha256"
"fmt"
"io"

"go.dedis.ch/cothority/v3"
"go.dedis.ch/cothority/v3/byzcoin"
"go.dedis.ch/cothority/v3/darc"
Expand All @@ -15,7 +17,6 @@ import (
"go.dedis.ch/kyber/v3/xof/keccak"
"go.dedis.ch/onet/v3/network"
"golang.org/x/xerrors"
"io"
)

func init() {
Expand Down
69 changes: 69 additions & 0 deletions darc/darc.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ package darc
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
Expand Down Expand Up @@ -773,6 +774,8 @@ func (s Signer) Type() int {
return 3
case s.EvmContract != nil:
return 4
case s.ECDSA != nil:
return 5
default:
return -1
}
Expand All @@ -790,6 +793,8 @@ func (s Signer) Identity() Identity {
return NewIdentityProxy(s.Proxy)
case 4:
return NewIdentityEvmContract(s.EvmContract)
case 5:
return NewIdentityECDSA(s.ECDSA.PublicKey)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and everywhere else: we should call the ECDSA identity MPCECDSA to indicate we're doing something special..

default:
return Identity{}
}
Expand Down Expand Up @@ -863,6 +868,8 @@ func (id Identity) Type() int {
return 3
case id.EvmContract != nil:
return 4
case id.ECDSA != nil:
return 5
}
return -1
}
Expand Down Expand Up @@ -937,6 +944,8 @@ func (id Identity) Verify(msg, sig []byte) error {
return id.Proxy.Verify(msg, sig)
case 4:
return id.EvmContract.Verify(msg, sig)
case 5:
return id.ECDSA.Verify(msg, sig)
default:
return errors.New("unknown identity")
}
Expand Down Expand Up @@ -964,6 +973,10 @@ func (id Identity) GetPublicBytes() []byte {
return buf
case 4:
return id.EvmContract.Address[:]
case 5:
buf := elliptic.Marshal(id.ECDSA.PublicKey.Curve, id.ECDSA.PublicKey.X, id.ECDSA.PublicKey.Y)
//TODO: add error check here?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of error check can you do here? The GetPublicBytes doesn't return an error, so all you could do is panic.

return buf
default:
return nil
}
Expand Down Expand Up @@ -1012,6 +1025,25 @@ func NewIdentityX509EC(public []byte) Identity {
}
}

// NewIdentityECDSA creates a new ECDSA identity struct given a public key
func NewIdentityECDSA(publicKey ecdsa.PublicKey) Identity {
return Identity{
ECDSA: &IdentityECDSA{
PublicKey: publicKey,
},
}
}

//TODO make calls to tsm available
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please resolve all TODOs.

From what I understand, the Verify method will not call to the TSM, no?

func (ide IdentityECDSA) Verify(msg []byte, sig []byte) error {
hashMsg := sha256.Sum256(msg)
valid := ecdsa.VerifyASN1(&ide.PublicKey, hashMsg[:], sig)
if !valid {
return errors.New("Signature failed to verify")
}
return nil
}

// NewIdentityProxy creates a new OpenID Connect identity struct.
func NewIdentityProxy(s *SignerProxy) Identity {
return Identity{
Expand Down Expand Up @@ -1120,6 +1152,8 @@ func ParseIdentity(in string) (Identity, error) {
return parseIDProxy(fields[1])
case "evm_contract":
return parseIDEvmContract(fields[1])
case "secp256k1":
return parseIDECDSA(fields[1])
default:
return Identity{}, fmt.Errorf("unknown identity type %v", fields[0])
}
Expand All @@ -1142,6 +1176,25 @@ func parseIDX509ec(in string) (Identity, error) {
return Identity{X509EC: &IdentityX509EC{Public: id}}, nil
}

//necessary function, needs to be refactored only supports elliptic.P256 curve
//needs to be tested Unmarshal might not work
Comment on lines +1204 to +1205
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//necessary function, needs to be refactored only supports elliptic.P256 curve
//needs to be tested Unmarshal might not work
// Tries to convert a string into a sec256k1 point.
// TODO: needs to be tested Unmarshal might not work

func parseIDECDSA(in string) (Identity, error) {
id := make([]byte, hex.DecodedLen(len(in)))
_, err := hex.Decode(id, []byte(in))
Comment on lines +1207 to +1208
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
id := make([]byte, hex.DecodedLen(len(in)))
_, err := hex.Decode(id, []byte(in))
buf, err := hex.DecodeString(in)
if err != nil {
return xerrors.Errorf("couldn't parse hex-string: %v", err)
}


x, y := elliptic.Unmarshal(elliptic.P256(), id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
x, y := elliptic.Unmarshal(elliptic.P256(), id)
x, y := elliptic.Unmarshal(elliptic.P256(), buf)


pubkey := ecdsa.PublicKey{
Curve: elliptic.P256(),
X: x,
Y: y,
}
if err != nil {
return Identity{}, err
}
Comment on lines +1217 to +1219
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if err != nil {
return Identity{}, err
}

Treat the error as close as possible to the source. Else it is very confusing.

return Identity{ECDSA: &IdentityECDSA{PublicKey: pubkey}}, nil
}

func parseIDDarc(in string) (Identity, error) {
id := make([]byte, hex.DecodedLen(len(in)))
_, err := hex.Decode(id, []byte(in))
Expand Down Expand Up @@ -1447,6 +1500,22 @@ func (kcs SignerX509EC) Sign(msg []byte) ([]byte, error) {
return nil, errors.New("not yet implemented")
}

// new signer creates a signer only with a public key used to verify signatures
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// new signer creates a signer only with a public key used to verify signatures
// NewSignerECDSA only takes a public key as the MPC is needed to sign data.

func NewSignerECDSA(public ecdsa.PublicKey) Signer {
if public.X == nil {
return Signer{}
}
return Signer{ECDSA: &SignerECDSA{
PublicKey: public,
}}
}

//TODO
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One way to implement sign would be to give the necessary configuration when calling NewSignerECDSA, and then having Sign call the MPC backend. But that would introduce a dependency on the MPC code that we probably don't want to have in here.

Suggested change
//TODO
// Sign cannot be implemented, as only the MPC can sign a message.

func (kcs SignerECDSA) Sign(msg []byte) ([]byte, error) {
//call tsm to sign
return nil, errors.New("not yet implemented")
}

// NewSignerProxy creates a new SignerProxy. When Sign is called, the getSignature
// callback will be called, so that the caller can use the appropriate mechanism
// to retrieve and/or construct the signature.
Expand Down
24 changes: 18 additions & 6 deletions darc/darc_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package darc

import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/hex"
"errors"
"fmt"
"math/big"
"net/url"
"strings"
"testing"
Expand Down Expand Up @@ -750,17 +754,25 @@ func TestParseIdentity(t *testing.T) {
}

// Test any identity
func testIdentity(t *testing.T, sig Signer) {
msg := []byte("something secret")
signed, err := sig.Sign(msg)
require.NoError(t, err)
func testIdentity(t *testing.T, id Identity) {
msg := []byte(`Hello World`)

//Signature from code example go-tsm-sdk corresponding to ecdsa public key example
signed, _ := hex.DecodeString("304402204f0b20a44efacec7b0514683233a79552026fe80e468078f6fed6cfe3f3e8a0402201eb12db7f6fe0828cafe8b0a032a37ff377b342799cfe77cfbac40c8ec1fa9e8")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
signed, _ := hex.DecodeString("304402204f0b20a44efacec7b0514683233a79552026fe80e468078f6fed6cfe3f3e8a0402201eb12db7f6fe0828cafe8b0a032a37ff377b342799cfe77cfbac40c8ec1fa9e8")
signed, err := hex.DecodeString("304402204f0b20a44efacec7b0514683233a79552026fe80e468078f6fed6cfe3f3e8a0402201eb12db7f6fe0828cafe8b0a032a37ff377b342799cfe77cfbac40c8ec1fa9e8")
require.NoError(t, err)

ALWAYS do error checking! You will save yourself a lot of pain!


id := sig.Identity()
require.NoError(t, id.Verify(msg, signed))
require.Error(t, id.Verify([]byte("wrong message"), signed))
}

// Test the different identities available - currently only Ed25519.
func TestIdentities(t *testing.T) {
testIdentity(t, NewSignerEd25519(nil, nil))
//Ecdsa public key example
var x, _ = new(big.Int).SetString("25613385885653880697990944418179706546134037329992108968315147853972798913688", 10)
var y, _ = new(big.Int).SetString("74946767262888349555270609195205284686604880870734462312238891495596941025713", 10)
Comment on lines +775 to +776
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error checking needed.

pk := ecdsa.PublicKey{
Curve: elliptic.P256(),
X: x,
Y: y,
}
testIdentity(t, NewIdentityECDSA(pk))
}
17 changes: 17 additions & 0 deletions darc/proto.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package darc

import (
"crypto/ecdsa"

"go.dedis.ch/cothority/v3/darc/expression"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/onet/v3/network"
Expand Down Expand Up @@ -71,13 +73,20 @@ type Identity struct {
EvmContract *IdentityEvmContract
// A claim signed by one of the keys in a DID Doc
DID *IdentityDID
// Publik-key identity from an ECDSA key
ECDSA *IdentityECDSA
}

// IdentityEd25519 holds a Ed25519 public key (Point)
type IdentityEd25519 struct {
Point kyber.Point
}

// IdentityECDSA holds a secp256k1 key (array of bytes)
type IdentityECDSA struct {
PublicKey ecdsa.PublicKey
}

// IdentityX509EC holds a public key from a X509EC
type IdentityX509EC struct {
Public []byte
Expand Down Expand Up @@ -159,6 +168,7 @@ type Signer struct {
Proxy *SignerProxy
EvmContract *SignerEvmContract
DID *SignerDID
ECDSA *SignerECDSA
}

// SignerEd25519 holds a public and private keys necessary to sign Darcs
Expand All @@ -174,6 +184,13 @@ type SignerX509EC struct {
secret []byte
}

// SignerECDSA holds a public and private keys necessary to sign Darcs,
// but the private key will not be given out.
type SignerECDSA struct {
PublicKey ecdsa.PublicKey
PrivateKey ecdsa.PrivateKey
}

// SignerProxy holds the information necessary to verify claims
// coming from external authentication systems via Authentication Proxies.
type SignerProxy struct {
Expand Down