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 identity tsm #2487

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ proto:

docker:
docker run -t -v $(PWD):/cothority golang:1.15-buster \
bash -c "cd /cothority; go build -o external/docker/conode -tags test ./conode"
bash -c "cd /cothority && \
go build -o external/docker/conode -tags test ./conode && \
go build -o external/docker/csadmin -tags test ./calypso/csadmin && \
go build -o external/docker/bcadmin -tags test ./byzcoin/bcadmin"
cp conode/run_nodes.sh external/docker
docker build -t $(TEST_IMAGE_NAME) external/docker

docker_test_run: docker
docker run -ti -p7770-7777:7770-7777 dedis/conode-test
docker run -ti -p7770-7777:7770-7777 $(TEST_IMAGE_NAME)

test_java: docker
cd external/java; mvn test
Expand Down
32 changes: 32 additions & 0 deletions byzcoin/bctest.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,38 @@ func (b *BCTest) TransferCoin(args *TxArgs, coinSrc, coinDst InstanceID,
})
}

// SpawnDarc spawns a new darc on byzcoin.
func (b *BCTest) SpawnDarc(args *TxArgs, d *darc.Darc) {
buf, err := d.ToProto()
require.NoError(b.T, err)
b.SendInst(args, Instruction{
InstanceID: NewInstanceID(b.GenesisDarc.GetBaseID()),
Spawn: &Spawn{
ContractID: "darc",
Args: Arguments{
{Name: "darc", Value: buf},
},
},
})
}

// EvolveDarc invokes 'evolve' on the given darc. The darc must have a
// 'version' greater than the already existing darc.
func (b *BCTest) EvolveDarc(args *TxArgs, d *darc.Darc) {
buf, err := d.ToProto()
require.NoError(b.T, err)
b.SendInst(args, Instruction{
InstanceID: NewInstanceID(b.GenesisDarc.GetBaseID()),
Invoke: &Invoke{
ContractID: "darc",
Command: "evolve",
Args: Arguments{
{Name: "darc", Value: buf},
},
},
})
}

// DummyContractName is the name of the dummy contract.
const DummyContractName = "dummy"

Expand Down
3 changes: 2 additions & 1 deletion byzcoin/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,8 @@ func (s *Service) GetProof(req *GetProof) (*GetProofResponse, error) {
// fulfill a given rule of a given darc. Because all darcs are now used in
// an online fashion, we need to offer this check.
func (s *Service) CheckAuthorization(req *CheckAuthorization) (resp *CheckAuthorizationResponse, err error) {
log.Lvlf2("%s getting authorizations of darc %x", s.ServerIdentity(), req.DarcID)
log.Lvlf2("%s getting authorizations of darc %x for identities %v",
s.ServerIdentity(), req.DarcID, req.Identities)

resp = &CheckAuthorizationResponse{}
st, err := s.GetReadOnlyStateTrie(req.ByzCoinID)
Expand Down
25 changes: 25 additions & 0 deletions byzcoin/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1478,6 +1478,31 @@ func TestService_DarcDelegation(t *testing.T) {
require.True(t, pr.Proof.InclusionProof.Match(darc3.GetBaseID()))
}

func TestService_CheckAuthorization_TSM(t *testing.T) {
b := newBCTRun(t, nil)
defer b.CloseAll()

// Add a new rule to the genesis darc and check if it is
// authorized.
signerTSM := darc.NewSignerTSM(nil)
ids := []darc.Identity{signerTSM.Identity()}
tsmDarcRules := darc.InitRules(ids, ids)
tsmDarc := darc.NewDarc(tsmDarcRules, []byte("tsmDarc"))
b.SpawnDarc(nil, tsmDarc)

newDarc := b.GenesisDarc.Copy()
require.NoError(t, newDarc.EvolveFrom(b.GenesisDarc))
require.NoError(t, newDarc.Rules.AddRule("spawn:test",
expression.Expr(darc.NewIdentityDarc(tsmDarc.GetBaseID()).String())))
b.EvolveDarc(nil, newDarc)

log.Lvl1("TSM:", signerTSM.Identity())
actions, err := b.Client.CheckAuthorization(b.GenesisDarc.GetBaseID(),
signerTSM.Identity())
require.NoError(t, err)
require.Contains(t, actions, darc.Action("spawn:test"))
}

func TestService_CheckAuthorization(t *testing.T) {
b := newBCTRun(t, nil)
defer b.CloseAll()
Expand Down
131 changes: 129 additions & 2 deletions calypso/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"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 @@ -203,9 +204,9 @@ func TestClient_Calypso(t *testing.T) {

// Make sure you can't decrypt with non-matching proofs
_, err = calypsoClient.DecryptKey(&DecryptKey{Read: *prRe1, Write: *prWr2})
require.NotNil(t, err)
require.Error(t, err)
_, err = calypsoClient.DecryptKey(&DecryptKey{Read: *prRe2, Write: *prWr1})
require.NotNil(t, err)
require.Error(t, err)

// Make sure you can actually decrypt
dk1, err := calypsoClient.DecryptKey(&DecryptKey{Read: *prRe1, Write: *prWr1})
Expand All @@ -217,3 +218,129 @@ func TestClient_Calypso(t *testing.T) {

// use keyCopy to unlock the stuff in writeInstance.Data
}

// Tests the Calypso system with a simple write/read scenario.
// But it does the signing outside of the `Read` and `Write` methods for
// integration of the MPC signing by OneKey.
func TestClient_Calypso_Simple(t *testing.T) {
l := onet.NewTCPTest(cothority.Suite)
_, roster, _ := l.GenTree(3, true)
defer l.CloseAll()

admin := darc.NewSignerEd25519(nil, nil)
adminCt := uint64(1)
user := darc.NewSignerTSM(nil)
//user := darc.NewSignerEd25519(nil, nil)
// Initialise the genesis message and send it to the service.
// The admin has the privilege to spawn darcs
msg, err := byzcoin.DefaultGenesisMsg(byzcoin.CurrentVersion, roster,
[]string{"spawn:" + ContractLongTermSecretID},
admin.Identity())

msg.BlockInterval = 500 * time.Millisecond
require.NoError(t, err)
// The darc inside it should be valid.
gDarc := msg.GenesisDarc
require.Nil(t, gDarc.Verify(true))
//Create Ledger
c, _, err := byzcoin.NewLedger(msg, false)
require.NoError(t, err)
//Create a Calypso Client (Byzcoin + Onet)
calypsoClient := NewClient(c)

//Create the LTS
for _, who := range roster.List {
err := calypsoClient.Authorize(who, c.ID)
require.NoError(t, err)
}
ltsReply, err := calypsoClient.CreateLTS(roster, gDarc.GetBaseID(), []darc.Signer{admin}, []uint64{adminCt})
adminCt++
require.NoError(t, err)
//If no error, assign it
//calypsoClient.ltsReply = ltsReply

//Create a signer darc
userDarc := darc.NewDarc(darc.InitRules([]darc.Identity{user.Identity()},
[]darc.Identity{user.Identity()}), []byte("Provider1"))
// user can read and write.
// This can be changed to two different public keys.
err = userDarc.Rules.AddRule(darc.Action("spawn:"+ContractWriteID),
expression.InitOrExpr(user.Identity().String()))
require.NoError(t, err)
err = userDarc.Rules.AddRule(darc.Action("spawn:"+ContractReadID),
expression.InitOrExpr(user.Identity().String()))
require.NoError(t, err)
require.NotNil(t, userDarc)
_, err = calypsoClient.SpawnDarc(admin, adminCt, gDarc, *userDarc, 10)
adminCt++
require.NoError(t, err)

data := []byte("Some secret data - or the user's private key")
// Create a Write structure
write1, err := NewWriteData(cothority.Suite,
ltsReply.InstanceID,
userDarc.GetBaseID(), ltsReply.X, data)
require.NoError(t, err)

// Create a write-instance and send it to Byzcoin - here
// the instruction and the transaction is created manually,
// so that an external signer can sign the hash of the instruction.
wrInst, err := ContractWriteSpawnInstruction(write1, userDarc)
require.NoError(t, err)
wrInst.SignerCounter = []uint64{1}
wrInst.SignerIdentities = []darc.Identity{user.Identity()}
wrTx, err := calypsoClient.bcClient.CreateTransaction(*wrInst)
require.NoError(t, err)
digest := wrTx.Instructions.Hash()

// This signature can be replaced by an external signature.
//TODO add sepior signature of digest here
signature, err := user.Sign(digest)
require.NoError(t, err)
wrTx.Instructions[0].Signatures = [][]byte{signature}

// Send the transaction to ByzCoin
_, err = calypsoClient.bcClient.AddTransactionAndWait(wrTx, 10)
require.NoError(t, err)
wrID := wrTx.Instructions[0].DeriveID("")
proofWr, err := calypsoClient.WaitProof(wrID, time.Second, nil)
require.NoError(t, err)

// Create a read-instance and send it to ByzCoin.
ephemeral := key.NewKeyPair(cothority.Suite)
readInst, err := ContractReadSpawnInstruction(wrID, ephemeral.Public)
require.NoError(t, err)
readInst.SignerCounter = []uint64{2}
readInst.SignerIdentities = []darc.Identity{user.Identity()}
readTx, err := calypsoClient.bcClient.CreateTransaction(*readInst)
require.NoError(t, err)
digest = readTx.Instructions.Hash()

// This signature can be replaced by an external signature
// TODO add signature on digest from MPC nodes
signature, err = user.Sign(digest)
require.NoError(t, err)
readTx.Instructions[0].Signatures = [][]byte{signature}
readID := readTx.Instructions[0].DeriveID("")

// Send the transaction to ByzCoin
_, err = calypsoClient.bcClient.AddTransactionAndWait(readTx, 10)
require.NoError(t, err)
proofRd, err := calypsoClient.WaitProof(readID, time.Second,
nil)
require.NoError(t, err)

// Make sure you can actually decrypt
dk, err := calypsoClient.DecryptKey(&DecryptKey{Read: *proofRd,
Write: *proofWr})
require.NoError(t, err)
require.True(t, dk.X.Equal(ltsReply.X))
keyCopy, err := dk.RecoverKey(ephemeral.Private)
require.NoError(t, err)
var wrCopy Write
require.NoError(t, proofWr.VerifyAndDecode(cothority.Suite, ContractWriteID,
&wrCopy))
dataDecrypt, err := wrCopy.Decrypt(keyCopy)
require.NoError(t, err)
require.Equal(t, data, dataDecrypt)
}
46 changes: 46 additions & 0 deletions calypso/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,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 Expand Up @@ -278,3 +279,48 @@ func (c ContractWrite) VerifyInstruction(rst byzcoin.ReadOnlyStateTrie, inst byz
}
return inst.VerifyWithOption(rst, ctxHash, nil)
}

// ContractWriteSpawnInstruction returns the spawn instruction for a Write
// contract.
func ContractWriteSpawnInstruction(wr *Write,
d *darc.Darc) (*byzcoin.Instruction, error) {
writeBuf, err := protobuf.Encode(wr)
if err != nil {
return nil, xerrors.Errorf("couldn't encode write: %v", err)
}
return &byzcoin.Instruction{
InstanceID: byzcoin.NewInstanceID(d.GetBaseID()),
Spawn: &byzcoin.Spawn{
ContractID: ContractWriteID,
Args: byzcoin.Arguments{
{
Name: "write",
Value: writeBuf,
},
},
},
}, nil
}

// ContractReadSpawnInstruction returns the spawn instruction for a Read
// contract.
func ContractReadSpawnInstruction(wrID byzcoin.InstanceID,
xc kyber.Point) (*byzcoin.Instruction, error) {
var readBuf []byte
read := &Read{
Write: wrID,
Xc: xc,
}
readBuf, err := protobuf.Encode(read)
if err != nil {
return nil, xerrors.Errorf("encoding Read message: %v", err)
}

return &byzcoin.Instruction{
InstanceID: wrID,
Spawn: &byzcoin.Spawn{
ContractID: ContractReadID,
Args: byzcoin.Arguments{{Name: "read", Value: readBuf}},
},
}, nil
}
Loading