Skip to content

Commit

Permalink
Merge branch 'master' into auditor-protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
masomel committed Feb 16, 2017
2 parents 6577d92 + deb0140 commit 8d48156
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 104 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ env:

script:
- test -z "$(go fmt ./...)"
- go vet ./...
- ./test_coverage.sh

after_success:
Expand Down
6 changes: 5 additions & 1 deletion client/coniksclient/internal/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"fmt"
"os"
"time"

"github.com/coniks-sys/coniks-go/client"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -38,6 +39,9 @@ func loadConfigOrExit(cmd *cobra.Command) *client.Config {
}

// append "\r\n" to msg and then write to terminal in raw mode.
func writeLineInRawMode(term *terminal.Terminal, msg string) {
func writeLineInRawMode(term *terminal.Terminal, msg string, printTimestamp bool) {
if printTimestamp {
term.Write([]byte("<" + time.Now().Format("15:04:05.999999999") + "> "))
}
term.Write([]byte(msg + "\r\n"))
}
48 changes: 34 additions & 14 deletions client/coniksclient/internal/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"log"
"net/url"
"os"
"strconv"
"strings"

"github.com/coniks-sys/coniks-go/client"
Expand All @@ -17,9 +18,13 @@ const help = "- register [name] [key]:\r\n" +
" Register a new name-to-key binding on the CONIKS-server.\r\n" +
"- lookup [name]:\r\n" +
" Lookup the key of some known contact or your own bindings.\r\n" +
"- enable timestamp:\r\n" +
" Print timestamp of format <15:04:05.999999999> along with the result.\r\n" +
"- disable timestamp:\r\n" +
" Disable timestamp printing.\r\n" +
"- help:\r\n" +
" Display this message.\r\n" +
"- exit:\r\n" +
"- exit, q:\r\n" +
" Close the REPL and exit the client."

var runCmd = &cobra.Command{
Expand All @@ -35,9 +40,11 @@ func init() {
RootCmd.AddCommand(runCmd)
runCmd.Flags().StringP("config", "c", "config.toml",
"Config file for the client (contains the server's initial public key etc).")
runCmd.Flags().BoolP("debug", "d", false, "Turn on debugging mode")
}

func run(cmd *cobra.Command) {
isDebugging, _ := strconv.ParseBool(cmd.Flag("debug").Value.String())
conf := loadConfigOrExit(cmd)
cc := p.NewCC(nil, true, conf.SigningPubKey)

Expand All @@ -50,41 +57,54 @@ func run(cmd *cobra.Command) {
for {
line, err := term.ReadLine()
if err != nil {
writeLineInRawMode(term, err.Error())
writeLineInRawMode(term, err.Error(), isDebugging)
return
}

args := strings.Fields(line)
if len(args) < 1 {
writeLineInRawMode(term, `[!] Type "help" for more information.`)
writeLineInRawMode(term, `[!] Type "help" for more information.`, isDebugging)
continue
}
cmd := args[0]

switch cmd {
case "exit":
writeLineInRawMode(term, "[+] See ya.")
case "exit", "q":
writeLineInRawMode(term, "[+] See ya.", isDebugging)
return
case "help":
writeLineInRawMode(term, help)
continue
writeLineInRawMode(term, help, false) // turn off debugging mode for this command
case "enable", "disable":
if len(args) != 2 {
writeLineInRawMode(term, "[!] Unrecognized command: "+line, isDebugging)
continue
}
switch args[1] {
case "timestamp":
if cmd == "enable" {
isDebugging = true
} else {
isDebugging = false
}
default:
writeLineInRawMode(term, "[!] Unrecognized command: "+line, isDebugging)
}
case "register":
if len(args) != 3 {
writeLineInRawMode(term, "[!] Incorrect number of args to register.")
writeLineInRawMode(term, "[!] Incorrect number of args to register.", isDebugging)
continue
}
msg := register(cc, conf, args[1], args[2])
writeLineInRawMode(term, "[+] "+msg)
writeLineInRawMode(term, "[+] "+msg, isDebugging)
case "lookup":
if len(args) != 2 {
writeLineInRawMode(term, "[!] Incorrect number of args to lookup.")
writeLineInRawMode(term, "[!] Incorrect number of args to lookup.", isDebugging)
continue
}
msg := keyLookup(cc, conf, args[1])
writeLineInRawMode(term, "[+] "+msg)
writeLineInRawMode(term, "[+] "+msg, isDebugging)
default:
writeLineInRawMode(term, "[!] Unrecognized command: "+cmd)
continue
writeLineInRawMode(term, "[!] Unrecognized command: "+cmd, isDebugging)
}
}
}
Expand Down Expand Up @@ -170,7 +190,7 @@ func keyLookup(cc *p.ConsistencyChecks, conf *client.Config, name string) string
return ("Invalid config!")
}

response := client.UnmarshalResponse(p.RegistrationType, res)
response := client.UnmarshalResponse(p.KeyLookupType, res)
if key, ok := cc.Bindings[name]; ok {
err = cc.HandleResponse(p.KeyLookupType, response, name, []byte(key))
} else {
Expand Down
8 changes: 0 additions & 8 deletions client/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package client
import (
"encoding/json"

"github.com/coniks-sys/coniks-go/merkletree"
p "github.com/coniks-sys/coniks-go/protocol"
)

Expand Down Expand Up @@ -43,13 +42,6 @@ func UnmarshalResponse(t int, msg []byte) *p.Response {
Error: p.ErrMalformedDirectoryMessage,
}
}
policies := &p.Policies{}
if err := json.Unmarshal([]byte(response.STR.Ad.(merkletree.RawAd)), policies); err != nil {
return &p.Response{
Error: p.ErrMalformedDirectoryMessage,
}
}
response.STR.Ad = policies
return &p.Response{
Error: res.Error,
DirectoryResponse: response,
Expand Down
15 changes: 15 additions & 0 deletions client/encoding_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package client

import (
"bytes"
"encoding/json"
"testing"

"github.com/coniks-sys/coniks-go/keyserver"
"github.com/coniks-sys/coniks-go/protocol"
)

Expand Down Expand Up @@ -32,3 +34,16 @@ func TestUnmarshalMalformedErrorResponse(t *testing.T) {
"got", res.Error)
}
}

func TestUnmarshalSampleMessage(t *testing.T) {
d, _ := protocol.NewTestDirectory(t, true)
res, _ := d.Register(&protocol.RegistrationRequest{
Username: "alice",
Key: []byte("key")})
msg, _ := keyserver.MarshalResponse(res)
response := UnmarshalResponse(protocol.RegistrationType, []byte(msg))
str := response.DirectoryResponse.(*protocol.DirectoryProof).STR
if !bytes.Equal(d.LatestSTR().Serialize(), str.Serialize()) {
t.Error("Cannot unmarshal Associate Data properly")
}
}
13 changes: 8 additions & 5 deletions merkletree/merkletree.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,14 @@ func (m *MerkleTree) Get(lookupIndex []byte) *AuthenticationPath {
case *userLeafNode:
pNode := nodePointer.(*userLeafNode)
authPath.Leaf = &ProofNode{
Level: pNode.level,
Index: pNode.index,
Value: pNode.value,
IsEmpty: false,
Commitment: &crypto.Commit{pNode.commitment.Salt, pNode.commitment.Value},
Level: pNode.level,
Index: pNode.index,
Value: pNode.value,
IsEmpty: false,
Commitment: &crypto.Commit{
Salt: pNode.commitment.Salt,
Value: pNode.commitment.Value,
},
}
if bytes.Equal(nodePointer.(*userLeafNode).index, lookupIndex) {
return authPath
Expand Down
56 changes: 13 additions & 43 deletions merkletree/str.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package merkletree
import (
"bytes"

"encoding/json"

"github.com/coniks-sys/coniks-go/crypto"
"github.com/coniks-sys/coniks-go/crypto/sign"
"github.com/coniks-sys/coniks-go/utils"
Expand All @@ -29,44 +27,7 @@ type SignedTreeRoot struct {
PreviousEpoch uint64
PreviousSTRHash []byte
Signature []byte
Ad AssocData
}

// TODO(arlolra): Look into using a DirSTR instead, to avoid this mess.

// RawAd makes json.RawMessage implement the AssocData interface.
type RawAd json.RawMessage

// Serialize should never be called.
func (r RawAd) Serialize() []byte {
panic("[str] Should never be called")
return nil
}

// UnmarshalJSON returns the STR with a json.RawMessage as AssocData for
// further unmarshalling by the caller.
func (str *SignedTreeRoot) UnmarshalJSON(m []byte) error {
type Str struct {
tree *MerkleTree
TreeHash []byte
Epoch uint64
PreviousEpoch uint64
PreviousSTRHash []byte
Signature []byte
Ad json.RawMessage
}
hStr := &Str{}
if err := json.Unmarshal(m, hStr); err != nil {
return err
}
str.tree = hStr.tree
str.TreeHash = hStr.TreeHash
str.Epoch = hStr.Epoch
str.PreviousEpoch = hStr.PreviousEpoch
str.PreviousSTRHash = hStr.PreviousSTRHash
str.Signature = hStr.Signature
str.Ad = RawAd(hStr.Ad)
return nil
Ad AssocData `json:"-"`
}

// NewSTR constructs a SignedTreeRoot with the given signing key pair,
Expand All @@ -90,17 +51,26 @@ func NewSTR(key sign.PrivateKey, ad AssocData, m *MerkleTree, epoch uint64, prev
return str
}

// Serialize serializes the signed tree root into
// a specified format for signing.
// Serialize serializes the signed tree root
// and its associated data into a specified format for signing.
// One should use this function for signing as well as
// verifying the signature.
// Any composition struct of SignedTreeRoot with
// a specific AssocData should override this method.
func (str *SignedTreeRoot) Serialize() []byte {
return append(str.SerializeInternal(), str.Ad.Serialize()...)
}

// SerializeInternal serializes the signed tree root into
// a specified format.
func (str *SignedTreeRoot) SerializeInternal() []byte {
var strBytes []byte
strBytes = append(strBytes, utils.ULongToBytes(str.Epoch)...) // t - epoch number
if str.Epoch > 0 {
strBytes = append(strBytes, utils.ULongToBytes(str.PreviousEpoch)...) // t_prev - previous epoch number
}
strBytes = append(strBytes, str.TreeHash...) // root
strBytes = append(strBytes, str.PreviousSTRHash...) // previous STR hash
strBytes = append(strBytes, str.Ad.Serialize()...)
return strBytes
}

Expand Down
2 changes: 1 addition & 1 deletion merkletree/str_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ func TestVerifyHashChain(t *testing.T) {

keyPrefix := "key"
valuePrefix := []byte("value")
pad, err := NewPAD(TestAd{""}, signKey, vrfPrivKey1, 10)
pad, err := NewPAD(TestAd{"abc"}, signKey, vrfPrivKey1, 10)
if err != nil {
t.Fatal(err)
}
Expand Down
19 changes: 7 additions & 12 deletions protocol/consistencychecks.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
// client request.
type ConsistencyChecks struct {
// SavedSTR stores the latest verified signed tree root.
SavedSTR *m.SignedTreeRoot
SavedSTR *DirSTR
Bindings map[string][]byte

// extensions settings
Expand All @@ -39,7 +39,7 @@ type ConsistencyChecks struct {
// NewCC creates an instance of ConsistencyChecks using
// a CONIKS directory's pinned STR at epoch 0, or
// the consistency state read from persistent storage.
func NewCC(savedSTR *m.SignedTreeRoot, useTBs bool, signKey sign.PublicKey) *ConsistencyChecks {
func NewCC(savedSTR *DirSTR, useTBs bool, signKey sign.PublicKey) *ConsistencyChecks {
// TODO: see #110
if !useTBs {
panic("[coniks] Currently the server is forced to use TBs")
Expand Down Expand Up @@ -101,7 +101,7 @@ func (cc *ConsistencyChecks) HandleResponse(requestType int, msg *Response,
}

func (cc *ConsistencyChecks) updateSTR(requestType int, msg *Response) error {
var str *m.SignedTreeRoot
var str *DirSTR
switch requestType {
case RegistrationType, KeyLookupType:
str = msg.DirectoryResponse.(*DirectoryProof).STR
Expand Down Expand Up @@ -132,7 +132,7 @@ func (cc *ConsistencyChecks) updateSTR(requestType int, msg *Response) error {

// verifySTR checks whether the received STR is the same with
// the SavedSTR using reflect.DeepEqual().
func (cc *ConsistencyChecks) verifySTR(str *m.SignedTreeRoot) error {
func (cc *ConsistencyChecks) verifySTR(str *DirSTR) error {
if reflect.DeepEqual(cc.SavedSTR, str) {
return nil
}
Expand All @@ -154,7 +154,6 @@ func verifySTRConsistency(signKey sign.PublicKey, savedSTR, str *m.SignedTreeRoo
if str.VerifyHashChain(savedSTR) {
return nil
}

// TODO: verify the directory's policies as well. See #115
return CheckBadSTR
}
Expand Down Expand Up @@ -218,12 +217,9 @@ func (cc *ConsistencyChecks) verifyKeyLookup(msg *Response,
return CheckPassed
}

func verifyAuthPath(uname string, key []byte,
ap *m.AuthenticationPath,
str *m.SignedTreeRoot) error {

func verifyAuthPath(uname string, key []byte, ap *m.AuthenticationPath, str *DirSTR) error {
// verify VRF Index
vrfKey := GetPolicies(str).VrfPublicKey
vrfKey := str.Policies.VrfPublicKey
if !vrfKey.Verify([]byte(uname), ap.LookupIndex, ap.VrfProof) {
return CheckBadVRFProof
}
Expand Down Expand Up @@ -293,8 +289,7 @@ func (cc *ConsistencyChecks) updateTBs(requestType int, msg *Response,

// verifyFulfilledPromise verifies issued TBs were inserted
// in the directory as promised.
func (cc *ConsistencyChecks) verifyFulfilledPromise(uname string,
str *m.SignedTreeRoot,
func (cc *ConsistencyChecks) verifyFulfilledPromise(uname string, str *DirSTR,
ap *m.AuthenticationPath) error {
// FIXME: Which epoch did this lookup happen in?
if tb, ok := cc.TBs[uname]; ok {
Expand Down
15 changes: 10 additions & 5 deletions protocol/consistencychecks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,21 @@ func lookupAndVerify(d *ConiksDirectory, cc *ConsistencyChecks,

func TestVerifyWithError(t *testing.T) {
d, pk := NewTestDirectory(t, true)
str := d.LatestSTR()

// modify the pinning STR so that the consistency check should fail.
str := *(d.LatestSTR())
str.Signature = append([]byte{}, str.Signature...)
str.Signature[0]++
str2 := *str.SignedTreeRoot
str2.Signature = append([]byte{}, str.Signature...)
str2.Signature[0]++
str.SignedTreeRoot = &str2

cc := NewCC(&str, true, pk)
cc := NewCC(str, true, pk)

if e1, e2 := registerAndVerify(d, cc, alice, key); e1 != ReqSuccess || e2 != CheckBadSTR {
e1, e2 := registerAndVerify(d, cc, alice, key)
if e1 != ReqSuccess {
t.Error("Expect", ReqSuccess, "got", e1)
}
if e2 != CheckBadSTR {
t.Error("Expect", CheckBadSTR, "got", e2)
}
}
Expand Down
Loading

0 comments on commit 8d48156

Please sign in to comment.