modern session encryption
TRANSCRIPT
Modern Session EncryptionDavid Wong
2. STROBE
outline
1. KECCAK
3. NOISE
4. ???
f
⊕ ⊕
f
⊕
f f f
squeezing
Sponge Construction
absorbing
0
0
0
0
0
0
0
0
00101 01001 01100 11001 01011 10101
f
input
⊕
init
output
duplexing
Duplex Construction
f
input
⊕
output
duplexing
f
input output
duplexing
⊕
0
0
0
0
0
0
0
0
Keyed-mode
f
key
⊕
init duplexing
0
0
0
0
0
0
0
0
f
key
⊕
init duplexing
0
0
0
0
0
0
0
0
Encryption?
f
key
⊕
init duplexing
0
0
0
0
0
0
0
0
ciphertext1
plaintext1⊕
Encryption
f
key
⊕
init duplexing
0
0
0
0
0
0
0
0
ciphertext1
plaintext1⊕
f
⊕
tag1
duplexing
Authenticated Encryption
f
key
⊕
init duplexing
0
0
0
0
0
0
0
0
ciphertext1
plaintext1⊕
f
⊕
tag1
duplexing
f
ciphertext2
duplexing
f
⊕
tag2
duplexing
plaintext2⊕
Sessions
0
0
0
0
0
0
0
0
f
key
⊕
init duplexing
ciphertext1
plaintext1⊕
f⊕
tag1
duplexing
f
ciphertext2
duplexing
f⊕
tag2
duplexing
plaintext2⊕
f
ciphertext3
duplexing
f⊕
tag3
duplexing
plaintext3⊕
f
ciphertext4
duplexing
f⊕
tag4
duplexing
plaintext4⊕
2. STROBE
outline
1. KECCAK
operation = AD
⊕
data = 010100…
⊕
ADoperation = KEY
⊕
data = 010100…
KEY
f
operation = PRF
⊕00000…
PRF
f
output
operation = send_CLR
⊕
data = 010100…
⊕
send_CLRoperation = recv_CLR
⊕
data = 010100…
⊕
recv_CLR
operation = send_ENC
⊕ciphertext
send_ENC
f
plaintext
⊕
operation = send_MAC
⊕tag
send_MAC
f
operation = RATCHET
⊕
RATCHET
f
0000operation = recv_ENC
⊕
plaintext
recv_ENC
f⊕ ciphertext
operation = recv_MAC
⊕
recv_MAC
f
0000…
⊕ tag
Strobe functions
myProtocol = Strobe_init(“myWebsite.com”)
myProtocol.AD(sharedSecret)
buffer = myProtocol.send_ENC(“GET /”)
buffer += myProtocol.send_MAC(len=16)
// send the buffer
// receive a ciphertext
message = myProtocol.recv_ENC(ciphertext[:-16])
ok = myProtocol.recv_MAC(ciphertext[-16:])
if !ok {
// reset the connection
}
Strobe protocol example
buffer = myProtocol.send_ENC(plaintext1)
buffer += myProtocol.send_MAC(len=16)
// send the buffer
buffer = myProtocol.send_ENC(plaintext2)
buffer += myProtocol.send_MAC(len=16)
// send the buffer
buffer = myProtocol.send_ENC(plaintext3)
buffer += myProtocol.send_MAC(len=16)
// send the buffer
buffer = myProtocol.send_ENC(plaintext4)
buffer += myProtocol.send_MAC(len=16)
// send the buffer
Strobe
• flexible framework to support a large number of protocols • large symmetric cryptography library
myHash = Strobe_init(“david_wong_hash”)
myHash.AD(“something to be hashed”)
hash = myHash.PRF(outputLen=32)
Strobe as a Hash Function
operation = AD
⊕rate
capacity
operation = AD
⊕
data = 010100…
⊕rate
capacity
operation = AD
⊕
data = 010100…
⊕
operation = send_ENC
⊕rate
capacity
operation = AD
⊕
data = 010100…
f
⊕
operation = send_ENC
⊕rate
capacity
operation = AD
⊕
data = 010100…
f
⊕
operation = send_ENC
data = hello
⊕
ciphertext
⊕rate
capacity
operation = AD
⊕
data = 010100…
f f
⊕
operation = send_ENC
data = hello
⊕
ciphertextlen = 16
tag
⊕
operation = send_MAC
⊕rate
capacity
operation = AD
⊕
data = 010100…
f f
⊕
operation = send_ENC
data = hello
⊕
ciphertextlen = 16
tag
⊕
operation = send_MAC
send_AEAD
⊕rate
capacity
Strobe
• flexible framework to support a large number of protocols • large symmetric cryptography library • fits into tiny IoT devices (~300 lines of code) • relies on strong SHA-3 standard (SHAKE-compliant)
2. STROBE
outline
1. KECCAK
3. NOISE
TLS• TLS is the de facto standard for securing communications • complex specification (TLS 1.3 is 160-page long)
• supported by other specifications (asn.1, x509, 44 mentioned RFCs …) • design carrying a lot of legacy decisions • cryptographic agility and complicated state machine • huge and scary libraries (OpenSSL is 700k LOC, 165 CVEs)
• cumbersome configuration… • often dangerously re-implemented (custom implementations)
• or re-invented (proprietary protocols)
Complexity is the enemy of security
www.noiseprotocol.org
The Noise Protocol Framework
• no need for certificates or a PKI • many handshakes to choose from (flexible) • it’s straight forward to implement (<1k LOC, 18kb for Arduino) • there are already libraries that you can leverage • minimal (or zero) configuration • used by WhatsApp, Slack, the Bitcoin Lightning Network, … • if you have a good excuse not to use TLS, Noise is the answer
• DH: X25519 or X448
• AEAD: Chacha20-Poly1305 or AES-GCM
• HASH: BLAKE2 or SHA-2
The crypto functions
ephemeral key
ephemeral key
Client Server
handshake
ephemeral key
ephemeral key
Client Server
handshakeDiffie-Hellman() Diffie-Hellman()
keys keys
ephemeral key
ephemeral key
Client Server
handshake
encrypted data
encrypted data
post-handshake
Diffie-Hellman() Diffie-Hellman()
keys keys
e
e
Client Server
handshake
encrypted data
encrypted data
post-handshake
ee ee
keys keys
→ e ← e, ee
• e: ephemeral key
• s: static key
• ee: DH(client ephemeral key, server ephemeral key)
• es: DH(client ephemeral key, server static key)
• se: DH(client static key, server ephemeral key)
• ss: DH(client static key, server static key)
• psk: pre-shared key
Tokens
→ e ← e, ee
NN():← s … → e, es ← e, ee
NK(rs):→ e ← e, ee, s, es
NX(rs):
→ e ← e, ee → s, se
XN(s):← s → s … → e, es, ss ← e, ee, se
KK(s, rs):→ e ← e, ee, s, es → s, se
XX(s, rs):
← s … → e, es
N(rs):← s → s … → e, es, ss
K(s,rs):← s … → e, es, s, ss
X(s,rs):
← s … → e, es ← e, ee → s, se
XK(s, rs):→ s … → e ← e, ee, se
KN(s):
Handshake Patterns
NX(rs): → e ← e, ee, s, es
Client Server
epublic
Client Server
NX(rs): → e ← e, ee, s, es
payload1
epublic
Client Server
NX(rs): → e ← e, ee, s, es
republic
epublic
Client Server
payload1
NX(rs): → e ← e, ee, s, es
republic
epublic
Client Server
payload1
NX(rs): → e ← e, ee, s, es
republic
EK1(rs)
epublic
Client Server
payload1
NX(rs): → e ← e, ee, s, es
republic
EK1(rs)
epublic
Client Server
payload1
NX(rs): → e ← e, ee, s, es
republic
EK1(rs)
EK2(payload2)
epublic
Client Server
payload1
NX(rs): → e ← e, ee, s, es
HandshakeStateSymmetricStateCipherState
epublic
payload1
republic
Ek1(rspublic)
HKDF
DH(e, re)
ckn=0 k1
e GENERATE_KEYPAIR()
Initializationck h “Noise_NX_25519_AESGCM_SHA256”HASH
h
e.public_keyHASH
re.public_keyHASH
h rs DecryptWithAd() Ek1(rspublic)
h
HASH
h
Ek1(rspublic)
HASH
h
payload1
CipherState
HKDF
k
k
n=0
n=0
CipherStateEk2(payload2)
re republicHKDF
DH(e, rs)
ckn=0 k2
DecryptWithAd() Ek2(payload2)
h
payload2
HASH
h
Ek2(payload2)
2. STROBE
outline
1. KECCAK
3. NOISE
4. DISCO
HandshakeStateStrobeState
epublic
payload1
republic
E(rspublic)
Initialization
E(payload2)
InitStrobe() “Noise_NX_25519_Strobe”
e GENERATE_KEYPAIR()
send_CLR()payload1
send_CLR() e.public_key
re.public_keyrecv_CLR()republic
recv_AEAD()E(payload2) payload2
AD()DH(e, rs)
rs.public_keyrecv_AEAD()E(rspublic)
StrobeState StrobeState……
AD()DH(e, re)
StrobeState
send_AEAD()
send_AEAD()
send_AEAD()
send_AEAD()
send_AEAD()
send_AEAD()
send_AEAD()
StrobeState
recv_AEAD()
recv_AEAD()
recv_AEAD()
recv_AEAD()
recv_AEAD()
recv_AEAD()
recv_AEAD()
HandshakeStateStrobeState
epublic
payload1
republic
E(rspublic), tag1
E(payload2), tag2
e GENERATE_KEYPAIR()Initialization“Noise_NX_25519_Strobe”⊕
e.public_key⊕payload1⊕
DH(e, re)⊕
DH(e, rs)⊕
re.public_key⊕ republic
tag1
rs.public_key
E(rspublic)⊕
rs.public_key
E(payload2)⊕
tag2
www.discocrypto.com
700,000 LOC
disco-c libdisco (go)
OpenSSL
4,000 LOC1,000 LOC
2,000 LOC
DiscoNet* (C#)
* implementation by Artyom Makarov
DISCO
STROBE X25519
KECCAK-F
Trust Graph of Disco
Trust Graph of biased SSL/TLS
TLS 1.3
HMAC X25519
SHA-256
HKDF ECDSAAES-GCM
Trust Graph of SSL/TLS
TLS 1.3
HMAC
SHA-256SHA-384SHA-512
HKDF ECDSAAES-GCM
DH
ECDH
CHACHA20-POLY1305
TLS 1.2TLS 1.1
X.509
ASN.1
DER
secp256r1
secp384r1
secp521r1
ffdhe2048
X25519
X448
ffdhe3072
ffdhe4096
ffdhe6144
ffdhe8192
RSA-PSS orRSA-PKCS#1
v1.5
AES-CCM
ed25519
ed448
• Disco is a draft specification extending Noise (experimental) • Noise is a stable draft (rev34) • Strobe is alpha (v1.0.2) • ⚠ Disco and the implementations are still experimental
• need more eyes, more interoperability testing, etc. • looking to formally prove handshakes with Tamarin
The state of Disco
the disco is at www.discocrypto.com
I write about crypto www.cryptologie.net
follow me on twitter.com/cryptodavidw (and I work here)