sodiumTest

Libsodium examples, client/server system
git clone https://noulin.net/git/sodiumTest.git
Log | Files | Refs | README

client4.c (6184B)


      1 #! /usr/bin/env sheepy
      2 
      3 /*
      4 client4 and server4 are following request/response model.
      5 
      6 Steps in client
      7 - load key
      8 - connect to server
      9 - generate nonce
     10 - send command, public key and nonce. Command is the first byte,
     11   0 to request server public key,
     12   1 to send first encrypted message directly
     13 - store remote public key
     14 - send encrypted message
     15 - get encrypted response
     16 
     17 Steps in server
     18 - generate keys
     19 - start event loop
     20 - store remote session public key
     21 - check identity with signature
     22 - send signature, identity public key, session public key, nonce
     23 - get encrypted message
     24 - send encrypted response
     25 
     26 This version uses secret/symetric key encryption after the key exchange.
     27 
     28 For more nonce randomness, the server can provide the first nonce with the public keys when the session opens
     29 
     30 >> when sending large amount of data, use stream functions
     31 >> use aead functions only if there are metadata
     32 >> privelege separation: have a seperate process with the secrets
     33 >> to change id: sign id public key, sign id public key and signature and the new id public key with the new id key
     34 
     35 */
     36 
     37 #include "libsheepyObject.h"
     38 
     39 #include <sys/types.h>
     40 #include <sys/socket.h>
     41 #include <netdb.h>
     42 #include <netinet/in.h>
     43 
     44 #include "sel.h"
     45 
     46 int main(int ac, char **av) {
     47 
     48   setLogMode(LOG_FUNC);
     49 
     50   if (not selInit()) ret 1;
     51 
     52   // generate keys
     53   bool isKnownServer                      = no;
     54   const char* clientSecretFilename        = "client4Secret.bin";
     55   const char* clientPublicFilename        = "client4Public.bin";
     56   bool sendClientIdToServer               = yes;
     57 
     58   // load client key if possible
     59   if (isPath(clientPublicFilename)) {
     60     logI("Client already has a session key");
     61     pError0(bLReadFile(clientSecretFilename, keys.secretKey, sizeof(keys.secretKey)));
     62     pError0(bLReadFile(clientPublicFilename, keys.publicKey, sizeof(keys.publicKey)));
     63   }
     64   else {
     65     newKeys();
     66     pError0(writeFile(clientSecretFilename, keys.secretKey, sizeof(keys.secretKey)));
     67     pError0(writeFile(clientPublicFilename, keys.publicKey, sizeof(keys.publicKey)));
     68   }
     69   newSignKeys();
     70 
     71 	char *msg = "Hello";
     72 
     73 	logI("message: %s\n", msg);
     74 
     75 
     76   // connect to server
     77   int sock;
     78   struct sockaddr_in server;
     79   struct hostent *hp;
     80   int mysock;
     81   char buf[128*1024];
     82   int rval;
     83 
     84   void connectToServer(void) {
     85     sock = socket(AF_INET, SOCK_STREAM, 0);
     86     if (sock < 0){
     87       perror("Failed to create socket");
     88     }
     89 
     90     server.sin_family = AF_INET;
     91 
     92     hp = gethostbyname(av[1]);
     93     if (hp==0) {
     94       perror("gethostbyname failed");
     95       close(sock);
     96       exit(1);
     97     }
     98 
     99     memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
    100     server.sin_port = htons(5000);
    101 
    102     if (connect(sock,(struct sockaddr *) &server, sizeof(server))){
    103       perror("connect failed");
    104       close(sock);
    105       exit(1);
    106     }
    107   }
    108   connectToServer();
    109 
    110   void snd(void *buf, size_t sz) {
    111     logVarG(sz);
    112     if(send(sock, buf, sz, 0) < 0){
    113       perror("send failed");
    114       close(sock);
    115       exit(1);
    116     }
    117   }
    118 
    119   void rcv(void *buf, size_t sz) {
    120     while (sz > 0) {
    121       rval = recv(sock, buf, sz, MSG_WAITALL);
    122       if (rval < 0) {
    123         perror("reading message");
    124         exit(1);
    125       }
    126       else if (rval == 0) {
    127         logI("Ending connection");
    128         close(sock);
    129         exit(0);
    130       }
    131       sz -= rval;
    132     }
    133     logVarG(rval);
    134   }
    135 
    136   // send public key
    137   // store remote public key
    138   void getServerPublicKey(void) {
    139 	  randombytes_buf(keys.nonce, sizeof(keys.nonce));
    140     u8 exchange[1 + sizeof(keys.publicKey) + sizeof(keys.nonce)] = init0Var;
    141     memcpy(exchange + 1, &keys.publicKey, sizeof(keys.publicKey));
    142     memcpy(exchange + 1 + sizeof(keys.publicKey), &keys.nonce, sizeof(keys.nonce));
    143     snd(exchange, sizeof(exchange));
    144 
    145     u8 serverInfo[sizeof(keys.remotePublicKey)] = init0Var;
    146     rcv(serverInfo, sizeof(serverInfo));
    147 
    148     memcpy(keys.remotePublicKey, serverInfo, sizeof(keys.remotePublicKey));
    149 
    150     logD("Remote public key");
    151     loghex(keys.remotePublicKey, sizeof(keys.remotePublicKey));
    152     put;
    153 
    154     // key exchange
    155     if (not computeSharedKeys(CLIENT_SESSION_KEYS)) {
    156       logE("Invalid server key");
    157       exit(1);
    158     }
    159   }
    160 
    161   getServerPublicKey();
    162 
    163   // send encrypted message
    164   // *nonce is incremented by after sending or receiving a message
    165   // *nonce is allowed to wrap from the max value
    166   u64 *nonce = (u64*)keys.nonce;
    167   logVarG(*nonce);
    168   int len = selEncrypt(buf, sizeof(buf), msg, strlen(msg));
    169   inc *nonce;
    170 
    171   logVarG(len);
    172 
    173   snd(&len, sizeof(len));
    174   snd(buf, len);
    175 
    176   // get encrypted response
    177   rcv(&len, sizeof(len));
    178   rcv(buf, len);
    179 
    180 	u8 decrypted[1000];
    181   logVarG(*nonce);
    182   len = selDecrypt(decrypted, sizeof(decrypted), buf, len);
    183   inc *nonce;
    184 
    185   if (!len) {
    186     logE("failed to decrypt");
    187     ret 1;
    188   }
    189 
    190   decrypted[len] = 0;
    191 
    192   logI("decrypted: %s", decrypted);
    193 
    194   close(sock);
    195 
    196 
    197   //////////////////////////////////////////
    198   // second session, server public is known
    199   {
    200   msg = "Second client session";
    201   connectToServer();
    202 
    203   // send public key
    204 	randombytes_buf(keys.nonce, sizeof(keys.nonce));
    205   u8 exchange[1 + sizeof(keys.publicKey) + sizeof(keys.nonce)] = init0Var;
    206   // command 1 send encrypted message directly
    207   exchange[0] = 1;
    208   memcpy(exchange + 1, &keys.publicKey, sizeof(keys.publicKey));
    209   memcpy(exchange + 1 + sizeof(keys.publicKey), &keys.nonce, sizeof(keys.nonce));
    210   snd(exchange, sizeof(exchange));
    211 
    212   // key exchange
    213   if (not computeSharedKeys(CLIENT_SESSION_KEYS)) {
    214     logE("Invalid server key");
    215     exit(1);
    216   }
    217 
    218   // send encrypted message
    219   // *nonce is incremented by after sending or receiving a message
    220   // *nonce is allowed to wrap from the max value
    221   u64 *nonce = (u64*)keys.nonce;
    222   logVarG(*nonce);
    223   int len = selEncrypt(buf, sizeof(buf), msg, strlen(msg));
    224   inc *nonce;
    225 
    226   logVarG(len);
    227 
    228   snd(&len, sizeof(len));
    229   snd(buf, len);
    230 
    231   // get encrypted response
    232   rcv(&len, sizeof(len));
    233   rcv(buf, len);
    234 
    235 	u8 decrypted[1000];
    236   logVarG(*nonce);
    237   len = selDecrypt(decrypted, sizeof(decrypted), buf, len);
    238   inc *nonce;
    239 
    240   if (!len) {
    241     logE("failed to decrypt");
    242     ret 1;
    243   }
    244 
    245   decrypted[len] = 0;
    246 
    247   logI("decrypted: %s", decrypted);
    248 
    249   close(sock);
    250   }
    251 
    252 }
    253 // vim: set expandtab ts=2 sw=2: