Can I swap the private and public key within ZeroMQ - c

At the moment, I am investigating the possibilities to use ZeroMQ with Curve to secure traffic between my publishers and subscribers.
I have successfully implemented a pub sub system which is using CZMQ.
At the moment, my publisher is encrypting the data he wants to send with his private key and subscribers can decrypt this data using the public key of the publisher. This is more 'authenticating' data than 'encrypting' data. Because when there is a Man In The Middle he can still decrypt all the data because the public key of the publisher is public.
I'm coding in C with the latest version of ZeroMQ and CZMQ.
My publisher.c
zctx_t* zmq_context = zctx_new();
zauth_t* auth = zauth_new (zmq_context);
zauth_set_verbose (auth, true);
zauth_configure_curve (auth, "*", CURVE_ALLOW_ANY);
zcert_t* pub_cert = zcert_load("cert.key"); // private key of publisher
void* socket = zsocket_new(zmq_context, ZMQ_PUB);
zcert_apply(pub_cert, socket);
zsocket_set_curve_server(socket, true);
//start publishing from here
My subscriber.c
zctx_t* zmq_context = zctx_new();
zcert_t* sub_cert = zcert_new();
zcert_t* pub_cert = zcert_load("cert.pub"); // public key of publisher
char* pub_key = zcert_public_txt(pub_cert);
void* zmq_s = zsocket_new(zmq_context, ZMQ_SUB);
zcert_apply(sub_cert, zmq_s);
zsocket_set_curve_serverkey(zmq_s, pub_key);
//start subscribing to topics and receiving messages from here
From this point, the publisher is encrypting all the data with his private key and the subscribing is decrypting all the data with the public key of the publisher. I would like to swap this system.
So, I would like to encrypt all the data with the public key of the publisher and decrypt all the data with the private key of the publisher.
I have tested it and changed the zcert_load("cert.key") to zcert_load("cert.pub") in my publisher.c.
I also changed this code in my subscriber.c:
zcert_t* pub_cert = zcert_load("cert.pub"); // public key of publisher
char* pub_key = zcert_public_txt(pub_cert);
to this code:
zcert_t* pub_cert = zcert_load("cert.key"); // private key of publisher
char* pub_key = zcert_secret_txt(pub_cert);
When I run my publisher and subscriber with these code changes, the publisher is constantly giving me the message: CURVE I: cannot open client HELLO -- wrong server key?
My question: Is it possibile to use a public key for encrypting data (publisher socket) and the private key for decrypting data (subscriber socket) with the architecture of ZeroMQ and CZMQ ?
Many thanks in advance,
Roy

I think you're misunderstanding the ZeroMQ CURVE mechanism. There are two great articles written about it by Pieter Hintjens, one is theoretical, where you can find this:
Clients and servers have long-term permanent keys, and for each connection, they create and securely exchange short-term transient keys. Each key is a public/secret keypair, following the elliptic curve security model.
To start a secure connection the client needs the server permanent public key. It then generates a transient key pair and sends a HELLO command to the server that contains its short term public key. The HELLO command is worthless to an attacker; it doesn't identify the client.
The server, when it gets a HELLO, generates its own short term key pair (one connection uses four keys in total), and encodes this new private key in a "cookie", which it sends back to the client as a WELCOME command. It also sends its short term public key, encrypted so only the client can read it. It then discards this short term key pair.
At this stage, the server hasn't stored any state for the client. It has generated a keypair, sent that back to the client in a way only the client can read, and thrown it away.
The client comes back with an INITIATE command that provides the server with its cookie back, and the client permanent public key, encrypted as a "vouch" so only the server can read it. As far as the client is concerned, the server is now authenticated, so it can also send back metadata in the command.
The server reads the INITIATE and can now authenticate the client permanent public key. It also unpacks the cookie and gets its short term key pair for the connection. As far as the server is now concerned, the client is now authenticated, so the server can send its metadata safely. Both sides can then send messages and commands.
So the keys you generate here are not used directly to encrypt data, they are only used to authenticate parties. The handshake process between client and server produces real encryption (and authentication as in MAC) keys that are used to encrypt the data. So if the only concern you have is MITM, you're already protected.
But you can also be concerned about rogue clients, your current scheme allows anyone to connect. This is where the second article by Pieter Hintjens can help you with "The Ironhouse Pattern". The critical part is to disable CURVE_ALLOW_ANY and tell server where to look for client public certificates:
// Tell authenticator to use the certificate store in .curve
zauth_configure_curve (auth, "*", ".curve");
Then you generate client key on the client (once! not calling zcert_new() for every connection), transfer its public part to the ".curve" directory of your server and load (on the client) that key instead of calling zcert_new().
If you want to make life a bit easier (not needing to transfer public keys from client to server for each client), you can create a "golden" client key pair, get its public part into the ".curve" store and then (via a secure channel, of course) copy the secret key on every client that needs to connect to your publisher.

Related

Multiple private and public key for same user

If a user have 2 pairs of public and private key, how can the server that has the public keys know which one to use? The server should encrypt the message using the public key to that private key, however how does it know?
No. SSH does not do Encrypt&Decrypt, but Sign&Verify sequence.
The server sends some data, client signs them using its private key and server can verify the data using all of the public keys it has stored in authorized_keys file.
But in real world, there is optional phase before doing all the above. The client sends also the public keys to match correct public part on the server.

Apache Camel Content Based Routing on Websocket Connections

I have a hypothetical scenario: let’s pretend I have an Apache Camel websocket server and I’m allowing many websocket connections. Each client connection will need to be associated with a ClientID. The ClientID is obtained by a new connection via an InitConnection json message where a ClientID is a member of the message. The question is: is it possible to have camel associate a websocket instance with a ClientID in order to perform content based routing?
yes, It is possible. you can retrieve a UUID of each client by below method:
from("direct:Consumer1")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
Map<String, Object> headers=exchange.getIn().getHeaders();
//you can get a unique connection key from the exchange header.
//store this key somewhere, to send messages to particular client.
String uniqueConnectionKey=headers.get("websocket.connectionKey").toString();
//you can get message from the client like below.
String dataFromClient=exchange.getIn().getBody().toString();
}
}).end();
you need to map this unique key with ur client id, so that u can send messages to particular client using this UUID.
CamelContext camelContext=new DefaultCamelContext();
ProducerTemplate template=camelContext.createProducerTemplate();
template.sendBodyAndHeader("direct:Producer1", {message}, "connectionKey", {connectionkey});
direct:Producer1 : producer endpoint name.
connectionkey : a unique connection key, which you will get from the exchange header in websocket consumer.
message : message to the websocket endpoint.
Edit :
here is the producer route.
from("direct:Producer1").
//we will use this connectionKey for uniquely identifying each connection from the client.
setHeader(WebsocketConstants.CONNECTION_KEY, header("connectionKey")).
to("websocket://{host}:{port}/camel-websocket?sendToAll=false").end();

Storing chat conversations in sql database using signalR

I'm developing a class library that contains generic methods for these scenarios:
Live support chat (1 on 1 private text chat, with many admins and guests)
Rooms with many users where you can send broadcast and private messages
These two features above are already implemented and now it's necessary for my application to save messages.
My question is, what is the best way to store chat conversations in a SQL database:
Everytime I click send, I insert the message in the database?
Create a List for each user and everytime I click send, the message is saved on the list of the user who sent the message. Then if a user disconnects, I'm going to iterate the list of messages and for each message insert all of them in the db.
Are there other solutions?
What I'm doing now is the following. I have this method which is located on my Hub class:
public void saveMessagetoDB(string userName, string message)
{
var ctx = new TestEntities1();
var msg = new tbl_Conversation {Msg = message};
ctx.tbl_Conversation.Add(msg);
ctx.SaveChanges();
}
I call this method saveMessagetoDB on my client side HTML file like this:
$('#btnSendMessage').click(function () {
var msg = $("#txtMessage").val();
if (msg.length > 0) {
var userName = $('#hUserName').val();
// <<<<<-- ***** Return to Server [ SaveMessagetoDB ] *****
objHub.server.saveMessagetoDB(userName, msg);
SignalR is great for a chat application and you wouldn't even need to store anything in SQL unless you want to create a transcript of the chat at a later time (which may not even be necessary).
I suggest getting the chat working with SignalR first (don't do anything with sql). Then once that is working you can put SQL logging as necessary in your signalR hub.
It most likely makes the most sense to write to sql on each message.
If you decide to store the chats in a database, then you will need to insert/update the messages as they happen.
If you are using the PersistentConnection then you can hook into the OnReceivedAsync event and insert / update data from that event:
protected override Task OnConnectedAsync(IRequest request, string connectionId)
{
_clients.Add(connectionId, string.Empty);
ChatData chatData = new ChatData("Server", "A new user has joined the room.");
return Connection.Broadcast(chatData);
}
Or in the SignalR class that inherits from Hub, you can persist to the Db right before you have notified any clients.

How to sign a SAML2 assertion with the encryption key(s)

I need to create a SAML2 assertion for a business partner we work with, who now requires a SAML2 SSO. We would be the identity provider.
They sent us their Public Key. We created a public key and sent ours to them. During the creation step, we had the option to exclude the private key and we did so.
I am not sure which combination of keys, and which form of the key (public or private), is used in the signing phase. What do we do with their public key? What do we do with our public and private keys? Do I have to create another version of our key that includes the private key?
Would someone care to offer a simple step by step explanation of a generic signing process, making clear which form of the key is used, and when?
First off. You do not give your private key to another entity. The whole point of the private-public key system is that you dont need to share you private key.
Signing is done with your private key and verified using your public key.
Encryption is down using theirs public key and is decrypted using their private key.

CryptoApi: Export a certificate without the private key?

I have generated a self signed certificate using the CertCreateSelfSignCertificate function. This yields a PCCERT_CONTEXT.
How can I export the certificate stored in the PCCERT_CONTEXT variable with only the public key? I want to do this, to send it to other parties in the network, so these are able to encrypt messages using the public key.
I thought this was a straight forward option, but it isnt.
No need for a pfx.
The certificate is present inside the structure CERT_CONTEXT : just save the content of the buffer pointed by the member pbCertEncoded and whose length is the value of the member cbCertEncoded.
Moreover, the public key from this certificate is directly present in the CERT_CONTEXT structure : pCertInfo->SubjectPublicKeyInfo. For example, you can import it using CryptImportPublicKeyInfo and then call CryptEncrypt to encrypt data.
With these two options, you have all what is needed to start encrypting messages. Of course, the private key must be kept safe to be able to decrypt encrypted data.
Looks like you will need to first put the certificate into a certificate store and then export it using PFXExportCertStoreEx passing dwFlags of 0 (i.e. not setting EXPORT_PRIVATE_KEYS).
P.S. nothing is ever straight forward when dealing with cryptography libraries, be it CryptAPI, JSSE, OpenSSL... it's always a nightmare.

Resources