{"action":"created","comment":{"url":"https://api.github.com/repos/dedis/cothority/pulls/comments/59019475","id":59019475,"diff_hunk":"@@ -0,0 +1,459 @@\n+package cosi\n+\n+import (\n+\t\"bytes\"\n+\t\"encoding/base64\"\n+\t\"encoding/json\"\n+\t\"errors\"\n+\t\"fmt\"\n+\t\"github.com/BurntSushi/toml\"\n+\t\"github.com/dedis/cothority/lib/cosi\"\n+\t\"github.com/dedis/cothority/lib/crypto\"\n+\t\"github.com/dedis/cothority/lib/dbg\"\n+\t\"github.com/dedis/cothority/lib/network\"\n+\t\"github.com/dedis/cothority/lib/sda\"\n+\t\"github.com/dedis/crypto/abstract\"\n+\t\"github.com/dedis/crypto/config\"\n+\t\"golang.org/x/net/context\"\n+\t\"io\"\n+\t\"io/ioutil\"\n+\t\"os\"\n+\t\"strings\"\n+\t\"time\"\n+)\n+\n+func init() {\n+\tdbg.Print(\"Registering\")\n+\tdbg.Print(network.RegisterMessageType(SignRequest{}))\n+\tdbg.Print(network.RegisterMessageType(SignResponse{}))\n+}\n+\n+// App represents the application that will listen for signatures\n+type App struct {\n+\thost    *sda.Host\n+\toverlay *sda.Overlay\n+\tEntity  *network.Entity\n+}\n+\n+// SignRequest is used by the client to send something to sda that\n+// will in turn give that to the CoSi system.\n+// It contains the message the client wants to sign.\n+type SignRequest struct {\n+\t// The entity list to use for creating the cosi tree\n+\tEntityList *sda.EntityList\n+\t// the actual message to sign by CoSi.\n+\tMessage []byte\n+}\n+\n+// SignResponse contains the signature out of the CoSi system.\n+// It can be verified using the lib/cosi package.\n+// NOTE: the `suite` field is absent here because this struct is a temporary\n+// hack and we only supports one suite for the moment,i.e. ed25519.\n+type SignResponse struct {\n+\t// The hash of the signed statement\n+\tSum []byte\n+\t// The Challenge out a of the Multi Schnorr signature\n+\tChallenge abstract.Secret\n+\t// the SignResponse out of the Multi Schnorr Signature\n+\tResponse abstract.Secret\n+}\n+\n+// MarshalJSON implements golang's JSON marshal interface\n+func (s *SignResponse) MarshalJSON() ([]byte, error) {\n+\tcw := new(bytes.Buffer)\n+\trw := new(bytes.Buffer)\n+\n+\terr := crypto.WriteSecret64(network.Suite, cw, s.Challenge)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\terr = crypto.WriteSecret64(network.Suite, rw, s.Response)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\treturn json.Marshal(struct {\n+\t\tSum       string\n+\t\tChallenge string\n+\t\tResponse  string\n+\t}{\n+\t\tSum:       base64.StdEncoding.EncodeToString(s.Sum),\n+\t\tChallenge: cw.String(),\n+\t\tResponse:  rw.String(),\n+\t})\n+}\n+\n+// UnmarshalJSON implements golang's JSON unmarshal interface\n+func (s *SignResponse) UnmarshalJSON(data []byte) error {\n+\ttype Aux struct {\n+\t\tSum       string\n+\t\tChallenge string\n+\t\tResponse  string\n+\t}\n+\taux := &Aux{}\n+\tif err := json.Unmarshal(data, aux); err != nil {\n+\t\treturn err\n+\t}\n+\tvar err error\n+\tif s.Sum, err = base64.StdEncoding.DecodeString(aux.Sum); err != nil {\n+\t\treturn err\n+\t}\n+\tsuite := network.Suite\n+\tcr := strings.NewReader(aux.Challenge)\n+\tif s.Challenge, err = crypto.ReadSecret64(suite, cr); err != nil {\n+\t\treturn err\n+\t}\n+\trr := strings.NewReader(aux.Response)\n+\tif s.Response, err = crypto.ReadSecret64(suite, rr); err != nil {\n+\t\treturn err\n+\t}\n+\treturn nil\n+}\n+\n+// CreateCosiApp takes the ip:Port and returns an app for signing\n+func CreateCosiApp(ip string) *App {\n+\t// create the public / private keys\n+\tkp := config.NewKeyPair(network.Suite)\n+\tentity := network.NewEntity(kp.Public, ip)\n+\thost := sda.NewHost(entity, kp.Secret)\n+\n+\treturn &App{\n+\t\thost:    host,\n+\t\toverlay: host.GetOverlay(),\n+\t}\n+}\n+\n+// ReadCosiApp reads the configuration from a file\n+func ReadCosiApp(cnf string) (*App, error) {\n+\th, err := sda.NewHostFromFile(cnf)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\treturn &App{\n+\t\thost:    h,\n+\t\toverlay: h.GetOverlay(),\n+\t}, nil\n+}\n+\n+// AddCosiApp registers the handler to the given host. This is used\n+// if another app wants to add the signing feature to the same host\n+func AddCosiApp(h *sda.Host) {\n+\tca := &App{\n+\t\thost:    h,\n+\t\toverlay: h.GetOverlay(),\n+\t}\n+\tca.host.RegisterExternalMessage(SignRequest{}, ca.HandleCosiSignRequest)\n+}\n+\n+// PrintServer prints out the configuration that can be copied to the servers.toml\n+// file\n+func (ca *App) PrintServer() {\n+\tserverToml := NewServerToml(network.Suite, ca.host.Entity.Public,\n+\t\tca.host.Entity.Addresses...)\n+\tgroupToml := NewGroupToml(serverToml)\n+\tfmt.Println(groupToml.String())\n+}\n+\n+// Start listens on the incoming port and DOES NOT return\n+func (ca *App) Start() {\n+\tca.host.RegisterExternalMessage(SignRequest{}, ca.HandleCosiSignRequest)\n+\tca.host.Listen()\n+\tca.host.StartProcessMessages()\n+\tca.host.WaitForClose()\n+}\n+\n+// Write saves the config to a file\n+func (ca *App) Write(cnf string) error {\n+\tif err := ca.host.SaveToFile(cnf); err != nil {\n+\t\treturn err\n+\t}\n+\treturn nil\n+}\n+\n+// handleCosiSignRequest will\n+// * register the entitylist\n+// * create a flat tree out of it with him being at the root\n+// * launch a CoSi protocol\n+// * wait for it to finish and send back the response to the client\n+func (ca *App) HandleCosiSignRequest(msg *network.Message) network.ProtocolMessage {\n+\tdbg.Lvl2(\"Received client CosiSignRequest from\", msg.From)\n+\tempty := &SignResponse{}\n+\tcr, ok := msg.Msg.(SignRequest)\n+\tif !ok {\n+\t\treturn empty\n+\t}\n+\tidx, e := cr.EntityList.Search(ca.host.Entity.ID)\n+\tif e == nil {\n+\t\tdbg.Error(\"Received CosiSignRequest without being included in the Entitylist\")\n+\t\treturn empty\n+\t}\n+\tif idx != 0 {\n+\t\t// replace the first entity by this host's entity\n+\t\ttmp := cr.EntityList.List[0]\n+\t\tcr.EntityList.List[0] = e\n+\t\tcr.EntityList.List[idx] = tmp\n+\t}\n+\t// register & create the tree\n+\tca.overlay.RegisterEntityList(cr.EntityList)\n+\t// for the moment let's just stick to a very simple binary tree\n+\ttree := cr.EntityList.GenerateBinaryTree()\n+\tca.overlay.RegisterTree(tree)\n+\n+\t// run the CoSi protocol\n+\tnode, err := ca.overlay.CreateNewNodeName(\"CoSi\", tree)\n+\tif err != nil {\n+\t\tdbg.Error(\"Error creating tree upon client SignRequest:\", err)\n+\t\treturn empty\n+\t}\n+\tpcosi := node.ProtocolInstance().(*ProtocolCosi)\n+\tpcosi.SigningMessage(cr.Message)\n+\thash := network.Suite.Hash()\n+\tif _, err := hash.Write(cr.Message); err != nil {\n+\t\tdbg.Error(\"Couldn't hash message:\", err)\n+\t}\n+\tsum := hash.Sum(nil)\n+\t// Register the handler when the signature is finished\n+\trchan := make(chan *SignResponse)\n+\tfn := func(chal, resp abstract.Secret) {\n+\t\tresponse := &SignResponse{\n+\t\t\tSum:       sum,\n+\t\t\tChallenge: chal,\n+\t\t\tResponse:  resp,\n+\t\t}\n+\t\tdbg.Lvl2(\"Getting CoSi signature back => sending to client\")\n+\t\t// send back to client\n+\t\trchan <- response\n+\t}\n+\tpcosi.RegisterDoneCallback(fn)\n+\tdbg.Lvl2(\"Starting CoSi protocol...\")\n+\tgo node.StartProtocol()\n+\treturn <-rchan\n+}\n+\n+// sign takes a stream and a toml file defining the servers\n+func Sign(r io.Reader, tomlFileName string) (*SignResponse, error) {\n+\tdbg.Lvl3(\"Starting signature\")\n+\tf, err := os.Open(tomlFileName)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\tel, err := ReadGroupToml(f)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\tdbg.Lvl2(\"Sending signature to\", el)\n+\tres, err := SignStatement(r, el)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\treturn res, nil\n+}\n+\n+// signStatement can be used to sign the contents passed in the io.Reader\n+// (pass an io.File or use an strings.NewReader for strings)\n+func SignStatement(r io.Reader, el *sda.EntityList) (*SignResponse, error) {\n+\n+\t// create a throw-away key pair:\n+\tkp := config.NewKeyPair(network.Suite)\n+\n+\t// create a throw-away entity with an empty  address:\n+\te := network.NewEntity(kp.Public, \"\")\n+\tclient := network.NewSecureTCPHost(kp.Secret, e)\n+\tmsg, _ := crypto.HashStream(network.Suite.Hash(), r)\n+\treq := &SignRequest{\n+\t\tEntityList: el,\n+\t\tMessage:    msg,\n+\t}\n+\n+\t// Connect to the root\n+\thost := el.List[0]\n+\tdbg.Lvl3(\"Opening connection to\", host.Addresses[0], host.Public)\n+\tcon, err := client.Open(host)\n+\tdefer client.Close()\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tdbg.Lvl3(\"Sending sign SignRequest\")\n+\tpchan := make(chan SignResponse)\n+\tgo func() {\n+\t\t// send the SignRequest\n+\t\tif err := con.Send(context.TODO(), req); err != nil {\n+\t\t\tclose(pchan)\n+\t\t\treturn\n+\t\t}\n+\t\tdbg.Lvl3(\"Waiting for the response\")\n+\t\t// wait for the response\n+\t\tpacket, err := con.Receive(context.TODO())\n+\t\tif err != nil {\n+\t\t\tclose(pchan)\n+\t\t\treturn\n+\t\t}\n+\t\tpchan <- packet.Msg.(SignResponse)\n+\t}()\n+\tselect {\n+\tcase response, ok := <-pchan:\n+\t\tdbg.Lvl5(\"Response:\", ok, response)\n+\t\tif !ok {\n+\t\t\treturn nil, errors.New(\"Invalid repsonse: Could not cast the \" +\n+\t\t\t\t\"received response to the right type\")\n+\t\t}\n+\t\terr = cosi.VerifySignature(network.Suite, msg, el.Aggregate,\n+\t\t\tresponse.Challenge, response.Response)\n+\t\tif err != nil {\n+\t\t\treturn nil, err\n+\t\t}\n+\t\treturn &response, nil\n+\tcase <-time.After(time.Second * 10):\n+\t\treturn nil, errors.New(\"Timeout on signing\")\n+\t}\n+}\n+\n+// verify takes a file and a group-definition, calls the signature\n+// verification and prints the result\n+func Verify(fileName, groupToml string) error {","path":"protocols/cosi/public_api.go","position":313,"original_position":313,"commit_id":"728f1eb9f44f9a58953227597718450a8749c769","original_commit_id":"728f1eb9f44f9a58953227597718450a8749c769","user":{"login":"nikkolasg","id":2564747,"avatar_url":"https://avatars.githubusercontent.com/u/2564747?v=3","gravatar_id":"","url":"https://api.github.com/users/nikkolasg","html_url":"https://github.com/nikkolasg","followers_url":"https://api.github.com/users/nikkolasg/followers","following_url":"https://api.github.com/users/nikkolasg/following{/other_user}","gists_url":"https://api.github.com/users/nikkolasg/gists{/gist_id}","starred_url":"https://api.github.com/users/nikkolasg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nikkolasg/subscriptions","organizations_url":"https://api.github.com/users/nikkolasg/orgs","repos_url":"https://api.github.com/users/nikkolasg/repos","events_url":"https://api.github.com/users/nikkolasg/events{/privacy}","received_events_url":"https://api.github.com/users/nikkolasg/received_events","type":"User","site_admin":false},"body":"Could you put that directly into lib/cosi ? As there is no network communication nothing complex, it can be put directly in lib/cosi I think, and it's only a wrapper around the existing method that exists to verify (`cosi.VerifySignature`...)\r\nPS: only doing high level comments since it's a very big PR.","created_at":"2016-04-08T12:50:04Z","updated_at":"2016-04-08T12:50:04Z","html_url":"https://github.com/dedis/cothority/pull/339#discussion_r59019475","pull_request_url":"https://api.github.com/repos/dedis/cothority/pulls/339","_links":{"self":{"href":"https://api.github.com/repos/dedis/cothority/pulls/comments/59019475"},"html":{"href":"https://github.com/dedis/cothority/pull/339#discussion_r59019475"},"pull_request":{"href":"https://api.github.com/repos/dedis/cothority/pulls/339"}}},"pull_request":{"url":"https://api.github.com/repos/dedis/cothority/pulls/339","id":65159555,"html_url":"https://github.com/dedis/cothority/pull/339","diff_url":"https://github.com/dedis/cothority/pull/339.diff","patch_url":"https://github.com/dedis/cothority/pull/339.patch","issue_url":"https://api.github.com/repos/dedis/cothority/issues/339","number":339,"state":"open","locked":false,"title":"Osdi ssh","user":{"login":"ineiti","id":1545067,"avatar_url":"https://avatars.githubusercontent.com/u/1545067?v=3","gravatar_id":"","url":"https://api.github.com/users/ineiti","html_url":"https://github.com/ineiti","followers_url":"https://api.github.com/users/ineiti/followers","following_url":"https://api.github.com/users/ineiti/following{/other_user}","gists_url":"https://api.github.com/users/ineiti/gists{/gist_id}","starred_url":"https://api.github.com/users/ineiti/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ineiti/subscriptions","organizations_url":"https://api.github.com/users/ineiti/orgs","repos_url":"https://api.github.com/users/ineiti/repos","events_url":"https://api.github.com/users/ineiti/events{/privacy}","received_events_url":"https://api.github.com/users/ineiti/received_events","type":"User","site_admin":false},"body":"Implementing a simple ssh-key-management using the cosi_cli binary/libraries.","created_at":"2016-04-04T15:00:37Z","updated_at":"2016-04-08T12:50:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c3a509541ab4c2010ca97ec8370857cccf55cc86","assignee":{"login":"ineiti","id":1545067,"avatar_url":"https://avatars.githubusercontent.com/u/1545067?v=3","gravatar_id":"","url":"https://api.github.com/users/ineiti","html_url":"https://github.com/ineiti","followers_url":"https://api.github.com/users/ineiti/followers","following_url":"https://api.github.com/users/ineiti/following{/other_user}","gists_url":"https://api.github.com/users/ineiti/gists{/gist_id}","starred_url":"https://api.github.com/users/ineiti/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ineiti/subscriptions","organizations_url":"https://api.github.com/users/ineiti/orgs","repos_url":"https://api.github.com/users/ineiti/repos","events_url":"https://api.github.com/users/ineiti/events{/privacy}","received_events_url":"https://api.github.com/users/ineiti/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/dedis/cothority/pulls/339/commits","review_comments_url":"https://api.github.com/repos/dedis/cothority/pulls/339/comments","review_comment_url":"https://api.github.com/repos/dedis/cothority/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dedis/cothority/issues/339/comments","statuses_url":"https://api.github.com/repos/dedis/cothority/statuses/728f1eb9f44f9a58953227597718450a8749c769","head":{"label":"dedis:osdi_ssh","ref":"osdi_ssh","sha":"728f1eb9f44f9a58953227597718450a8749c769","user":{"login":"dedis","id":3638331,"avatar_url":"https://avatars.githubusercontent.com/u/3638331?v=3","gravatar_id":"","url":"https://api.github.com/users/dedis","html_url":"https://github.com/dedis","followers_url":"https://api.github.com/users/dedis/followers","following_url":"https://api.github.com/users/dedis/following{/other_user}","gists_url":"https://api.github.com/users/dedis/gists{/gist_id}","starred_url":"https://api.github.com/users/dedis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dedis/subscriptions","organizations_url":"https://api.github.com/users/dedis/orgs","repos_url":"https://api.github.com/users/dedis/repos","events_url":"https://api.github.com/users/dedis/events{/privacy}","received_events_url":"https://api.github.com/users/dedis/received_events","type":"Organization","site_admin":false},"repo":{"id":41791684,"name":"cothority","full_name":"dedis/cothority","owner":{"login":"dedis","id":3638331,"avatar_url":"https://avatars.githubusercontent.com/u/3638331?v=3","gravatar_id":"","url":"https://api.github.com/users/dedis","html_url":"https://github.com/dedis","followers_url":"https://api.github.com/users/dedis/followers","following_url":"https://api.github.com/users/dedis/following{/other_user}","gists_url":"https://api.github.com/users/dedis/gists{/gist_id}","starred_url":"https://api.github.com/users/dedis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dedis/subscriptions","organizations_url":"https://api.github.com/users/dedis/orgs","repos_url":"https://api.github.com/users/dedis/repos","events_url":"https://api.github.com/users/dedis/events{/privacy}","received_events_url":"https://api.github.com/users/dedis/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dedis/cothority","description":"Scalable collective authority prototype","fork":false,"url":"https://api.github.com/repos/dedis/cothority","forks_url":"https://api.github.com/repos/dedis/cothority/forks","keys_url":"https://api.github.com/repos/dedis/cothority/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dedis/cothority/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dedis/cothority/teams","hooks_url":"https://api.github.com/repos/dedis/cothority/hooks","issue_events_url":"https://api.github.com/repos/dedis/cothority/issues/events{/number}","events_url":"https://api.github.com/repos/dedis/cothority/events","assignees_url":"https://api.github.com/repos/dedis/cothority/assignees{/user}","branches_url":"https://api.github.com/repos/dedis/cothority/branches{/branch}","tags_url":"https://api.github.com/repos/dedis/cothority/tags","blobs_url":"https://api.github.com/repos/dedis/cothority/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dedis/cothority/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dedis/cothority/git/refs{/sha}","trees_url":"https://api.github.com/repos/dedis/cothority/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dedis/cothority/statuses/{sha}","languages_url":"https://api.github.com/repos/dedis/cothority/languages","stargazers_url":"https://api.github.com/repos/dedis/cothority/stargazers","contributors_url":"https://api.github.com/repos/dedis/cothority/contributors","subscribers_url":"https://api.github.com/repos/dedis/cothority/subscribers","subscription_url":"https://api.github.com/repos/dedis/cothority/subscription","commits_url":"https://api.github.com/repos/dedis/cothority/commits{/sha}","git_commits_url":"https://api.github.com/repos/dedis/cothority/git/commits{/sha}","comments_url":"https://api.github.com/repos/dedis/cothority/comments{/number}","issue_comment_url":"https://api.github.com/repos/dedis/cothority/issues/comments{/number}","contents_url":"https://api.github.com/repos/dedis/cothority/contents/{+path}","compare_url":"https://api.github.com/repos/dedis/cothority/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dedis/cothority/merges","archive_url":"https://api.github.com/repos/dedis/cothority/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dedis/cothority/downloads","issues_url":"https://api.github.com/repos/dedis/cothority/issues{/number}","pulls_url":"https://api.github.com/repos/dedis/cothority/pulls{/number}","milestones_url":"https://api.github.com/repos/dedis/cothority/milestones{/number}","notifications_url":"https://api.github.com/repos/dedis/cothority/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dedis/cothority/labels{/name}","releases_url":"https://api.github.com/repos/dedis/cothority/releases{/id}","deployments_url":"https://api.github.com/repos/dedis/cothority/deployments","created_at":"2015-09-02T09:13:57Z","updated_at":"2016-04-08T00:17:26Z","pushed_at":"2016-04-08T12:42:43Z","git_url":"git://github.com/dedis/cothority.git","ssh_url":"git@github.com:dedis/cothority.git","clone_url":"https://github.com/dedis/cothority.git","svn_url":"https://github.com/dedis/cothority","homepage":"","size":52180,"stargazers_count":97,"watchers_count":97,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":51,"forks":7,"open_issues":51,"watchers":97,"default_branch":"master"}},"base":{"label":"dedis:cosi_cli","ref":"cosi_cli","sha":"2f102d4ac6f4ad45ae86a5458af50eb9db9fe6b4","user":{"login":"dedis","id":3638331,"avatar_url":"https://avatars.githubusercontent.com/u/3638331?v=3","gravatar_id":"","url":"https://api.github.com/users/dedis","html_url":"https://github.com/dedis","followers_url":"https://api.github.com/users/dedis/followers","following_url":"https://api.github.com/users/dedis/following{/other_user}","gists_url":"https://api.github.com/users/dedis/gists{/gist_id}","starred_url":"https://api.github.com/users/dedis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dedis/subscriptions","organizations_url":"https://api.github.com/users/dedis/orgs","repos_url":"https://api.github.com/users/dedis/repos","events_url":"https://api.github.com/users/dedis/events{/privacy}","received_events_url":"https://api.github.com/users/dedis/received_events","type":"Organization","site_admin":false},"repo":{"id":41791684,"name":"cothority","full_name":"dedis/cothority","owner":{"login":"dedis","id":3638331,"avatar_url":"https://avatars.githubusercontent.com/u/3638331?v=3","gravatar_id":"","url":"https://api.github.com/users/dedis","html_url":"https://github.com/dedis","followers_url":"https://api.github.com/users/dedis/followers","following_url":"https://api.github.com/users/dedis/following{/other_user}","gists_url":"https://api.github.com/users/dedis/gists{/gist_id}","starred_url":"https://api.github.com/users/dedis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dedis/subscriptions","organizations_url":"https://api.github.com/users/dedis/orgs","repos_url":"https://api.github.com/users/dedis/repos","events_url":"https://api.github.com/users/dedis/events{/privacy}","received_events_url":"https://api.github.com/users/dedis/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dedis/cothority","description":"Scalable collective authority prototype","fork":false,"url":"https://api.github.com/repos/dedis/cothority","forks_url":"https://api.github.com/repos/dedis/cothority/forks","keys_url":"https://api.github.com/repos/dedis/cothority/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dedis/cothority/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dedis/cothority/teams","hooks_url":"https://api.github.com/repos/dedis/cothority/hooks","issue_events_url":"https://api.github.com/repos/dedis/cothority/issues/events{/number}","events_url":"https://api.github.com/repos/dedis/cothority/events","assignees_url":"https://api.github.com/repos/dedis/cothority/assignees{/user}","branches_url":"https://api.github.com/repos/dedis/cothority/branches{/branch}","tags_url":"https://api.github.com/repos/dedis/cothority/tags","blobs_url":"https://api.github.com/repos/dedis/cothority/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dedis/cothority/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dedis/cothority/git/refs{/sha}","trees_url":"https://api.github.com/repos/dedis/cothority/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dedis/cothority/statuses/{sha}","languages_url":"https://api.github.com/repos/dedis/cothority/languages","stargazers_url":"https://api.github.com/repos/dedis/cothority/stargazers","contributors_url":"https://api.github.com/repos/dedis/cothority/contributors","subscribers_url":"https://api.github.com/repos/dedis/cothority/subscribers","subscription_url":"https://api.github.com/repos/dedis/cothority/subscription","commits_url":"https://api.github.com/repos/dedis/cothority/commits{/sha}","git_commits_url":"https://api.github.com/repos/dedis/cothority/git/commits{/sha}","comments_url":"https://api.github.com/repos/dedis/cothority/comments{/number}","issue_comment_url":"https://api.github.com/repos/dedis/cothority/issues/comments{/number}","contents_url":"https://api.github.com/repos/dedis/cothority/contents/{+path}","compare_url":"https://api.github.com/repos/dedis/cothority/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dedis/cothority/merges","archive_url":"https://api.github.com/repos/dedis/cothority/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dedis/cothority/downloads","issues_url":"https://api.github.com/repos/dedis/cothority/issues{/number}","pulls_url":"https://api.github.com/repos/dedis/cothority/pulls{/number}","milestones_url":"https://api.github.com/repos/dedis/cothority/milestones{/number}","notifications_url":"https://api.github.com/repos/dedis/cothority/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dedis/cothority/labels{/name}","releases_url":"https://api.github.com/repos/dedis/cothority/releases{/id}","deployments_url":"https://api.github.com/repos/dedis/cothority/deployments","created_at":"2015-09-02T09:13:57Z","updated_at":"2016-04-08T00:17:26Z","pushed_at":"2016-04-08T12:42:43Z","git_url":"git://github.com/dedis/cothority.git","ssh_url":"git@github.com:dedis/cothority.git","clone_url":"https://github.com/dedis/cothority.git","svn_url":"https://github.com/dedis/cothority","homepage":"","size":52180,"stargazers_count":97,"watchers_count":97,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":51,"forks":7,"open_issues":51,"watchers":97,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dedis/cothority/pulls/339"},"html":{"href":"https://github.com/dedis/cothority/pull/339"},"issue":{"href":"https://api.github.com/repos/dedis/cothority/issues/339"},"comments":{"href":"https://api.github.com/repos/dedis/cothority/issues/339/comments"},"review_comments":{"href":"https://api.github.com/repos/dedis/cothority/pulls/339/comments"},"review_comment":{"href":"https://api.github.com/repos/dedis/cothority/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dedis/cothority/pulls/339/commits"},"statuses":{"href":"https://api.github.com/repos/dedis/cothority/statuses/728f1eb9f44f9a58953227597718450a8749c769"}}}}