Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OTRv4
otrv4_reference_design
Commits
0936f0d3
Commit
0936f0d3
authored
Nov 23, 2016
by
Reinaldo de Souza Jr
Browse files
Just copy double_ratchet.go to compare changes
parent
46cfc784
Changes
1
Hide whitespace changes
Inline
Side-by-side
simple_double_ratchet.go
0 → 100644
View file @
0936f0d3
package
main
import
(
"bytes"
"fmt"
"golang.org/x/crypto/sha3"
"github.com/twstrike/ed448"
)
const
(
Q
=
iota
P1
P2
D
)
type
Msg
struct
{
mtype
int
sender
string
rid
,
mid
int
dh
pubkey
encKey
key
// this is here only to check if we can decrypt
}
func
(
m
Msg
)
decryptWith
(
k
key
)
{
if
!
bytes
.
Equal
(
k
,
m
.
encKey
)
{
panic
(
"failed to decrypt message."
)
}
}
var
c
=
ed448
.
NewCurve
()
var
NULLSEC
=
seckey
{}
var
NULLPUB
=
pubkey
{}
type
seckey
[
144
]
byte
type
pubkey
[
56
]
byte
type
key
[]
byte
type
Entity
struct
{
name
string
our_dh_pub
,
their_dh
pubkey
our_dh_priv
seckey
R
[]
key
Ca
,
Cb
[]
key
rid
,
j
,
k
int
}
func
(
e
*
Entity
)
sendData
()
Msg
{
var
cj
key
if
e
.
j
==
0
{
fmt
.
Println
()
fmt
.
Printf
(
"%s
\t
Ratcheting...
\n
"
,
e
.
name
)
e
.
our_dh_priv
,
e
.
our_dh_pub
,
_
=
c
.
GenerateKeys
()
e
.
rid
+=
1
secret
:=
c
.
ComputeSecret
(
e
.
our_dh_priv
,
e
.
their_dh
)
e
.
derive
(
secret
[
:
])
}
cj
=
e
.
retriveChainkey
(
e
.
rid
,
e
.
j
)
toSend
:=
Msg
{
D
,
e
.
name
,
e
.
rid
,
e
.
j
,
e
.
our_dh_pub
,
cj
}
e
.
j
+=
1
fmt
.
Printf
(
"%s
\t
sending: %v
\n
"
,
e
.
name
,
toSend
)
fmt
.
Printf
(
"%s
\t
our key: %x
\n
"
,
e
.
name
,
cj
)
return
toSend
}
func
(
e
*
Entity
)
receive
(
m
Msg
)
{
fmt
.
Println
()
fmt
.
Printf
(
"%s
\t
receive: %v
\n
"
,
e
.
name
,
m
)
switch
m
.
mtype
{
case
D
:
e
.
receiveData
(
m
)
break
case
Q
:
break
case
P1
:
e
.
receiveP1
(
m
)
break
case
P2
:
e
.
receiveP2
(
m
)
break
}
}
func
(
e
*
Entity
)
receiveP1
(
m
Msg
)
{
e
.
their_dh
=
m
.
dh
e
.
rid
=
e
.
rid
+
1
if
bytes
.
Compare
(
e
.
our_dh_priv
[
:
],
NULLSEC
[
:
])
==
1
{
secret
:=
c
.
ComputeSecret
(
e
.
our_dh_priv
,
e
.
their_dh
)
e
.
derive
(
secret
[
:
])
}
}
func
(
e
*
Entity
)
receiveP2
(
m
Msg
)
{
e
.
their_dh
=
m
.
dh
e
.
rid
=
e
.
rid
+
1
secret
:=
c
.
ComputeSecret
(
e
.
our_dh_priv
,
e
.
their_dh
)
e
.
derive
(
secret
[
:
])
}
func
(
e
*
Entity
)
receiveData
(
m
Msg
)
{
ck
:=
make
([]
byte
,
64
)
if
m
.
rid
==
e
.
rid
+
1
{
fmt
.
Printf
(
"%s
\t
Follow Ratcheting...
\n
"
,
e
.
name
)
e
.
rid
=
m
.
rid
e
.
their_dh
=
m
.
dh
secret
:=
c
.
ComputeSecret
(
e
.
our_dh_priv
,
e
.
their_dh
)
e
.
derive
(
secret
[
:
])
e
.
j
=
0
// need to ratchet next time when send
}
else
if
e
.
k
>
m
.
mid
{
//panic("we received a message delayed out of order")
}
e
.
k
=
m
.
mid
ck
=
e
.
retriveChainkey
(
m
.
rid
,
m
.
mid
)
fmt
.
Printf
(
"%s
\t
their key: %x
\n
"
,
e
.
name
,
ck
)
m
.
decryptWith
(
ck
)
}
func
(
e
*
Entity
)
wasAliceAt
(
rid
int
)
bool
{
return
rid
%
2
==
1
}
func
(
e
*
Entity
)
retriveChainkey
(
rid
,
mid
int
)
key
{
var
ck
key
buf
:=
make
([]
byte
,
64
)
if
e
.
wasAliceAt
(
rid
)
{
ck
=
e
.
Ca
[
rid
]
}
else
{
ck
=
e
.
Cb
[
rid
]
}
copy
(
buf
,
ck
)
for
i
:=
mid
;
i
>
0
;
i
--
{
sha3
.
ShakeSum256
(
buf
,
buf
)
}
return
buf
}
func
(
e
*
Entity
)
derive
(
secret
[]
byte
)
{
r
:=
make
([]
byte
,
64
)
ca
:=
make
([]
byte
,
64
)
cb
:=
make
([]
byte
,
64
)
if
len
(
e
.
R
)
>
0
{
secret
=
append
(
secret
,
e
.
R
[
e
.
rid
-
1
]
...
)
}
sha3
.
ShakeSum256
(
r
,
append
(
secret
,
0
))
sha3
.
ShakeSum256
(
ca
,
append
(
secret
,
1
))
sha3
.
ShakeSum256
(
cb
,
append
(
secret
,
2
))
e
.
R
=
append
(
e
.
R
,
r
)
e
.
Ca
=
append
(
e
.
Ca
,
ca
)
e
.
Cb
=
append
(
e
.
Cb
,
cb
)
}
func
(
e
*
Entity
)
query
()
Msg
{
toSend
:=
Msg
{
mtype
:
Q
,
sender
:
e
.
name
}
fmt
.
Printf
(
"%s
\t
sending: %v
\n
"
,
e
.
name
,
toSend
)
return
toSend
}
func
(
e
*
Entity
)
sendP1
()
Msg
{
e
.
our_dh_priv
,
e
.
our_dh_pub
,
_
=
c
.
GenerateKeys
()
e
.
j
=
1
e
.
rid
=
e
.
rid
+
1
if
bytes
.
Compare
(
e
.
their_dh
[
:
],
NULLPUB
[
:
])
==
1
{
secret
:=
c
.
ComputeSecret
(
e
.
our_dh_priv
,
e
.
their_dh
)
e
.
derive
(
secret
[
:
])
}
toSend
:=
Msg
{
P1
,
e
.
name
,
-
1
,
-
1
,
e
.
our_dh_pub
,
nil
}
fmt
.
Printf
(
"%s
\t
sending: %v
\n
"
,
e
.
name
,
toSend
)
return
toSend
}
func
(
e
*
Entity
)
sendP2
()
Msg
{
e
.
j
=
0
e
.
rid
=
e
.
rid
+
1
e
.
our_dh_priv
,
e
.
our_dh_pub
,
_
=
c
.
GenerateKeys
()
secret
:=
c
.
ComputeSecret
(
e
.
our_dh_priv
,
e
.
their_dh
)
e
.
derive
(
secret
[
:
])
toSend
:=
Msg
{
P2
,
e
.
name
,
-
1
,
-
1
,
e
.
our_dh_pub
,
nil
}
fmt
.
Printf
(
"%s
\t
sending: %v
\n
"
,
e
.
name
,
toSend
)
return
toSend
}
func
main
()
{
a
,
b
:=
initialize
()
b
.
receive
(
a
.
query
())
a
.
receive
(
b
.
sendP1
())
b
.
receive
(
a
.
sendP2
())
fmt
.
Println
(
"========================="
)
fmt
.
Println
(
"Testing sync data message"
)
fmt
.
Println
(
"========================="
)
a
.
receive
(
b
.
sendData
())
// b sends first, so no new ratchet happens.
a
.
receive
(
b
.
sendData
())
// b again: this is another follow up msg.
b
.
receive
(
a
.
sendData
())
// a sends, a new ratchet happens and bob follows.
b
.
receive
(
a
.
sendData
())
// a again: this is a follow up.
fmt
.
Println
(
"========================="
)
fmt
.
Println
(
"Testing async data message"
)
fmt
.
Println
(
"========================="
)
m1
:=
a
.
sendData
()
// a sends again: another follow up message.
m2
:=
b
.
sendData
()
// b sends now, a new ratcher happens for bob.
m3
:=
a
.
sendData
()
// a sends again: another follow up message.
b
.
receive
(
m1
)
// b receives follow up message from a previous ratchet.
b
.
receive
(
m3
)
// b receives follow up message from a previous ratchet.
a
.
receive
(
m2
)
// a receives a message from a new ratchet. She follows the ratchet.
fmt
.
Println
(
"========================="
)
fmt
.
Println
(
"Testing new sync DAKE"
)
fmt
.
Println
(
"========================="
)
b
.
receive
(
a
.
query
())
a
.
receive
(
b
.
sendP1
())
b
.
receive
(
a
.
sendP2
())
b
.
receive
(
a
.
sendData
())
// a sends, a new ratchet starts and bob follows
b
.
receive
(
a
.
sendData
())
// a sends a follow up
a
.
receive
(
b
.
sendData
())
// b sends, a new ratchet starts and alice follows
a
.
receive
(
b
.
sendData
())
// b sends a follow up
fmt
.
Println
(
"========================="
)
fmt
.
Println
(
"Testing async DAKE message"
)
fmt
.
Println
(
"========================="
)
b
.
receive
(
a
.
query
())
p1
:=
b
.
sendP1
()
b0
:=
b
.
sendData
()
// bob sends a data message during a new DAKE, is this a follow up msg?
b1
:=
b
.
sendData
()
// bob sends a data message during a new DAKE - surely a follow up msg.
b
.
receive
(
a
.
sendData
())
// a sends a new message before she receives p1, but after bob sends p1.
// this will be a new ratchet, and thats a problem because bob will also ratchet when sending p1.
a
.
receive
(
p1
)
// a receives p1
p2
:=
a
.
sendP2
()
// ... and immediately replies with a p2
a0
:=
a
.
sendData
()
// ... and send a new data msg
b
.
receive
(
p2
)
// bob receives a p2
b
.
receive
(
a0
)
// and the a0
a
.
receive
(
b0
)
// a receives b0 (I want to see how it works if she receives this BEFORE sending a0)
a
.
receive
(
b1
)
// a receives b1
}
func
initialize
()
(
alice
,
bob
Entity
)
{
alice
.
name
=
"Alice"
alice
.
rid
=
-
2
bob
.
name
=
"Bob"
bob
.
rid
=
-
2
return
alice
,
bob
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment