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

Fingerprint of public keys #175

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
10 changes: 6 additions & 4 deletions client/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -808,10 +808,11 @@ func (c *cliClient) showIdentity() {
heading: "Identity",
rows: []cliRow{
cliRow{cols: []string{"Server", terminalEscape(c.server, false)}},
cliRow{cols: []string{"Public identity", fmt.Sprintf("%x", c.identityPublic[:])}},
cliRow{cols: []string{"Fingerprint", fmt.Sprintf("%d", c.fingerprint())}},
cliRow{cols: []string{"Public key", fmt.Sprintf("%x", c.pub[:])}},
cliRow{cols: []string{"Identity key", fmt.Sprintf("%x", c.identityPublic[:])}},
cliRow{cols: []string{"Generation", fmt.Sprintf("%d", c.generation)}},
cliRow{cols: []string{"State file", terminalEscape(c.stateFilename, false)}},
cliRow{cols: []string{"Group generation", fmt.Sprintf("%d", c.generation)}},
},
}
table.WriteTo(c.term)
Expand Down Expand Up @@ -1858,9 +1859,10 @@ func (c *cliClient) showContact(contact *Contact) {
rows: []cliRow{
cliRow{cols: []string{"Name", terminalEscape(contact.name, false)}},
cliRow{cols: []string{"Server", terminalEscape(contact.theirServer, false)}},
cliRow{cols: []string{"Generation", fmt.Sprintf("%d", contact.generation)}},
cliRow{cols: []string{"Public key", fmt.Sprintf("%x", contact.theirPub[:])}},
cliRow{cols: []string{"Fingerprint", fmt.Sprintf("%d", contact.fingerprint())}},
cliRow{cols: []string{"Identity key", fmt.Sprintf("%x", contact.theirIdentityPublic[:])}},
cliRow{cols: []string{"Public key", fmt.Sprintf("%x", contact.theirPub[:])}},
cliRow{cols: []string{"Generation", fmt.Sprintf("%d", contact.generation)}},
cliRow{cols: []string{"Client version", fmt.Sprintf("%d", contact.supportedVersion)}},
},
}
Expand Down
56 changes: 43 additions & 13 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,17 @@ type Contact struct {
cliId cliId
}

func (contact *Contact) fingerprint() []byte {
if contact.isPending {
return []byte{}
}
return fingerprint(contact.theirPub[:])
}

func (c *client) fingerprint() []byte {
return fingerprint(c.pub[:])
}

// Event represents a log entry. This does not apply to the global log, which
// is quite chatty, but rather to significant events related to a given
// contact. These events are surfaced in the UI and recorded in the statefile.
Expand Down Expand Up @@ -802,11 +813,8 @@ func (c *client) loadUI() error {
copy(c.priv[:], priv[:])
copy(c.pub[:], pub[:])

if c.disableV2Ratchet {
c.randBytes(c.identity[:])
} else {
extra25519.PrivateKeyToCurve25519(&c.identity, priv)
}
// Avoid tying identity to pub to keep pub from being a selector
c.randBytes(c.identity[:])
curve25519.ScalarBaseMult(&c.identityPublic, &c.identity)

c.groupPriv, err = bbssig.GenerateGroup(rand.Reader)
Expand Down Expand Up @@ -907,6 +915,17 @@ func (contact *Contact) indicator() Indicator {
return indicatorNone
}

func (contact *Contact) ratchetVersion(disableV2Ratchet bool) int32 {
if disableV2Ratchet || contact.supportedVersion < 1 {
return 1
}
if protoVersion <= contact.supportedVersion {
return protoVersion
} else {
return contact.supportedVersion
}
}

func (contact *Contact) processKeyExchange(kxsBytes []byte, testing, simulateOldClient, disableV2Ratchet bool) error {
var kxs pond.SignedKeyExchange
if err := proto.Unmarshal(kxsBytes, &kxs); err != nil {
Expand Down Expand Up @@ -951,6 +970,11 @@ func (contact *Contact) processKeyExchange(kxsBytes []byte, testing, simulateOld
}
copy(contact.theirIdentityPublic[:], kx.IdentityPublic)

// Contact might be using the v2 ratchet if kx.SupportedVersion exists
if kx.SupportedVersion != nil {
contact.supportedVersion = *kx.SupportedVersion
}

if simulateOldClient {
kx.Dh1 = nil
}
Expand All @@ -966,12 +990,9 @@ func (contact *Contact) processKeyExchange(kxsBytes []byte, testing, simulateOld
copy(contact.theirCurrentDHPublic[:], kx.Dh)
contact.ratchet = nil
} else {
// If the identity and ed25519 public keys are the same (modulo
// isomorphism) then the contact is using the v2 ratchet.
var ed25519Public, curve25519Public [32]byte
copy(ed25519Public[:], kx.PublicKey)
extra25519.PublicKeyToCurve25519(&curve25519Public, &ed25519Public)
v2 := !disableV2Ratchet && bytes.Equal(curve25519Public[:], kx.IdentityPublic[:])
// Just leave contact.supportedVersion=0 if not specified, but maybe
// worth setting supportedVersion=1 if we've thought about it more.
v2 := (contact.ratchetVersion(disableV2Ratchet) == 2)
if err := contact.ratchet.CompleteKeyExchange(&kx, v2); err != nil {
return err
}
Expand Down Expand Up @@ -1035,11 +1056,20 @@ func (c *client) registerId(id uint64) {
}

func (c *client) newRatchet(contact *Contact) *ratchet.Ratchet {
// contact.ratchetVersion(disableV2Ratchet) == 2
r := ratchet.New(c.rand)
r.MyIdentityPrivate = &c.identity
r.MySigningPublic = &c.pub
r.TheirIdentityPublic = &contact.theirIdentityPublic
r.TheirSigningPublic = &contact.theirPub
switch contact.ratchetVersion(c.disableV2Ratchet) {
case 1:
r.MyIdentityPrivate = &c.identity
r.TheirIdentityPublic = &contact.theirIdentityPublic
case 2:
r.MyIdentityPrivate = new([32]byte)
extra25519.PrivateKeyToCurve25519(r.MyIdentityPrivate, &c.priv)
r.TheirIdentityPublic = new([32]byte)
extra25519.PublicKeyToCurve25519(r.TheirIdentityPublic, &contact.theirPub)
}
return r
}

Expand Down
8 changes: 8 additions & 0 deletions client/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ import (
"golang.org/x/crypto/curve25519"
)

//go:generate protoc --proto_path=$GOPATH/src:. --gogo_out=. disk/client.proto

// We use gogoprotobuf from https://code.google.com/p/gogoprotobuf/ because
// Francesc @Campoy indicated that even Google uses it over goprotobuf.
// See 29d5f5d16f523b0a113e786143fc4dacc8affa97 for goprotobuf scripts like :
// protoc --proto_path=$GOPATH/src:. --go_out=. disk/client.proto
// perl -p -i~ -e 's/(import protos \"github.com\/agl\/pond\/protos)\/pond.pb\"/$1\"/' disk/client.pb.go

// erasureRotationTime is the amount of time that we'll use a single erasure
// storage value before rotating.
const erasureRotationTime = 24 * time.Hour
Expand Down
Loading