@@ -69,11 +69,11 @@ import (
6969"sync"
7070"time"
7171
72- "code.google.com/p/go.crypto/curve25519"
7372"code.google.com/p/goprotobuf/proto"
7473"github.com/agl/ed25519"
7574"github.com/agl/pond/bbssig"
7675"github.com/agl/pond/client/disk"
76+ "github.com/agl/pond/client/ratchet"
7777"github.com/agl/pond/panda"
7878pond"github.com/agl/pond/protos"
7979)
@@ -200,6 +200,10 @@ type client struct {
200200// nowFunc is a function that, if not nil, will be used by the GUI to
201201// get the current time. This is used in testing.
202202nowFunc func () time.Time
203+
204+ // simulateOldClient causes the client to act like a pre-ratchet client
205+ // for testing purposes.
206+ simulateOldClient bool
203207}
204208
205209// UI abstracts behaviour that is specific to a given interface (GUI or CLI).
@@ -406,11 +410,14 @@ type Contact struct {
406410// exchange failed.
407411pandaResult string
408412
409- lastDHPrivate [ 32 ] byte
410- currentDHPrivate [32 ]byte
411-
413+ // Members for the old ratchet.
414+ lastDHPrivate [32 ]byte
415+ currentDHPrivate [ 32 ] byte
412416theirLastDHPublic [32 ]byte
413417theirCurrentDHPublic [32 ]byte
418+
419+ // New ratchet support.
420+ ratchet * ratchet.Ratchet
414421}
415422
416423// previousTagLifetime contains the amount of time that we'll store a previous
@@ -679,7 +686,7 @@ func (c *client) loadUI() error {
679686return nil
680687}
681688
682- func (contact * Contact )processKeyExchange (kxsBytes []byte ,testing bool )error {
689+ func (contact * Contact )processKeyExchange (kxsBytes []byte ,testing , simulateOldClient bool )error {
683690var kxs pond.SignedKeyExchange
684691if err := proto .Unmarshal (kxsBytes ,& kxs );err != nil {
685692return err
@@ -723,10 +730,25 @@ func (contact *Contact) processKeyExchange(kxsBytes []byte, testing bool) error
723730}
724731copy (contact .theirIdentityPublic [:],kx .IdentityPublic )
725732
726- if len (kx .Dh )!= len (contact .theirCurrentDHPublic ) {
727- return errors .New ("invalid public DH value" )
733+ if simulateOldClient {
734+ kx .Dh1 = nil
735+ }
736+
737+ if len (kx .Dh1 )== 0 {
738+ // They are using an old-style ratchet. We have to extract the
739+ // private value from the Ratchet in order to use it with the
740+ // old code.
741+ contact .lastDHPrivate = contact .ratchet .GetKXPrivateForTransition ()
742+ if len (kx .Dh )!= len (contact .theirCurrentDHPublic ) {
743+ return errors .New ("invalid public DH value" )
744+ }
745+ copy (contact .theirCurrentDHPublic [:],kx .Dh )
746+ contact .ratchet = nil
747+ }else {
748+ if err := contact .ratchet .CompleteKeyExchange (& kx );err != nil {
749+ return err
750+ }
728751}
729- copy (contact .theirCurrentDHPublic [:],kx .Dh )
730752
731753contact .generation = * kx .Generation
732754
@@ -774,26 +796,34 @@ func (c *client) registerId(id uint64) {
774796c .usedIds [id ]= true
775797}
776798
799+ func (c * client )newRatchet (contact * Contact )* ratchet.Ratchet {
800+ r := ratchet .New (c .rand )
801+ r .MyIdentityPrivate = & c .identity
802+ r .MySigningPublic = & c .pub
803+ r .TheirIdentityPublic = & contact .theirIdentityPublic
804+ r .TheirSigningPublic = & contact .theirPub
805+ return r
806+ }
807+
777808func (c * client )newKeyExchange (contact * Contact ) {
778809var err error
779- c .randBytes (contact .lastDHPrivate [:])
780- c .randBytes (contact .currentDHPrivate [:])
781-
782- var pub [32 ]byte
783- curve25519 .ScalarBaseMult (& pub ,& contact .lastDHPrivate )
784810if contact .groupKey ,err = c .groupPriv .NewMember (c .rand );err != nil {
785811panic (err )
786812}
813+ contact .ratchet = c .newRatchet (contact )
787814
788815kx := & pond.KeyExchange {
789816PublicKey :c .pub [:],
790817IdentityPublic :c .identityPublic [:],
791818Server :proto .String (c .server ),
792- Dh :pub [:],
793819Group :contact .groupKey .Group .Marshal (),
794820GroupKey :contact .groupKey .Marshal (),
795821Generation :proto .Uint32 (c .generation ),
796822}
823+ contact .ratchet .FillKeyExchange (kx )
824+ if c .simulateOldClient {
825+ kx .Dh1 = nil
826+ }
797827
798828kxBytes ,err := proto .Marshal (kx )
799829if err != nil {