Last active
December 15, 2015 07:39
-
-
Save hintjens/5224958 to your computer and use it in GitHub Desktop.
CurveZMQ prototype - see http://hintjens.com/blog:36 for the story.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ========================================================================= | |
CurveZMQ - authentication and confidentiality for 0MQ | |
------------------------------------------------------------------------- | |
Copyright (c) 1991-2013 iMatix Corporation <www.imatix.com> | |
Copyright other contributors as noted in the AUTHORS file. | |
This is free software; you can redistribute it and/or modify it under | |
the terms of the GNU Lesser General Public License as published by | |
the Free Software Foundation; either version 3 of the License, or (at | |
your option) any later version. | |
This software is distributed in the hope that it will be useful, but | |
WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Lesser General Public License for more details. | |
You should have received a copy of the GNU Lesser General Public | |
License along with this program. If not, see | |
<http://www.gnu.org/licenses/>. | |
========================================================================= | |
*/ | |
#include <czmq.h> | |
#include <sodium.h> | |
#include "zcurve.h" | |
#if crypto_box_PUBLICKEYBYTES != 32 \ | |
|| crypto_box_SECRETKEYBYTES != 32 \ | |
|| crypto_box_BEFORENMBYTES != 32 | |
# error "libsodium not built correctly" | |
#endif | |
typedef enum { | |
pending, // Waiting for first event | |
expect_hello, // S: accepts HELLO from client | |
expect_cookie, // C: accepts COOKIE from server | |
expect_initiate, // S: accepts INITIATE from client | |
connected // C/S: accepts MESSAGE from server | |
} state_t; | |
// Structure of our class | |
struct _zcurve_t { | |
// Long term keys, if known | |
byte public_key [32]; // Our public key | |
byte secret_key [32]; // Our secret key | |
// Server connection properties | |
byte cookie_key [32]; // Server cookie key | |
byte cn_client [32]; // Client's short-term public key | |
// Client connection properties | |
byte server_key [32]; // Server public key | |
byte cn_server [32]; // Server's short-term public key | |
byte cn_cookie [96]; // Connection cookie from server | |
// Symmetric connection properties | |
bool is_server; // True or false | |
state_t state; // Connection state | |
int64_t cn_nonce; // Connection nonce | |
byte cn_public [32]; // Connection public key | |
byte cn_secret [32]; // Connection secret key | |
byte cn_precom [32]; // Connection precomputed key | |
zmq_msg_t msg; // ZMQ message to send to peer | |
}; | |
// Command types, taken from CurveCP handshake | |
#define C_HELLO "QvnQ5XlH" | |
#define S_COOKIE "RL3aNMXK" | |
#define C_INITIATE "QvnQ5XlI" | |
#define CS_MESSAGE "RL3Q5XlM" | |
// Command structures | |
typedef struct { | |
byte id [8]; // Command ID | |
byte cn_client [32]; // Client short-term public key C' | |
byte cn_nonce [8]; // Client short-term nonce | |
byte box [80]; // Box [64 * %x0](C'->S) | |
byte padding [64]; // Anti-amplification padding | |
} c_hello_t; | |
typedef struct { | |
byte id [8]; // Command ID | |
byte nonce [16]; // Server long-term nonce | |
byte box [144]; // Box [S' + cookie](C'->S) | |
} s_cookie_t; | |
typedef struct { | |
byte id [8]; // Command ID | |
byte cn_client [32]; // Client short-term public key C' | |
byte cn_cookie [96]; // Server connection cookie | |
byte cn_nonce [8]; // Client short-term nonce | |
byte box [112]; // Box [C + nonce + vouch](C'->S') | |
} c_initiate_t; | |
typedef struct { | |
byte id [8]; // Command ID | |
byte cn_nonce [8]; // Server short-term nonce | |
byte box [116]; // Box [M](A'->B') (from A to B) | |
} cs_message_t; | |
// -------------------------------------------------------------------------- | |
// Constructor. Always generates a new public/secret key pair which | |
// you can override if you need to. | |
zcurve_t * | |
zcurve_new (void) | |
{ | |
zcurve_t | |
*self; | |
self = (zcurve_t *) zmalloc (sizeof (zcurve_t)); | |
int rc; | |
// Generate long-term key pair, in case we need it | |
rc = crypto_box_keypair (self->public_key, self->secret_key); | |
assert (rc == 0); | |
// Generate short-term key pair | |
rc = crypto_box_keypair (self->cn_public, self->cn_secret); | |
assert (rc == 0); | |
self->state = pending; | |
return self; | |
} | |
// -------------------------------------------------------------------------- | |
// Destructor | |
void | |
zcurve_destroy (zcurve_t **self_p) | |
{ | |
assert (self_p); | |
if (*self_p) { | |
zcurve_t *self = *self_p; | |
zmq_msg_close (&self->msg); | |
free (self); | |
*self_p = NULL; | |
} | |
} | |
// -------------------------------------------------------------------------- | |
// Return value of public key | |
byte * | |
zcurve_public_key (zcurve_t *self) | |
{ | |
assert (self); | |
return self->public_key; | |
} | |
// -------------------------------------------------------------------------- | |
// Set public key from provided value | |
void | |
zcurve_public_key_set (zcurve_t *self, byte *public_key) | |
{ | |
assert (self); | |
memcpy (self->public_key, public_key, 32); | |
} | |
// -------------------------------------------------------------------------- | |
// Return value of secret key | |
byte * | |
zcurve_secret_key (zcurve_t *self) | |
{ | |
assert (self); | |
return self->secret_key; | |
} | |
// -------------------------------------------------------------------------- | |
// Set secret key from provided value | |
void | |
zcurve_secret_key_set (zcurve_t *self, byte *secret_key) | |
{ | |
assert (self); | |
memcpy (self->secret_key, secret_key, 32); | |
} | |
static void | |
s_dump (byte *buffer, int size, char *prefix) | |
{ | |
printf ("\n%s: ", prefix); | |
int byte_nbr; | |
for (byte_nbr = 0; byte_nbr < size; byte_nbr++) | |
printf ("%02X ", buffer [byte_nbr]); | |
printf ("\n"); | |
} | |
// -------------------------------------------------------------------------- | |
// Start zcurve instance as client (if you provide a server key) or as | |
// server. May return a zmq_msg_t to send to the peer, or NULL if there | |
// is nothing to send. | |
zmq_msg_t * | |
zcurve_start (zcurve_t *self, byte *server_key) | |
{ | |
assert (self); | |
assert (self->state == pending); | |
zmq_msg_t *outgoing = NULL; | |
// If caller provides us with server's long term public key, | |
// we are acting as client, so send HELLO command | |
if (server_key) { | |
// Store server public key | |
memcpy (self->server_key, server_key, 32); | |
// Working variables for crypto calls | |
byte nonce [24]; | |
byte box [256]; | |
byte plain [256]; | |
// Create Box [64 * %x0](C'->S) | |
assert (crypto_box_ZEROBYTES == 32); | |
memset (plain, 0, crypto_box_ZEROBYTES + 64); | |
// Prepare the full nonce and encrypt | |
assert (crypto_box_NONCEBYTES == 24); | |
memcpy (nonce, (byte *) "CurveCP-client-H", 16); | |
memcpy (nonce + 16, &self->cn_nonce, 8); | |
int rc = crypto_box (box, plain, crypto_box_ZEROBYTES + 64, | |
nonce, self->server_key, self->cn_secret); | |
assert (rc == 0); | |
// Prepare full command ready for sending | |
zmq_msg_close (&self->msg); | |
zmq_msg_init_size (&self->msg, sizeof (c_hello_t)); | |
c_hello_t *hello = (c_hello_t *) zmq_msg_data (&self->msg); | |
memcpy (hello->id, C_HELLO, 8); | |
memcpy (hello->cn_client, self->cn_public, 32); | |
memcpy (hello->cn_nonce, &self->cn_nonce, 8); | |
memcpy (hello->box, box + crypto_box_BOXZEROBYTES, sizeof (hello->box)); | |
outgoing = &self->msg; | |
// Set next state for our connection | |
self->cn_nonce++; | |
self->is_server = false; | |
self->state = expect_cookie; | |
} | |
else { | |
self->is_server = true; | |
self->state = expect_hello; | |
} | |
return outgoing; | |
} | |
// -------------------------------------------------------------------------- | |
// Decode and process incoming commands, return reply message if any | |
zmq_msg_t * | |
s_process_hello (zcurve_t *self, c_hello_t *hello) | |
{ | |
// Working variables for crypto calls | |
byte nonce [24]; | |
byte box [256]; | |
byte plain [256]; | |
// Decode HELLO command | |
printf ("C:HELLO: "); | |
// Open Box [64 * %x0](C'->S) | |
memset (box, 0, crypto_box_BOXZEROBYTES); | |
memcpy (box + crypto_box_BOXZEROBYTES, hello->box, sizeof (hello->box)); | |
// Prepare the full nonce and decrypt | |
memcpy (nonce, (byte *) "CurveCP-client-H", 16); | |
memcpy (nonce + 16, hello->cn_nonce, 8); | |
int rc = crypto_box_open (plain, box, | |
crypto_box_BOXZEROBYTES + sizeof (hello->box), | |
nonce, hello->cn_client, self->secret_key); | |
assert (rc == 0); // In practice, if box doesn't open, discard it | |
puts ("OK"); | |
// Generate cookie = Box [C' + s'](t), | |
memset (plain, 0, crypto_box_ZEROBYTES); | |
memcpy (plain + crypto_box_ZEROBYTES, hello->cn_client, 32); | |
memcpy (plain + crypto_box_ZEROBYTES + 32, self->cn_secret, 32); | |
// Create full nonce for encryption | |
// 8-byte prefix plus 16-byte random nonce | |
assert (crypto_box_BOXZEROBYTES == 16); | |
byte cookie_nonce [16]; | |
randombytes (cookie_nonce, 16); | |
memcpy (nonce, (byte *) "Cookie--", 8); | |
memcpy (nonce + 8, cookie_nonce, 16); | |
// Encrypt using symmetric cookie key | |
byte cookie_box [96]; | |
// Generate fresh cookie key | |
randombytes (self->cookie_key, 32); | |
rc = crypto_secretbox (cookie_box, plain, 96, nonce, self->cookie_key); | |
assert (rc == 0); | |
// Now create 144-byte Box [S' + cookie] (S->C') | |
memset (plain, 0, crypto_box_ZEROBYTES); | |
memcpy (plain + crypto_box_ZEROBYTES, self->cn_public, 32); | |
memcpy (plain + crypto_box_ZEROBYTES + 32, cookie_nonce, 16); | |
memcpy (plain + crypto_box_ZEROBYTES + 48, | |
cookie_box + crypto_box_BOXZEROBYTES, 80); | |
// Prepare the full nonce and encrypt | |
// 8-byte prefix plus 16-byte random nonce | |
randombytes (cookie_nonce, 16); | |
memcpy (nonce, (byte *) "CurveCPK", 8); | |
memcpy (nonce + 8, cookie_nonce, 16); | |
rc = crypto_box (box, plain, crypto_box_ZEROBYTES + 128, | |
nonce, hello->cn_client, self->secret_key); | |
assert (rc == 0); | |
// Prepare full command ready for sending | |
zmq_msg_close (&self->msg); | |
zmq_msg_init_size (&self->msg, sizeof (s_cookie_t)); | |
s_cookie_t *cookie = (s_cookie_t *) zmq_msg_data (&self->msg); | |
memcpy (cookie->id, S_COOKIE, 8); | |
memcpy (cookie->nonce, cookie_nonce, 16); | |
memcpy (cookie->box, | |
box + crypto_box_BOXZEROBYTES, sizeof (cookie->box)); | |
return &self->msg; | |
} | |
zmq_msg_t * | |
s_process_cookie (zcurve_t *self, s_cookie_t *cookie) | |
{ | |
// Working variables for crypto calls | |
byte nonce [24]; | |
byte box [256]; | |
byte plain [256]; | |
// Decode COOKIE command | |
printf ("S:COOKIE: "); | |
// Open Box [S' + cookie](C'->S) | |
memset (box, 0, crypto_box_BOXZEROBYTES); | |
memcpy (box + crypto_box_BOXZEROBYTES, | |
cookie->box, sizeof (cookie->box)); | |
// Prepare the full nonce and decrypt | |
memcpy (nonce, (byte *) "CurveCPK", 8); | |
memcpy (nonce + 8, cookie->nonce, 16); | |
int rc = crypto_box_open (plain, box, | |
crypto_box_BOXZEROBYTES + sizeof (cookie->box), | |
nonce, self->server_key, self->cn_secret); | |
assert (rc == 0); | |
puts ("OK"); | |
// Get server cookie and short-term key | |
memcpy (self->cn_server, plain + crypto_box_ZEROBYTES, 32); | |
memcpy (self->cn_cookie, plain + crypto_box_ZEROBYTES + 32, 96); | |
// Precompute connection secret from server key | |
rc = crypto_box_beforenm (self->cn_precom, | |
self->cn_server, self->cn_secret); | |
assert (rc == 0); | |
// Create vouch = Box [C'](C->S) | |
memset (plain, 0, crypto_box_ZEROBYTES); | |
memcpy (plain + crypto_box_ZEROBYTES, self->cn_public, 32); | |
// Prepare the full nonce and encrypt | |
byte vouch_nonce [16]; | |
randombytes (vouch_nonce, 16); | |
memcpy (nonce, (byte *) "CurveCPV", 8); | |
memcpy (nonce + 8, vouch_nonce, 16); | |
rc = crypto_box (box, plain, crypto_box_ZEROBYTES + 32, | |
nonce, self->server_key, self->secret_key); | |
assert (rc == 0); | |
// Vouch is in box after initial null padding | |
byte *vouch_box = box + crypto_box_BOXZEROBYTES; | |
// Create Box [C + nonce + vouch](C'->S') | |
memset (plain, 0, crypto_box_ZEROBYTES); | |
memcpy (plain + crypto_box_ZEROBYTES, self->public_key, 32); | |
memcpy (plain + crypto_box_ZEROBYTES + 32, vouch_nonce, 16); | |
memcpy (plain + crypto_box_ZEROBYTES + 48, vouch_box, 48); | |
// Prepare the full nonce and encrypt | |
memcpy (nonce, (byte *) "CurveCP-client-I", 16); | |
memcpy (nonce + 16, &self->cn_nonce, 8); | |
rc = crypto_box (box, plain, crypto_box_ZEROBYTES + 96, | |
nonce, self->cn_server, self->cn_secret); | |
assert (rc == 0); | |
// Prepare full command ready for sending | |
zmq_msg_close (&self->msg); | |
zmq_msg_init_size (&self->msg, sizeof (c_initiate_t)); | |
c_initiate_t *initiate = (c_initiate_t *) zmq_msg_data (&self->msg); | |
memcpy (initiate->id, C_INITIATE, 8); | |
memcpy (initiate->cn_client, self->cn_public, 32); | |
memcpy (initiate->cn_cookie, self->cn_cookie, sizeof (initiate->cn_cookie)); | |
memcpy (initiate->cn_nonce, &self->cn_nonce, 8); | |
memcpy (initiate->box, | |
box + crypto_box_BOXZEROBYTES, sizeof (initiate->box)); | |
self->cn_nonce++; | |
return &self->msg; | |
} | |
zmq_msg_t * | |
s_process_initiate (zcurve_t *self, c_initiate_t *initiate) | |
{ | |
// Working variables for crypto calls | |
byte nonce [24]; | |
byte box [256]; | |
byte plain [256]; | |
// Decode INITIATE command | |
printf ("C:INITIATE: "); | |
// Check cookie is valid | |
// We could but don't expire cookie key after 60 seconds | |
// Cookie nonce is first 16 bytes of cookie | |
memcpy (nonce, (byte *) "Cookie--", 8); | |
memcpy (nonce + 8, initiate->cn_cookie, 16); | |
// Cookie box is next 80 bytes of cookie | |
memset (box, 0, crypto_box_BOXZEROBYTES); | |
memcpy (box + crypto_box_BOXZEROBYTES, initiate->cn_cookie + 16, 80); | |
int rc = crypto_secretbox_open (plain, box, | |
crypto_box_BOXZEROBYTES + 80, | |
nonce, self->cookie_key); | |
assert (rc == 0); | |
// Check cookie plain text is as expected [C' + s'] | |
// In practice we'd reject mismatched cookies, not assert | |
assert (memcmp (plain + crypto_box_ZEROBYTES, initiate->cn_client, 32) == 0); | |
assert (memcmp (plain + crypto_box_ZEROBYTES + 32, self->cn_secret, 32) == 0); | |
// Open Box [C + nonce + vouch](C'->S') | |
memset (box, 0, crypto_box_BOXZEROBYTES); | |
memcpy (box + crypto_box_BOXZEROBYTES, | |
initiate->box, sizeof (initiate->box)); | |
// Prepare the full nonce and decrypt | |
memcpy (nonce, (byte *) "CurveCP-client-I", 16); | |
memcpy (nonce + 16, initiate->cn_nonce, 8); | |
rc = crypto_box_open (plain, box, | |
crypto_box_BOXZEROBYTES + sizeof (initiate->box), | |
nonce, initiate->cn_client, self->cn_secret); | |
assert (rc == 0); | |
// This is where we'd check the decrypted client public key | |
byte *client_key = plain + crypto_box_ZEROBYTES; | |
// Open vouch Box [C'](C->S) and check contents | |
memset (box, 0, crypto_box_BOXZEROBYTES); | |
memcpy (box + crypto_box_BOXZEROBYTES, plain + 80, 48); | |
// Prepare the full nonce and decrypt | |
memcpy (nonce, (byte *) "CurveCPV", 8); | |
memcpy (nonce + 8, plain + 64, 16); | |
rc = crypto_box_open (plain, box, crypto_box_BOXZEROBYTES + 48, | |
nonce, client_key, self->secret_key); | |
assert (rc == 0); | |
// What we decrypted must be the short term client public key | |
assert (memcmp (plain + crypto_box_ZEROBYTES, initiate->cn_client, 32) == 0); | |
memcpy (self->cn_client, initiate->cn_client, 32); | |
// Precompute connection secret from client key | |
rc = crypto_box_beforenm (self->cn_precom, | |
self->cn_client, self->cn_secret); | |
assert (rc == 0); | |
puts ("OK"); | |
return NULL; | |
} | |
zmq_msg_t * | |
s_process_message (zcurve_t *self, cs_message_t *message) | |
{ | |
// Working variables for crypto calls | |
byte nonce [24]; | |
byte box [256]; | |
byte plain [256]; | |
// Decode MESSAGE command | |
printf ("-:MESSAGE: "); | |
// Open Box [M](S'->C') or Box [M](C'->S') | |
memset (box, 0, crypto_box_BOXZEROBYTES); | |
memcpy (box + crypto_box_BOXZEROBYTES, | |
message->box, 100 + crypto_box_BOXZEROBYTES); | |
// Prepare the full nonce and decrypt | |
char *prefix = self->is_server? "CurveCP-client-M": "CurveCP-server-M"; | |
memcpy (nonce, (byte *) prefix, 16); | |
memcpy (nonce + 16, message->cn_nonce, 8); | |
int rc = crypto_box_open_afternm ( | |
plain, box, | |
crypto_box_BOXZEROBYTES + sizeof (message->box), | |
nonce, self->cn_precom); | |
assert (rc == 0); | |
puts ("OK"); | |
// Convert to 0MQ message | |
zmq_msg_close (&self->msg); | |
zmq_msg_init_size (&self->msg, 100); | |
memcpy (zmq_msg_data (&self->msg), | |
plain + crypto_box_ZEROBYTES, 100); | |
return &self->msg; | |
} | |
// -------------------------------------------------------------------------- | |
// Accept command from peer. If the command is invalid, it is discarded | |
// silently (in this prototype, that causes an assertion failure). May | |
// return a zmq_msg_t to send to the peer, or NULL if there is nothing | |
// to send. | |
zmq_msg_t * | |
zcurve_accept (zcurve_t *self, zmq_msg_t *message) | |
{ | |
assert (self); | |
assert (message); | |
size_t size = zmq_msg_size (message); | |
byte *data = zmq_msg_data (message); | |
zmq_msg_t *response = NULL; | |
// Now process command according to current state | |
if (size == sizeof (c_hello_t) | |
&& memcmp (data, C_HELLO, 8) == 0 | |
&& self->state == expect_hello) { | |
response = s_process_hello (self, (c_hello_t *) data); | |
self->state = expect_initiate; | |
} | |
else | |
if (size == sizeof (s_cookie_t) | |
&& memcmp (data, S_COOKIE, 8) == 0 | |
&& self->state == expect_cookie) { | |
response = s_process_cookie (self, (s_cookie_t *) data); | |
self->state = connected; | |
} | |
else | |
if (size == sizeof (c_initiate_t) | |
&& memcmp (data, C_INITIATE, 8) == 0 | |
&& self->state == expect_initiate) { | |
response = s_process_initiate (self, (c_initiate_t *) data); | |
self->state = connected; | |
} | |
else | |
if (size == sizeof (cs_message_t) | |
&& memcmp (data, CS_MESSAGE, 8) == 0 | |
&& self->state == connected) { | |
response = s_process_message (self, (cs_message_t *) data); | |
} | |
else { | |
puts ("E: invalid command"); | |
assert (false); | |
} | |
return response; | |
} | |
// -------------------------------------------------------------------------- | |
// Encode message from peer. Returns a zmq_msg_t ready to send on the wire. | |
zmq_msg_t * | |
zcurve_encode (zcurve_t *self, byte *data, size_t size) | |
{ | |
assert (self); | |
assert (data); | |
assert (self->state == connected); | |
// Working variables for crypto calls | |
byte nonce [24]; | |
byte box [256]; | |
byte plain [256]; | |
// Create message Box [M](C'->S'), max M is 100 | |
memset (plain, 0, crypto_box_ZEROBYTES + 100); | |
memcpy (plain + crypto_box_ZEROBYTES, data, size); | |
// Prepare the full nonce and encrypt | |
char *prefix = self->is_server? "CurveCP-server-M": "CurveCP-client-M"; | |
memcpy (nonce, (byte *) prefix, 16); | |
memcpy (nonce + 16, &self->cn_nonce, 8); | |
int rc = crypto_box_afternm ( | |
box, plain, | |
crypto_box_ZEROBYTES + 100, | |
nonce, self->cn_precom); | |
assert (rc == 0); | |
// Prepare full command ready for sending | |
zmq_msg_close (&self->msg); | |
zmq_msg_init_size (&self->msg, sizeof (cs_message_t)); | |
cs_message_t *message = (cs_message_t *) zmq_msg_data (&self->msg); | |
memcpy (message->id, CS_MESSAGE, 8); | |
memcpy (message->cn_nonce, &self->cn_nonce, 8); | |
memcpy (message->box, box + crypto_box_BOXZEROBYTES, | |
sizeof (message->box)); | |
self->cn_nonce++; | |
return &self->msg; | |
} | |
// -------------------------------------------------------------------------- | |
// Selftest | |
int | |
zcurve_test (bool verbose) | |
{ | |
printf (" * zcurve: "); | |
// @selftest | |
zmq_msg_t *msg; | |
// Start server peer | |
zcurve_t *server = zcurve_new (); | |
msg = zcurve_start (server, NULL); | |
assert (msg == NULL); | |
// Start client peer and ping/pong through the handshake | |
zcurve_t *client = zcurve_new (); | |
msg = zcurve_start (client, zcurve_public_key (server)); | |
while (msg) { | |
msg = zcurve_accept (server, msg); | |
if (msg) | |
msg = zcurve_accept (client, msg); | |
} | |
msg = zcurve_encode (client, (byte *) "Hello", 5); | |
assert (msg); | |
// Send encoded message over the wire | |
// ... | |
// Receive encoded message from the wire | |
msg = zcurve_accept (server, msg); | |
assert (msg); | |
assert (memcmp (zmq_msg_data (msg), "Hello", 5) == 0); | |
msg = zcurve_encode (server, (byte *) "World", 5); | |
assert (msg); | |
// Send encoded message over the wire | |
// ... | |
// Receive encoded message from the wire | |
msg = zcurve_accept (client, msg); | |
assert (msg); | |
assert (memcmp (zmq_msg_data (msg), "World", 5) == 0); | |
zcurve_destroy (&server); | |
zcurve_destroy (&client); | |
// @end | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ========================================================================= | |
CurveZMQ - authentication and confidentiality for 0MQ | |
------------------------------------------------------------------------- | |
Copyright (c) 1991-2013 iMatix Corporation <www.imatix.com> | |
Copyright other contributors as noted in the AUTHORS file. | |
This is free software; you can redistribute it and/or modify it under | |
the terms of the GNU Lesser General Public License as published by | |
the Free Software Foundation; either version 3 of the License, or (at | |
your option) any later version. | |
This software is distributed in the hope that it will be useful, but | |
WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Lesser General Public License for more details. | |
You should have received a copy of the GNU Lesser General Public | |
License along with this program. If not, see | |
<http://www.gnu.org/licenses/>. | |
========================================================================= | |
*/ | |
#ifndef __ZCURVE_H_INCLUDED__ | |
#define __ZCURVE_H_INCLUDED__ | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
// Opaque class structure | |
typedef struct _zcurve_t zcurve_t; | |
// Constructor. Always generates a new public/secret key pair which | |
// you can override if you need to. | |
zcurve_t * | |
zcurve_new (void); | |
// Destructor | |
void | |
zcurve_destroy (zcurve_t **self_p); | |
// Return value of public key | |
byte * | |
zcurve_public_key (zcurve_t *self); | |
// Return value of secret key | |
byte * | |
zcurve_secret_key (zcurve_t *self); | |
// Start zcurve instance as client (if you provide a server key) or as | |
// server. May return a zmq_msg_t to send to the peer, or NULL if there | |
// is nothing to send. | |
zmq_msg_t * | |
zcurve_start (zcurve_t *self, byte *server_key); | |
// Accept command from peer. If the command is invalid, it is discarded | |
// silently (in this prototype, that causes an assertion failure). May | |
// return a zmq_msg_t to send to the peer, or NULL if there is nothing | |
// to send. | |
zmq_msg_t * | |
zcurve_accept (zcurve_t *self, zmq_msg_t *message); | |
// Encode message from peer. Returns a zmq_msg_t ready to send on the wire. | |
zmq_msg_t * | |
zcurve_encode (zcurve_t *self, byte *data, size_t size); | |
// Selftest | |
int | |
zcurve_test (bool verbose); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "czmq.h" | |
#include "zcurve.h" | |
int main (int argc, char *argv []) | |
{ | |
Bool verbose; | |
if (argc == 2 && streq (argv [1], "-v")) { | |
argc--; | |
verbose = TRUE; | |
} | |
else | |
verbose = FALSE; | |
// Do normal checks if run without arguments | |
if (argc < 2) { | |
printf ("Running self tests...\n"); | |
zcurve_test (verbose); | |
printf ("Tests passed OK\n"); | |
return 0; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment