This draft proposal is based on the Salt design for secure pub-sub.
Scope
Authentication and encryption of distributed 0MQ publish-subscribe systems in which subscribers and publishers are known to each other in advance.
Components of the System
- Master: responsible for authentication, master key distribution, and publishing encrypted application data.
- Minion: responsible for receiving encrypted application data.
Overall Operation
- PSAE uses public/private asymmetric encryption (e.g. RSA) for authentication and master key exchange. Each PSAE peer has a public key-private key pair. Public and private keys are static.
- PSAE uses a static master key for symmetric data encryption (using e.g. AES). The master will regenerate its master keys (one per domain) arbitrarily.
- Each PSAE message consists of a clear header specifying the encryption mechanism, and an encrypted body.
- The master is pre-configured with the public keys of all the minions it will work with.
- Each minion is pre-configured with the public key of the master(s) it will work with.
- PSAE assumes that public keys are exchanged in advance by some unspecified secure mechanism.
Minion Authentication
Authentication is by domain, which is an application-level access container. Minions are identified by name, and verified by their public keys.
A minion authenticates as follows:
- It opens a REQ socket and connects to the master, which has bound a ROUTER socket.
- It sends an AUTHENTICATE command to the master. The body consists of the desired domain, minion name, and minion signature. The minion signature consists of the six letters "MINION", encrypted using the minion's private key. The body is encrypted using the master's public key.
- The master decrypts the AUTHENTICATE body using its private key, and verifies the domain and minion name. It then decrypts the signature using the minion's public key, and verifies it. If this succeeds, the master replies with AUTHENTICATE-OK to the minion.
- The body of AUTHENTICATE-OK consists of the current master key, master signature, and port number for the specified domain. The master signature consists of the six letters "MASTER", encrypted using the master's private key. The body is encrypted with the minion's public key.
- The minion decrypts the AUTHENTICATE-OK body using its private key, then decrypts the master signature using the master's public key, and verifies that the result is equal to the master's public key. If this succeeds, the minion will use the decrypted master key to decrypt data published by the master.
The format of the AUTHENTICATE command is:
- Frame 0: "AUTHENTICATE" (0MQ string)
- Frame 1: security mechanism (0MQ string, e.g. "RSA")
- Frame 2: encrypted body (length-specified blob)
Where the encrypted body is formatted as follows:
[size][domain] as one byte followed by 0MQ string
[size][minion name] as one byte followed by 0MQ string
[size][signature] as one byte followed by blob
The format of the AUTHENTICATE-OK command is:
- Frame 0: "AUTHENTICATE-OK" (0MQ string)
- Frame 1: security mechanism (0MQ string, e.g. "RSA")
- Frame 2: encrypted body (length-specified blob)
Where the encrypted body is formatted as follows:
[size][domain] as one byte followed by 0MQ string
[port] as two-byte integer, in network order
[size][signature] as one byte followed by blob
Data Distribution
- The minion connects a SUB socket to the specified port on the master host, which is bound to a PUB socket.
- The master encrypts and sends data using the master key.
- The minion decrypts data using the master key.
- If the master regenerates its master data key, the minion will be unable to decrypt traffic, and will re-authenticate to get the new data key before continuing.
The format of publish-subscribe data is:
- Frame 0: filter (0MQ string, unencrypted)
- Frame 1: security mechanism (0MQ string, e.g. "AES")
- Frame 2: encrypted body (length-specified blob)
The filter may be left empty.
Encryption Mechanisms
- "RSA" - the body is encrypted using the RSA public key of the intended recipient.
- "AES" - the body is encrypted using the AES master key.
- "CLEAR" - the body is not encrypted in any way.
Man in the Middle Attacks
A MIM attacker cannot create fraudulent AUTHENTICATE or AUTHENTICATE-OK commands because it cannot create valid signatures, not knowing the private keys.
A MIM attacker can create fraudulent data messages and can modify the filter.

1. You're vulnerable to a replay-attack, so an attacker is able to re-send messages in the window between master-key changes.
2. Renegotiation can be forced by an attacker injecting crap into the data stream; this is indistinguishable from the master actually asking for renegotiation. This can cause a DoS on both master and minion, since asymmetric encryption is CPU-intensive. Problem gets worse with number of minions.
3. I think you might want to get a cryptographer to look this over.
Thanks for the comments. I assume a reply attack can be rendered meaningless by sequencing messages, and discarding duplicates. Renegotiation could be a nasty DoS… but can be managed by throttling, IMO.
Portfolio
Is the raw tcp/ip protocol for 0mq susceptible to subversion — be that sending malformed packets that produce DoS attacks, etc. How well tested are the underlying transport methods to buffer overflow attacks, etc.
I am not sure if this proposal still stands but I will proceed to comment for posterity as it does not seem to be obviously outdated.
Although this draft does implement a signature for identity verification, this seems almost redundant as there is no capacity to ensure message integrity.
The "signatures" generated here could just be copied from a valid request and used to "sign" any other request.
It therefore follows that the signature should be derived from the actual content of the message rather than a known, arbitrary string, this is near enough industry standard and seems like a significant oversight.
This could simply be achieved by hashing (sha256 would be advisable) the actual contents of the message and then encrypting this with the senders private to generate a signature unique to that message, for example the minion may (pseudo code):
digest = sha256(desired_domain + minion_name) #include everything in the message
signature = private_encrypt(digest)
The message would include the data + the signature. The master would decrypt the signature, reconstruct the digest using the actual message body and verify this matches the signature provided, we know they are who they say they are, and we know the message arrived as it was sent.
I also notice that this system doesn't provide backward secrecy: If an attacker were recording all traffic and then a private key were compromised, the attacker could then obtain all master keys and decrypt all the recorded traffic.
A solution to this would be to use the public/private RSA key pair for nothing but authentication. The master AES key exchange mechanism would instead use Diffie-Hellman to negotiate a single-use session key, and then use that to exchange the new AES master key. Then the system would throw away the Diffie-Hellman key.
The effect of this would be that an attacker who had managed to obtain an RSA private key and recorded past traffic would still not have the Diffie-Hellman session key for a particular master key change, so he wouldn't be able to derive the AES master key. Past traffic would remain safe, though of course future traffic will only be safe from this attacker if the private key compromise was detected and that minion's public key removed from the master's whitelist.