Server has a long-term static Classic McEliece 6960-119 and X25519 keypairs. They are transferred to client outside the connection. Client: * has: serverStaticPubMcEliece, serverStaticPubX25519 * clientEphPrvX25519, clientEphPubX25519 = Generate() * ctMcElice, ssMcEliece = Encapsulate(serverStaticPubMcEliece) * H = SHAKE256("VoRS v5") * H = SHAKE256(H || serverStaticPubMcEliece || serverStaticPubX25519) * H = SHAKE256(H || ctMcElice) * CK = HKDF-Extract(SHAKE256, ikm=ssMcEliece, salt="") * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 client x25519") * ctX25519 = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=clientEphPubX25519) * H = SHAKE256(H || ctX25519) * ssX25519 = X25519(clientEphPrvX25519, serverStaticPubX25519) * CK = HKDF-Extract(SHAKE256, ikm=ssX25519, salt=CK) * sends: ctMcElice || ctX25519 Server: * ... * serverEphPrvX25519, serverEphPubX25519 = Generate() * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 server x25519") * ctX25519 = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=serverEphPubX25519) * H = SHAKE256(H || ctX25519) * ssX25519 = X25519(serverEphPrvX25519, clientEphPubX25519) * CK = HKDF-Extract(SHAKE256, ikm=ssX25519, salt=CK) * serverEphPrvSNTRUP761, serverEphPubSNTRUP761 = Generate() * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 server sntrup761") * ctSNTRUP = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=serverEphPubSNTRUP761) * H = SHAKE256(H || ctSNTRUP) * sends: ctX25519 || ctSNTRUP Client: * has: prefinish message payload * ... * ctSNTRUP, ssSNTRUP = Encapsulate(serverEphPubSNTRUP761) * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 client sntrup761") * ctSNTRUP = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=ctSNTRUP) * H = SHAKE256(H || ctSNTRUP) * CK = HKDF-Extract(SHAKE256, ikm=ssSNTRUP, salt=CK) * k = HKDF-Expand(SHAKE256, prk=CK, info="VoRS v5 client prefinish") * ctPrefinish = ChaCha20-Poly1305(k, nonce=0, ad=H, pt=prefinish) * H = SHAKE256(H || ctPrefinish) * sends: ctPrefinish Server: * ... Both: clientChaPolyKey, serverChaPolyKey, VoIPKey = HKDF-Expand(SHAKE256, ikm=CK, salt=H)