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

clean darc_identity_tsm branch for PR #2491

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
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
}
75 changes: 75 additions & 0 deletions calypso/struct.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package calypso

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"fmt"
"io"

"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/kyber/v3/suites"
"go.dedis.ch/kyber/v3/util/random"
"go.dedis.ch/kyber/v3/xof/keccak"
"go.dedis.ch/onet/v3/network"
"golang.org/x/xerrors"
)

func init() {
Expand Down Expand Up @@ -68,6 +75,20 @@ func NewWrite(suite suites.Suite, ltsid byzcoin.InstanceID, writeDarc darc.ID, X
return wr
}

// NewWriteData is like NewWrite,
// but it encrypts the data with a random key and adds the data to the Write
// structure.
func NewWriteData(suite suites.Suite, ltsid byzcoin.InstanceID,
writeDarc darc.ID, X kyber.Point, data []byte) (wr *Write, err error) {
key := random.Bits(192, true, random.New())
wr = NewWrite(suite, ltsid, writeDarc, X, key)
wr.Data, err = AeadSeal(key, data)
if err != nil {
return nil, xerrors.Errorf("couldn't seal data: %v", err)
}
return
}

// CheckProof verifies that the write-request has actually been created with
// somebody having access to the secret key.
func (wr *Write) CheckProof(suite suite, writeID darc.ID) error {
Expand Down Expand Up @@ -97,6 +118,60 @@ func (wr *Write) CheckProof(suite suite, writeID darc.ID) error {
"%s\n%s", e.String(), wr.E.String())
}

// Decrypt calls AeadOpen to decrypt the data with the given key.
func (wr *Write) Decrypt(key []byte) ([]byte, error) {
return AeadOpen(key, wr.Data)
}

// This suggested length is from https://godoc.org/crypto/cipher#NewGCM example
const nonceLen = 12

// AeadSeal encrypts the given plaintext with the given key.
// It adds a 12-byte nonce to the ciphertext.
func AeadSeal(symKey, data []byte) ([]byte, error) {
block, err := aes.NewCipher(symKey)
if err != nil {
return nil,
xerrors.Errorf("creating aes cipher block instance: %v", err)
}

// Never use more than 2^32 random nonces with a given key because of the risk of a repeat.
nonce := make([]byte, nonceLen)
_, err = io.ReadFull(rand.Reader, nonce)
if err != nil {
return nil, xerrors.Errorf("reading nonce: %v", err)
}

aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, xerrors.Errorf("creating aesgcm instance: %v", err)
}
encData := aesgcm.Seal(nil, nonce, data, nil)
encData = append(encData, nonce...)
return encData, nil
}

// AeadOpen decrypts a given ciphertext with the given key.
func AeadOpen(key, ciphertext []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil,
xerrors.Errorf("creating aes cipher block instance: %v", err)
}

aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, xerrors.Errorf("creating aesgcm instance: %v", err)
}

if len(ciphertext) < 12 {
return nil, xerrors.New("ciphertext too short")
}
nonce := ciphertext[len(ciphertext)-nonceLen:]
out, err := aesgcm.Open(nil, nonce, ciphertext[0:len(ciphertext)-nonceLen], nil)
return out, cothority.ErrorOrNil(err, "decrypting ciphertext")
}

type newLtsConfig struct {
byzcoin.Proof
}
Expand Down
2 changes: 1 addition & 1 deletion external/js/cothority/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 18 additions & 4 deletions external/js/cothority/spec/byzcoin/darc-instance.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { randomBytes } from "crypto";
import ByzCoinRPC from "../../src/byzcoin/byzcoin-rpc";
import DarcInstance from "../../src/byzcoin/contracts/darc-instance";
import Darc from "../../src/darc/darc";
import IdentityDarc from "../../src/darc/identity-darc";
import { Rule } from "../../src/darc/rules";
import SignerEd25519 from "../../src/darc/signer-ed25519";
import { Darc, IdentityDarc, IdentityTsm, IdentityWrapper, Rule, SignerEd25519 } from "../../src/darc";
import { BLOCK_INTERVAL, ROSTER, SIGNER, startConodes } from "../support/conondes";

describe("DarcInstance Tests", () => {
Expand All @@ -28,4 +26,20 @@ describe("DarcInstance Tests", () => {
expect(di1.ruleMatch(Darc.ruleSign, [sig])).toBeTruthy();
expect(di1.ruleMatch(Darc.ruleSign, [new IdentityDarc({id: d2.getBaseID()})])).toBeTruthy();
});

it("should find tsm authorization", async () => {
const darc = ByzCoinRPC.makeGenesisDarc([SIGNER], roster);

const rpc = await ByzCoinRPC.newByzCoinRPC(roster, darc, BLOCK_INTERVAL);
rpc.setParallel(1);
const di = await DarcInstance.fromByzcoin(rpc, darc.getBaseID());

const id = new IdentityTsm({publickey: randomBytes(32)});
const newDarc = darc.evolve();
newDarc.addIdentity("spawn:test", id, Rule.OR);
await di.evolveDarcAndWait(newDarc, [SIGNER], 10);

const rules = await rpc.checkAuthorization(rpc.genesisID, darc.getBaseID(), IdentityWrapper.fromIdentity(id));
expect(rules).toEqual(["spawn:test"]);
});
});
37 changes: 37 additions & 0 deletions external/js/cothority/src/darc/identity-tsm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Message, Properties } from "protobufjs/light";
import { EMPTY_BUFFER, registerMessage } from "../protobuf";
import IdentityWrapper, { IIdentity } from "./identity-wrapper";

/**
* Identity based on a TSM
*/
export default class IdentityTsm extends Message<IdentityTsm> implements IIdentity {
/**
* @see README#Message classes
*/
static register() {
registerMessage("IdentityTSM", IdentityTsm);
}

readonly publickey: Buffer;

constructor(props?: Properties<IdentityTsm>) {
super(props);
this.publickey = Buffer.from(this.publickey || EMPTY_BUFFER);
}

/** @inheritdoc */
verify(msg: Buffer, signature: Buffer): boolean {
throw new Error("Not implemented");
}

/** @inheritdoc */
toBytes(): Buffer {
return Buffer.from(this.publickey);
}

/** @inheritdoc */
toString(): string {
return `tsm:${this.publickey.toString("hex")}`;
}
}
15 changes: 14 additions & 1 deletion external/js/cothority/src/darc/identity-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { registerMessage } from "../protobuf";
import IdentityDarc from "./identity-darc";
import IdentityDid from "./identity-did";
import IdentityEd25519 from "./identity-ed25519";
import IdentityTsm from "./identity-tsm";

/**
* Protobuf representation of an identity
Expand All @@ -13,7 +14,7 @@ export default class IdentityWrapper extends Message<IdentityWrapper> {
* @see README#Message classes
*/
static register() {
registerMessage("Identity", IdentityWrapper, IdentityEd25519, IdentityDarc, IdentityDid);
registerMessage("Identity", IdentityWrapper, IdentityEd25519, IdentityDarc, IdentityDid, IdentityTsm);
}

/**
Expand Down Expand Up @@ -42,6 +43,11 @@ export default class IdentityWrapper extends Message<IdentityWrapper> {
const id = new IdentityDid({method: Buffer.from(field[1]), did: Buffer.from(field[2]) });
return new IdentityWrapper({did: id});
}
if (idStr.startsWith("tsm:")) {
const field = idStr.split(":", 2);
const tsm = new IdentityTsm({publickey: Buffer.from(field[1], "hex")});
return new IdentityWrapper({tsm});
}
}

/**
Expand All @@ -54,6 +60,7 @@ export default class IdentityWrapper extends Message<IdentityWrapper> {
readonly ed25519: IdentityEd25519;
readonly darc: IdentityDarc;
readonly did: IdentityDid;
readonly tsm: IdentityTsm;

/**
* Get the inner identity as bytes
Expand All @@ -69,6 +76,9 @@ export default class IdentityWrapper extends Message<IdentityWrapper> {
if (this.did) {
return this.did.toBytes();
}
if (this.tsm) {
return this.tsm.toBytes();
}

return Buffer.from([]);
}
Expand All @@ -87,6 +97,9 @@ export default class IdentityWrapper extends Message<IdentityWrapper> {
if (this.did) {
return this.did.toString();
}
if (this.tsm) {
return this.tsm.toString();
}

return "empty signer";
}
Expand Down
2 changes: 2 additions & 0 deletions external/js/cothority/src/darc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Darc from "./darc";
import IdentityDarc from "./identity-darc";
import IdentityDid from "./identity-did";
import IdentityEd25519 from "./identity-ed25519";
import IdentityTsm from "./identity-tsm";
import IdentityWrapper, { IIdentity } from "./identity-wrapper";
import Rules, { Rule } from "./rules";
import Signer from "./signer";
Expand All @@ -13,6 +14,7 @@ export {
IdentityDarc,
IdentityDid,
IdentityEd25519,
IdentityTsm,
IdentityWrapper,
Rule,
Rules,
Expand Down
2 changes: 1 addition & 1 deletion external/js/cothority/src/network/websocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class WebSocketConnection implements IConnection {
let timer = setTimeout(() => ws.close(1000, "timeout"), this.timeout);

ws.onOpen(() => {
Log.lvl3("Sending message to", url.href);
Log.lvl3("Sending message", bytes.toString("hex"), "to", url.href);
ws.send(bytes);
});

Expand Down
2 changes: 1 addition & 1 deletion external/js/cothority/src/protobuf/models.json

Large diffs are not rendered by default.

12 changes: 11 additions & 1 deletion external/js/cothority/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@
"typeRoots": [
"../types",
"./node_modules/@types"
]
],
"paths": {
"@dedis/kyber": [
"node_modules/@dedis/kyber/dist",
"node_modules/@dedis/kyber"
],
"@dedis/kyber/*": [
"node_modules/@dedis/kyber/dist/*",
"node_modules/@dedis/kyber/*"
]
}
},
"include": [
"src/**/*"
Expand Down