This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Specifications

  • 1:
  • 2:
  • 3:
  • 4:
  • 5:
  • 6:
  • 7:
  • 8:
  • 9:
  • 10:
  • 11:
  • 12:

These technical specifications describe the specifics of Katzenpost protocols and implementations, and are aimed primarily at software developers.

Title Description Link(s)
πŸ“– Certificate format PKI Certificate format. HTML / PDF
πŸ“– Client2 Client2 thin client library design. HTML / PDF
πŸ“– KEM Sphinx packet format The KEM Sphinx variation of Sphinx. HTML / PDF
πŸ“– Mixnet Describes the overall mixnet design. HTML / PDF
πŸ“– Mix decoy stats propagation Mix decoy stats propagation. HTML / PDF
πŸ“– Public Key Infrastructure Every mixnet must have a PKI, this doc describes ours. HTML / PDF
πŸ“– Provider-side autoresponder extension Autoresponder agent that runs on provider nodes. HTML / PDF
πŸ“– Sphinx packet format Sphinx packet format, a nested cryptographic packet format designed for mix networks. HTML / PDF
πŸ“– Sphinx Replay Detection Sphinx replay detection. HTML / PDF
πŸ“– Wire Protocol A detailed design specification for our PQ Noise based wire protocol, which is used for transport encryption between all the mix nodes and dirauth nodes. HTML / PDF
πŸ“– Glossary Consolidated list of terms defined in the specifications. HTML / PDF
πŸ“– References Consolidated list of references cited in the specifications. HTML / PDF

1 -

Certificate format

Certificate format

David Stainton

Abstract

This document proposes a certificate format that Katzenpost mix server, directory authority server and clients will use.


Terminology

The following terms are used in this specification.

Conventions Used in This Document

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC2119.

1. Introduction

Mixes and Directory Authority servers need to have key agility in the sense of operational abilities such as key rotation and key revocation. That is, we wish for mixes and authorities to periodically utilize a long-term signing key for generating certificates for new short-term signing keys.

Yet another use-case for these certificate is to replace the use of JOSE RFC7515 in the voting Directory Authority system KATZMIXPKI for the multi-signature documents exchanged for voting and consensus.

1.1. Document Format

The CBOR RFC7049 serialization format is used to serialize certificates:

Signature is a cryptographic signature which has an associated signer ID.

type Signature struct {
// Identity is the identity of the signer.
Identity []byte
// Signature is the actual signature value.
Signature []byte
}

Certificate structure for serializing certificates.

type certificate struct {
// Version is the certificate format version.
Version uint32

// Expiration is seconds since Unix epoch.
Expiration int64

// KeyType indicates the type of key
// that is certified by this certificate.
KeyType string

// Certified is the data that is certified by
// this certificate.
Certified []byte

// Signatures are the signature of the certificate.
Signatures []Signature
}

That is, one or more signatures sign the certificate. However the Certified field is not the only information that is signed. The Certified field along with the other non-signature fields are all concatenated together and signed. Before serialization the signatures are sorted by their identity so that the output is binary deterministic.

1.2 Certificate Types

The certificate type field indicates the type of certificate. So far we have only two types:

  • identity key certificate

  • directory authority certificate

Both mixes and directory authority servers have a secret, long-term identity key. This key is ideally stored encrypted and offline, it’s used to sign key certificate documents. Key certificates contain a medium-term signing key that is used to sign other documents. In the case of an authority signing key, it is used to sign vote and consensus documents whereas the mix singing key is used to sign mix descriptors which are uploaded to the directory authority servers.

1.3. Certificate Key Types

It’s more practical to continue using Ed25519 ED25519 keys but it’s also possible that in the future we could upgrade to a stateless hash based post quantum cryptographic signature scheme such as SPHINCS-256 or SPHINCS+. SPHINCS256

2. Golang API

  • https://godoc.org/github.com/katzenpost/katzenpost/core/crypto/cert

Our golang implementation is agnostic to the specific cryptographic signature scheme which is used. Cert can handle single and multiple signatures per document and has a variety of helper functions that ease use for multi signature use cases.

Acknowledgments

This specification was inspired by Tor Project’s certificate format specification document:

  • https://gitweb.torproject.org/torspec.git/tree/cert-spec.txt

References

RFC7049

C. Bormannm, P. Hoffman, Concise Binary Object Representation (CBOR), Internet Engineering Task Force (IETF), October 2013, https://www.rfc-editor.org/info/rfc7049.

RFC7515

Jones, M., Bradley, J., Sakimura, N., JSON Web Signature (JWS), May 2015, https://www.rfc-editor.org/info/rfc7515.

KATZMIXPKI

Angel, Y., Piotrowska, A., Stainton, D., Katzenpost Mix Network Public Key Infrastructure Specification, December 2017, https://katzenpost.network/docs/specs/pdf/pki.pdf.

RFC2119

Bradner, S., Key words for use in RFCs to Indicate Requirement Levels, BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, http://www.rfc-editor.org/info/rfc2119.

RFC7693

Saarinen, M-J., Ed., and J-P. Aumasson, The BLAKE2 Cryptographic Hash and Message Authentication Code (MAC), RFC 7693, DOI 10.17487/RFC7693, November 2015, http://www.rfc-editor.org/info/rfc7693.

ED25519

https://www.rfc-editor.org/rfc/rfc8032.

SPHINCS256

Bernstein, D., Hopwood, D., Hulsing, A., Lange, T., Niederhagen, R., Papachristodoulou, L., Schwabe, P., Wilcox O'Hearn, Z., SPHINCS: practical stateless hash-based signatures, http://sphincs.cr.yp.to/sphincs-20141001.pdf.

2 -

Client2 design specification

Client2 design specification

David Stainton

Abstract

This document describes the design of the new Katzenpost mix network client known as client2. In particular we discuss its multiplexing and privilege separation design elements as well as the protocol used by the thin client library.


1. Overview

A Katzenpost mixnet client has several responsibilities at a minimum:

  • compose Sphinx packets

  • decrypt SURB replies

  • send and receive Noise protocol messages

  • keep up to date with the latest PKI document

Client2 is essentially a long running daemon process that listens on an abstract unix domain socket for incoming thin client library connections. Many client applications can use the same client2 daemon. Those connections are in a sense being multiplexed into the daemon’s single connection to the mix network.

Therefore applications will be integrated with Katzenpost using the thin client library which gives them the capability to talk with the client2 daemon and in that way interact with the mix network. The reason we call it a thin client library is because it does not do any mixnet related cryptography since that is already handled by the client2 daemon. In particular, the PKI document is stripped by the daemon before it’s passed on to the thin clients. Likewise, thin clients don’t decrypt SURB replies or compose Sphinx packets, instead all the that Noise, Sphinx and PKI related cryptography is handled by the daemon.

2. Thin client and daemon protocol

Note that the thin client daemon protocol uses abstract unix domain sockets in datagram packet mode. The socket is of type SOCK_SEQPACKET which is defined as:

  • SOCK_SEQPACKET (since Linux 2.6.4), is a connection-oriented socket that preserves message boundaries and delivers messages in the order that they were sent.

In golang this is referred to by the unixpacket network string.

2.1 Client socket naming convention

Thin clients MUST randomize their abstract unix domain socket name otherwise the static name will prevent multiplexing because the kernel requires that the connection be between uniquely nameed socket pairs. The Katzenpost reference implementation of the thin client library selects a socket name with four random hex digits appended to the end of the name like so:

@katzenpost_golang_thin_client_DEADBEEF

2.2 Daemon socket naming convention

The client2 daemon listens on an abstract unix domain socket with the following name:

@katzenpost

2.3 Protocol messages

Note that there are two protocol message types and they are always CBOR encoded. We do not make use of any prefix length encoding because the socket type preserves message boundaries for us. Therefore we simply send over pure CBOR encoded messages.

The daemon sends the Response message which is defined in golang as a struct containing an app ID and one of four possible events:


type Response struct {
// AppID must be a unique identity for the client application
// that is receiving this Response.
AppID *[AppIDLength]byte `cbor:app_id`

ConnectionStatusEvent *ConnectionStatusEvent `cbor:connection_status_event`

NewPKIDocumentEvent *NewPKIDocumentEvent `cbor:new_pki_document_event`

MessageSentEvent *MessageSentEvent `cbor:message_sent_event`

MessageReplyEvent *MessageReplyEvent `cbor:message_reply_event`
}

type ConnectionStatusEvent struct {
IsConnected bool `cbor:is_connected`
Err error `cbor:err`
}

type NewPKIDocumentEvent struct {
Payload []byte `cbor:payload`
}

type MessageReplyEvent struct {
MessageID *[MessageIDLength]byte `cbor:message_id`
SURBID *[sConstants.SURBIDLength]byte `cbor:surbid`
Payload []byte `cbor:payload`
Err error `cbor:err`
}

type MessageSentEvent struct {
MessageID *[MessageIDLength]byte `cbor:message_id`
SURBID *[sConstants.SURBIDLength]byte `cbor:surbid`
SentAt time.Time `cbor:sent_at`
ReplyETA time.Duration `cbor:reply_eta`
Err error `cbor:err`
}

The client sends the Request message which is defined in golang as:


type Request struct {
// ID is the unique identifier with respect to the Payload.
// This is only used by the ARQ.
ID *[MessageIDLength]byte `cbor:id`

// WithSURB indicates if the message should be sent with a SURB
// in the Sphinx payload.
WithSURB bool `cbor:with_surb`

// SURBID must be a unique identity for each request.
// This field should be nil if WithSURB is false.
SURBID *[sConstants.SURBIDLength]byte `cbor:surbid`

// AppID must be a unique identity for the client application
// that is sending this Request.
AppID *[AppIDLength]byte `cbor:app_id`

// DestinationIdHash is 32 byte hash of the destination Provider's
// identity public key.
DestinationIdHash *[32]byte `cbor:destination_id_hash`

// RecipientQueueID is the queue identity which will receive the message.
RecipientQueueID []byte `cbor:recipient_queue_id`

// Payload is the actual Sphinx packet.
Payload []byte `cbor:payload`

// IsSendOp is set to true if the intent is to send a message through
// the mix network.
IsSendOp bool `cbor:is_send_op`

// IsARQSendOp is set to true if the intent is to send a message through
// the mix network using the naive ARQ error correction scheme.
IsARQSendOp bool `cbor:is_arq_send_op`

// IsEchoOp is set to true if the intent is to merely test that the unix
// socket listener is working properly; the Response payload will be
// contain the Request payload.
IsEchoOp bool `cbor:is_echo_op`

// IsLoopDecoy is set to true to indicate that this message shall
// be a loop decoy message.
IsLoopDecoy bool `cbor:is_loop_decoy`

// IsDropDecoy is set to true to indicate that this message shall
// be a drop decoy message.
IsDropDecoy bool `cbor:is_drop_decoy`
}

2.4 Protocol description

Upon connecting to the daemon socket the client must wait for two messages. The first message received must have it’s is_status field set to true. If so then it’s is_connected field indicates whether or not the daemon has a mixnet PQ Noise protocol connection to an entry node.

Next the client awaits the second message which contains the PKI document in it’s payload field. This marks the end of the initial connection sequence. Note that this PKI document is stripped of all cryptographic signatures.

In the next protocol phase, the client may send Request messages to the daemon in order to cause the daemon to encapsulate the given payload in a Sphinx packet and send it to the entry node. Likewise the daemon my send the client Response messages at any time during this protocol phase. These Response messages may indicated a connection status change, a new PKI document or a message sent or reply event.

2.5 Request message fields

There are several Request fields that we need to discuss.

Firstly, each Request message sent by a thin client needs to have the app_id field set to an ID that is unique among the applications using thin clients. The app_id is used by the daemon to route Response messages to the correct thin client socket.

The rest of the fields we are concerned with are the following:

  • with_surb is set to true if a Sphinx packet with a SURB in it’s payload should be sent.

  • surbid is used to uniquely identify the reponse to a message sent with the with_surb field set to true. It should NOT be set if using the built-in ARQ for reliability and optional retransmissions.

  • is_send_op must be set to true.

  • payload must be set to the message payload being sent.

  • destination_id_hash is 32 byte hash of the destination entry node’s identity public key.

  • recipient_queue_id is the destination queue identity. This is the destination the message will be delivered to.

If a one way message should be sent with no SURB then with_surb should be set to false and surbid may be nil. If however the thin client wishes to send a reliable message using the daemon’s ARQ, then the following fields must be set:

  • id the message id which uniquely identifies this message and it’s eventual reply.

  • with_surb set to true

  • is_arq_send_op set to true

  • payload set to the message payload, as usual.

  • destination_id_hash set to the destination service node’s identity public key 32 byte hash.

  • recipient_queue_id is the destination queue identity. This is the destination the message will be delivered to.

2.6 Response message fields

A thin client connection always begins with the daemon sendings the client two messages, a connection status followed by a PKI document.

After this connection sequence phase, the daemon may send the thin client a connection status or PKI document update at any time.

Thin clients recieve four possible events inside of Response messages:

  1. connection status event

    • is_connected indicated whether the client is connected or not.

    • err may contain an error indicating why connection status changed.

  2. new PKI document event

    • payload is the CBOR serialied PKI document, stripped of all the cryptographic signatures.

  3. message sent event

    • message_id is a unique message ID

    • surb_id is the SURB ID

    • sent_at is the time the message was sent

    • replay_eta is the time we expect a reply

    • err is the optional error we received when attempting to send

  4. message reply event

    • message_id is a unique message ID

    • surb_id is a the SURB ID

    • payload is the replay payload

    • err is the error, if any.

3 -

KEMSphinx

KEMSphinx

David Stainton

Abstract

Here I present a modification of the Sphinx cryptographic packet format that uses a KEM instead of a NIKE whilst preserving the properties of bitwise unlinkability, constant packet size and route length hiding.


1. Introduction

We’ll express our KEM Sphinx header in pseudo code. The Sphinx body will be exactly the same as the section called “References” Our basic KEM API has three functions:

  • PRIV_KEY, PUB_KEY = GEN_KEYPAIR(RNG)

  • ct, ss = ENCAP(PUB_KEY) - Encapsulate generates a shared secret, ss, for the public key and encapsulates it into a ciphertext.

  • ss = DECAP(PRIV_KEY, ct) - Decapsulate computes the shared key, ss, encapsulated in the ciphertext, ct, for the private key.

Additional notation includes:

  • || = concatenate two binary blobs together

  • PRF = pseudo random function, a cryptographic hash function, e.g. Blake2b.

Therefore we must embed these KEM ciphertexts in the KEMSphinx header, one KEM ciphertext per mix hop.

2. Post Quantum Hybrid KEM

Special care must be taken in order correctly compose a hybrid post quantum KEM that is IND-CCA2 robust.

The hybrid post quantum KEMs found in Cloudflare’s circl library are suitable to be used with Noise or TLS but not with KEM Sphinx because they are not IND-CCA2 robust. Noise and TLS achieve IND-CCA2 security by mixing in the public keys and ciphertexts into the hash object and therefore do not require an IND-CCA2 KEM.

Firstly, our post quantum KEM is IND-CCA2 however we must specifically take care to make our NIKE to KEM adapter have semantic security. Secondly, we must make a security preserving KEM combiner.

2.1 NIKE to KEM adapter

We easily achieve our IND-CCA2 security by means of hashing together the DH shared secret along with both of the public keys:

func ENCAPSULATE(their_pubkey publickey) ([]byte, []byte) {
my_privkey, my_pubkey = GEN_KEYPAIR(RNG)
ss = DH(my_privkey, their_pubkey)
ss2 = PRF(ss || their_pubkey || my_pubkey)
return my_pubkey, ss2
}

func DECAPSULATE(my_privkey, their_pubkey) []byte {
s = DH(my_privkey, their_pubkey)
shared_key = PRF(ss || my_pubkey || their_pubkey)
return shared_key
}

2.2 KEM Combiner

The KEM Combiners paper ??? makes the observation that if a KEM combiner is not security preserving then the resulting hybrid KEM will not have IND-CCA2 security if one of the composing KEMs does not have IND-CCA2 security. Likewise the paper points out that when using a security preserving KEM combiner, if only one of the composing KEMs has IND-CCA2 security then the resulting hybrid KEM will have IND-CCA2 security.

Our KEM combiner uses the split PRF design from the paper when combining two KEM shared secrets together we use a hash function to also mix in the values of both KEM ciphertexts. In this pseudo code example we are hashing together the two shared secrets from the two underlying KEMs, ss1 and ss2. Additionally the two ciphertexts from the underlying KEMs, cct1 and cct2, are also hashed together:

func SplitPRF(ss1, ss2, cct1, cct2 []byte) []byte {
cct := cct1 || cct2
return PRF(ss1 || cct) XOR PRF(ss2 || cct)
}

Which simplifies to:

SplitPRF := PRF(ss1 || cct2) XOR PRF(ss2 || cct1)

The Split PRF can be used to combine an arbitrary number of KEMs. Here’s what it looks like with three KEMs:

func SplitPRF(ss1, ss2, ss3, cct1, cct2, cct3 []byte) []byte {
cct := cct1 || cct2 || cct3
return PRF(ss1 || cct) XOR PRF(ss2 || cct) XOR PRF(ss3 || cct)
}

3. KEMSphinx Header Design

NIKE Sphinx header elements:

  1. Version number (MACed but not encrypted)

  2. Group element

  3. Encrypted per routing commands

  4. MAC for this hop (authenticates header fields 1 thru 4)

KEM Sphinx header elements:

  1. Version number (MACed but not encrypted)

  2. One KEM ciphertext for use with the next hop

  3. Encrypted per routing commands AND KEM ciphtertexts, one for each additional hop

  4. MAC for this hop (authenticates header fields 1 thru 4)

We can say that KEMSphinx differs from NIKE Sphinx by replacing the header’s group element (e.g. an X25519 public key) field with the KEM ciphertext. Subsequent KEM ciphertexts for each hop are stored inside the Sphinx header routing information section.

First we must have a data type to express a mix hop, and we can use lists of these hops to express a route:

type PathHop struct {
public_key kem.PublicKey
routing_commands Commands
}

Here’s how we construct a KEMSphinx packet header where path is a list of PathHop, and indicates the route through the network:

  1. Derive the KEM ciphertexts for each hop.

route_keys = []
route_kems = []
for i := 0; i < num_hops; i++ {
kem_ct, ss := ENCAP(path[i].public_key)
route_kems += kem_ct
route_keys += ss
}
  1. Derive the routing_information keystream and encrypted padding for each hop.

Same as in the section called “References” except for the fact that each routing info slot is now increased by the size of the KEM ciphertext.

  1. Create the routing_information block.

Here we modify the Sphinx implementation to pack the next KEM ciphertext into each routing information block. Each of these blocks is decrypted for each mix mix hop which will decrypt the KEM ciphertext for the next hop in the route.

  1. Assemble the completed Sphinx Packet Header and Sphinx Packet Payload SPRP key vector. Same as in SPHINXSPEC except the kem_element field is set to the first KEM ciphertext, route_kems[0]:

var sphinx_header SphinxHeader
sphinx_header.additional_data = version
sphinx_header.kem_element = route_kems[0]
sphinx_header.routing_info = routing_info
sphinx_header.mac = mac
<<<<<<< HEAD

2. KEMSphinx Unwrap Operation

Most of the design here will be exactly the same as in SPHINXSPEC. However there are a few notable differences:

  1. The shared secret is derived from the KEM ciphertext instead of a DH.

  2. Next hop’s KEM ciphertext stored in the encrypted routing information.

3. Acknowledgments

I would like to thank Peter Schwabe for the original idea of simply replacing the Sphinx NIKE with a KEM and for answering all my questions. I’d also like to thank Bas Westerbaan for answering questions.

Appendix A. References

KEMCOMB. Federico Giacon, Felix Heuer, Bertram Poettering, "KEM Combiners", 2018. https://link.springer.com/chapter/10.1007/978-3-319-76578-5_7

SPHINX09. Danezis, G., Goldberg, I., "Sphinx: A Compact and Provably Secure Mix Format\", DOI 10.1109/SP.2009.15, May 2009. https://cypherpunks.ca/~iang/pubs/Sphinx_Oakland09.pdf

SPHINXSPEC. Angel, Y., Danezis, G., Diaz, C., Piotrowska, A., Stainton, D., "Sphinx Mix Network Cryptographic Packet Format Specification" July 2017. https://katzenpost.network/docs/specs/sphinx/

=======

4. KEMSphinx Unwrap Operation

Most of the design here will be exactly the same as in SPHINXSPEC. However there are a few notable differences:

  1. The shared secret is derived from the KEM ciphertext instead of a DH.

  2. Next hop’s KEM ciphertext stored in the encrypted routing information.

Acknowledgments

I would like to thank Peter Schwabe for the original idea of simply replacing the Sphinx NIKE with a KEM and for answering all my questions. I’d also like to thank Bas Westerbaan for answering questions.

References

KEMCOMB

Federico Giacon, Felix Heuer, Bertram Poettering, KEM Combiners, 2018, https://link.springer.com/chapter/10.1007/978-3-319-76578-5_7

SPHINX09

Danezis, G., Goldberg, I., Sphinx: A Compact and Provably Secure Mix Format, DOI 10.1109/SP.2009.15, May 2009, https://cypherpunks.ca/~iang/pubs/Sphinx_Oakland09.pdf.

SPHINXSPEC

Angel, Y., Danezis, G., Diaz, C., Piotrowska, A., Stainton, D., Sphinx Mix Network Cryptographic Packet Format Specification, July 2017, https://katzenpost.network/docs/specs/pdf/sphinx.pdf.