I am fairly new to ZeroMQ and have been comparing security of messages using the ZeroMQ NuGet package and the NetMQ & NetMQ Security NuGet packages.
So far, I have not been able to find a C# version of the Ironhouse example using Curve Security. There is a "todo" item on the ZGuides repo but so far nothing implemented. (https://github.com/metadings/zguide/issues/1)
I am also trying to determine whether the NetMQ.Security approach to security is better than the curve security approach that is built into ZeroMQ 4. It seems like most information about Curve is at least from 2014 or earlier.
Any information would be greatly appreciated!
ZeroMQ provides a whole slew of language APIs which run on most operating systems and allows you to communicate seamlessly between all sorts of programs. It also provides a collection of patterns, such as request-reply and publish-subscribe which assist you in creating and structuring your network.
ZeroMQ still works great and the open source community is still maintaining it on GitHub [3].
ZeroMQ (also spelled ØMQ, 0MQ or ZMQ) is an asynchronous messaging library, aimed at use in distributed or concurrent applications. It provides a message queue, but unlike message-oriented middleware, a ZeroMQ system can run without a dedicated message broker; the zero in the name is for zero broker.
ZeroMQ sockets carry messages, like UDP, rather than a stream of bytes as TCP does. A ZeroMQ message is length-specified binary data.
Both publisher and subscriber need to use its own set of public\private keys. In your sample code for subscriber you set CurvePublicKey
(to that of server, which is wrong but still) but do not set CurveSecretKey
- that's why you get "cannot open client INITIATE vouch". Here is your sample from another question fixed:
public class Program
{
static void Main(string[] args) {
using (var context = new ZContext()) {
Console.WriteLine($"Curve Supported: {ZeroMQ.ZContext.Has("curve")}");
byte[] serverPublicKey;
byte[] serverSecretKey;
Z85.CurveKeypair(out serverPublicKey, out serverSecretKey);
var publisher = new ZSocket(context, ZSocketType.PUB);
publisher.CurvePublicKey = serverPublicKey;
publisher.CurveSecretKey = serverSecretKey;
publisher.CurveServer = true;
publisher.Bind("tcp://*:5050");
var subscriber = new ZSocket(context, ZSocketType.SUB);
byte[] subPublicKey;
byte[] subSecretKey;
Z85.CurveKeypair(out subPublicKey, out subSecretKey);
subscriber.CurvePublicKey = subPublicKey;
subscriber.CurveSecretKey = subSecretKey;
subscriber.CurveServerKey = serverPublicKey;
ZError connectError;
subscriber.Connect("tcp://mybox:5050", out connectError);
if (connectError != null) {
Console.WriteLine($"Connection error: {connectError.Name} - {connectError.Number} - {connectError.Text}");
}
subscriber.SubscribeAll();
// Publish some messages
Task.Run(() => {
for (var i = 1; i <= 5; i++) {
var msg = $"Pub msg: {Guid.NewGuid().ToString()}";
using (var frame = new ZFrame(msg)) {
publisher.Send(frame);
}
}
});
Task.Run(() => {
// Receive some messages
while (true) {
using (var frame = subscriber.ReceiveFrame()) {
var msg = frame.ReadString();
Console.WriteLine($"Received: {msg}");
}
}
});
Console.WriteLine("Press ENTER to exit");
Console.ReadLine();
ZError subError;
subscriber.Disconnect("tcp://mybox:5050", out subError);
subscriber.Dispose();
ZError pubError;
publisher.Disconnect("tcp://*:5050", out pubError);
publisher.Dispose();
}
}
}
Indeed, there are not much C# examples with NetMQ. I found this that works "CurveTests.cs":
public void CurveTest()
{
var serverPair = new NetMQCertificate();
using var server = new DealerSocket();
server.Options.CurveServer = true;
server.Options.CurveCertificate = serverPair;
server.Bind($"tcp://127.0.0.1:55367");
var clientPair = new NetMQCertificate();
using var client = new DealerSocket();
client.Options.CurveServerKey = serverPair.PublicKey;
client.Options.CurveCertificate = clientPair;
client.Connect("tcp://127.0.0.1:55367");
for (int i = 0; i < 100; i++)
{
client.SendFrame("Hello");
var hello = server.ReceiveFrameString();
Assert.Equal("Hello", hello);
server.SendFrame("World");
var world = client.ReceiveFrameString();
Assert.Equal("World", world);
}
}
Important note - if you want to share server public key between different applications, don't use string representation (serverPair.PublicKeyZ85), because encryption won't work. I assume it related to encoding. Better save byte array representation to some file and share it instead:
File.WriteAllBytes("serverPublicKey.txt", serverPair.PublicKey);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With