[zeromq-dev] Message source identification/authentication

Eric Hill eric at ijack.net
Sun May 12 05:59:01 CEST 2013

> But what prevents one peer from
> impersonating another?  Absolutely nothing, because by the time the
> message gets to the application layer the authentication information
> has been lost.

The thing that prevents one peer from impersonating another is each peer
should have a unique secret shared only with the server.  Any other client
that attempts to send a message with a bogus client id will fail because it
cannot authenticate the message (HMAC, etc) because it doesn't have the
key.  Client C sends message M to server S with key K using MC+HMAC(MC, K)
-> S.  This means the client sends the message M and client identity C
along with the HMAC of the message M and client C using key K to the server
S.  Ok so far?

Now, replay attacks are another problem.  Client C sends message M to
server S, and jerk J sees the message on the line.  If J re-sends M to S, S
cannot tell that the message didn't originate from C.  I think this is the
problem you're trying to explain.

So what is one way to solve it?  Time.

When client C sends a message, we add time T to the message:  MCT+HMAC(MCT,
K) -> S

Once the server receives the message, it verifies the HMAC of MCT to
authenticate the message, then verifies the time T is within +/-whatever
seconds of "now".  If a time stamp on a message deviates more than however
many seconds/minutes/whatever from the server time, we assume the message
is a replay and discard it.

Another method is an integer sequence I.  For every message M the client
sends, it increments the counter.  I++, then MCI+HMAC(MCI, K) -> S

The server maintains a dictionary D of counters by client C.  We'll call
this D[C] = I

When the server S receives a message M from the client C, it can check D[C]
<= I to see if the last seen counter is less than or equal to the received
messages' I.  If so, discard the message as a replay.  If not, save D[C] =
I for the next time we receive a message from the client.

An advantage to using time is that you don't have to hold a dictionary on
the server.  However if a replay could happen in sub-millisecond time, you
may not be able to reliably use that method.

Hope this helps.

On Sat, May 11, 2013 at 2:14 PM, Randall Nortman <rnzmq at wonderclown.net>wrote:

> I know this has been discussed before on this list and there are some
> RFC's related to secure authentication, but I have not yet seen any
> reasonable solutions, because of a limitation in the libzmq API.  The
> encryption/authentication built into ZMTPv3.0 doesn't seem to fix the
> problem, because the problem is at the API level.  Let me start by
> illustrating the problem with a simple example:
> Let's say we have a server which maintains some data for
> clients/peers.  Let's call the data "files" for this example, but it
> could be anything.  The files are owned by particular clients (which
> are peers with respect to the protocol, but clients with respect to
> the file service).  Clients are somehow known to the server
> (previously shared keys), and they can store and retrieve their own
> files, but should not be able to access the files of other clients.
> Let's say you do something smart like put the whole thing on a VPN
> using client certificates to authenticate clients and assign them a
> static IP on the VPN.  The VPN makes sure that the private IP
> addresses cannot be spoofed.  So if I were writing a server based on
> traditional sockets rather than ZMQ, I'd just trust that if I get a
> packet from, then that is definitely from the client
> assigned that address and no additional authentication is required.
> You could also do it with SSL using client certificates, and then my
> SSL-based server would just query the SSL library for the identity of
> the client connected to the socket and everything would be great.
> Now let's say you've got ZMQ running on top of the same kind of VPN or
> SSL setup.  Or you're using the CurveCP/CurveZMQ underlying transport
> or the SASL mechanism in the ZMTPv3.0 spec.  Great, you at least know
> that anybody that connects to you is a known peer.  But when you get a
> message, you don't know what peer sent it, because zmq_recv has no way
> of communicating that to you.  So your protocol of course will need to
> have the client ID in each message.  But what prevents one peer from
> impersonating another?  Absolutely nothing, because by the time the
> message gets to the application layer the authentication information
> has been lost.
> So now you *have* to put authentication on top of ZMQ, at the
> application level, and sign each message.  So now each ZMQ application
> needs to implement crypto, and it is way, way too easy to get that
> wrong to have it happening at the application layer.  (The
> pubsub-security draft at http://www.zeromq.org/topics:pubsub-security
> nicely illustrates how easy it is to get this stuff terribly, horribly
> wrong, because nothing in that protocol stops replay attacks, as has
> already been pointed out in the comments.)
> Furthermore, it seems like unnecessary overhead, given that the
> underlying layers may already have authenticated the peer (if auth at
> the ZMTP layer is being used, for example, or CurveCP/TLS/VPN
> underneath that).
> Could the API simply provide a way to identify the sender of each
> message somehow?  The "identity" could be handled as a blob whose
> interpretation is dependent on the underlying transport, anything from
> an IP address up to the CN from the peer's X509 certificate.  This
> does not do a whole lot to help in the case of multi-hop
> (routed/proxied) messages, but it at least gives you single-hop
> authentication, which is good enough for a large number of
> applications.  And it could perhaps serve as the basis for end-to-end
> multi-hop authentication as well.  If end-to-end auth is going to be
> done by signing each message (a reasonable way to do it), then that
> *must* be part of the ZMQ spec and the libzmq implementation, because
> you simply cannot leave it up to each application to design and
> implement crypto properly.
> Am I missing something?  Has this been handled somehow already?
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20130511/298264e9/attachment.htm>

More information about the zeromq-dev mailing list