@@ -69,11 +69,11 @@ import (
69
69
"sync"
70
70
"time"
71
71
72
- "code.google.com/p/go.crypto/curve25519"
73
72
"code.google.com/p/goprotobuf/proto"
74
73
"github.com/agl/ed25519"
75
74
"github.com/agl/pond/bbssig"
76
75
"github.com/agl/pond/client/disk"
76
+ "github.com/agl/pond/client/ratchet"
77
77
"github.com/agl/pond/panda"
78
78
pond "github.com/agl/pond/protos"
79
79
)
@@ -200,6 +200,10 @@ type client struct {
200
200
// nowFunc is a function that, if not nil, will be used by the GUI to
201
201
// get the current time. This is used in testing.
202
202
nowFunc func () time.Time
203
+
204
+ // simulateOldClient causes the client to act like a pre-ratchet client
205
+ // for testing purposes.
206
+ simulateOldClient bool
203
207
}
204
208
205
209
// UI abstracts behaviour that is specific to a given interface (GUI or CLI).
@@ -406,11 +410,14 @@ type Contact struct {
406
410
// exchange failed.
407
411
pandaResult string
408
412
409
- lastDHPrivate [ 32 ] byte
410
- currentDHPrivate [32 ]byte
411
-
413
+ // Members for the old ratchet.
414
+ lastDHPrivate [32 ]byte
415
+ currentDHPrivate [ 32 ] byte
412
416
theirLastDHPublic [32 ]byte
413
417
theirCurrentDHPublic [32 ]byte
418
+
419
+ // New ratchet support.
420
+ ratchet * ratchet.Ratchet
414
421
}
415
422
416
423
// previousTagLifetime contains the amount of time that we'll store a previous
@@ -679,7 +686,7 @@ func (c *client) loadUI() error {
679
686
return nil
680
687
}
681
688
682
- func (contact * Contact ) processKeyExchange (kxsBytes []byte , testing bool ) error {
689
+ func (contact * Contact ) processKeyExchange (kxsBytes []byte , testing , simulateOldClient bool ) error {
683
690
var kxs pond.SignedKeyExchange
684
691
if err := proto .Unmarshal (kxsBytes , & kxs ); err != nil {
685
692
return err
@@ -723,10 +730,25 @@ func (contact *Contact) processKeyExchange(kxsBytes []byte, testing bool) error
723
730
}
724
731
copy (contact .theirIdentityPublic [:], kx .IdentityPublic )
725
732
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
+ }
728
751
}
729
- copy (contact .theirCurrentDHPublic [:], kx .Dh )
730
752
731
753
contact .generation = * kx .Generation
732
754
@@ -774,26 +796,34 @@ func (c *client) registerId(id uint64) {
774
796
c .usedIds [id ] = true
775
797
}
776
798
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
+
777
808
func (c * client ) newKeyExchange (contact * Contact ) {
778
809
var err error
779
- c .randBytes (contact .lastDHPrivate [:])
780
- c .randBytes (contact .currentDHPrivate [:])
781
-
782
- var pub [32 ]byte
783
- curve25519 .ScalarBaseMult (& pub , & contact .lastDHPrivate )
784
810
if contact .groupKey , err = c .groupPriv .NewMember (c .rand ); err != nil {
785
811
panic (err )
786
812
}
813
+ contact .ratchet = c .newRatchet (contact )
787
814
788
815
kx := & pond.KeyExchange {
789
816
PublicKey : c .pub [:],
790
817
IdentityPublic : c .identityPublic [:],
791
818
Server : proto .String (c .server ),
792
- Dh : pub [:],
793
819
Group : contact .groupKey .Group .Marshal (),
794
820
GroupKey : contact .groupKey .Marshal (),
795
821
Generation : proto .Uint32 (c .generation ),
796
822
}
823
+ contact .ratchet .FillKeyExchange (kx )
824
+ if c .simulateOldClient {
825
+ kx .Dh1 = nil
826
+ }
797
827
798
828
kxBytes , err := proto .Marshal (kx )
799
829
if err != nil {
0 commit comments