sodiumTest

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

presharedClientudp.c (3971B)


      1 #! /usr/bin/env sheepy
      2 
      3 /*
      4 client sends data to server. Client doesn't get any responses from the server
      5 The keys are preshared, there is no key exchange.
      6 
      7 The client knows: client secret key, client public key and server public key
      8 The server knows: client public key, server secret key and server public key
      9 
     10 Run this to generate the client and server keys:
     11 
     12 ./presharedClient.c generate keys
     13 
     14 The messages don't need to be signed because the client uses the client secret and
     15 the server public keys to encrypt.
     16 
     17 Steps in client
     18 - load keys
     19 - connect to server
     20 - send encrypted message
     21 
     22 Steps in server
     23 - start event loop
     24 - get encrypted message
     25 
     26 It uses public key encryption which is slow compare to secret/symetric key encryption
     27 Secret key encryption is between 25 and 50 times faster than public key encryption depending on the CPU.
     28 With secret key encryption, my computer can encode 4GB/s which is enough (I have 1GB/s network).
     29 
     30 The nonces are not verified, each nonce can be used multiple times, so replay attacks would be successful.
     31 */
     32 
     33 #include "libsheepyObject.h"
     34 
     35 #include <sys/types.h>
     36 #include <sys/socket.h>
     37 #include <netdb.h>
     38 #include <netinet/in.h>
     39 
     40 #include "sel.h"
     41 
     42 int main(int ac, char **av) {
     43 
     44   setLogMode(LOG_FUNC);
     45 
     46   if (not selInit()) ret 1;
     47 
     48   const char* clientSecretFilename = "presharedClientSecret.bin";
     49   const char* clientPublicFilename = "presharedClientPublic.bin";
     50   const char* serverSecretFilename = "presharedServerSecret.bin";
     51   const char* serverPublicFilename = "presharedServerPublic.bin";
     52   keyst clientKeys                 = init0Var;
     53   keyst serverKeys                 = init0Var;
     54 
     55   if (ac > 2) {
     56     // generate keys
     57     logI("Generate keys");
     58     newKeysBuf(&clientKeys);
     59     newKeysBuf(&serverKeys);
     60     pError0(writeFile(clientSecretFilename, clientKeys.secretKey, sizeof(clientKeys.secretKey)));
     61     pError0(writeFile(clientPublicFilename, clientKeys.publicKey, sizeof(clientKeys.publicKey)));
     62     pError0(writeFile(serverSecretFilename, serverKeys.secretKey, sizeof(serverKeys.secretKey)));
     63     pError0(writeFile(serverPublicFilename, serverKeys.publicKey, sizeof(serverKeys.publicKey)));
     64     ret 0;
     65   }
     66 
     67   // load keys
     68   pError0(bLReadFile(clientSecretFilename, clientKeys.secretKey, sizeof(clientKeys.secretKey)));
     69   pError0(bLReadFile(clientPublicFilename, clientKeys.publicKey, sizeof(clientKeys.publicKey)));
     70   pError0(bLReadFile(serverPublicFilename, clientKeys.remotePublicKey, sizeof(clientKeys.remotePublicKey)));
     71 
     72 	char *msg = "Hello";
     73 
     74 	logI("message: %s\n", msg);
     75 
     76 
     77   // connect to server
     78   int sock;
     79   struct sockaddr_in server;
     80   struct hostent *hp;
     81   typ struct PACKED {
     82     u64 time;
     83     char buf[64*1024];
     84   } payloadt;
     85   typ struct PACKED {
     86     u8 nonce[crypto_box_NONCEBYTES];
     87     i32 len;
     88     payloadt payload;
     89   } packett;
     90   packett data = init0Var;
     91   int rval;
     92 
     93   sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     94   if (sock < 0){
     95     perror("Failed to create socket");
     96   }
     97 
     98   server.sin_family = AF_INET;
     99 
    100   hp = gethostbyname(av[1]);
    101   if (hp==0) {
    102     perror("gethostbyname failed");
    103     close(sock);
    104     exit(1);
    105   }
    106 
    107   memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
    108   server.sin_port = htons(5000);
    109 
    110   // send encrypted message with nonce
    111 	randombytes_buf(clientKeys.nonce, sizeof(clientKeys.nonce));
    112   memcpy(data.nonce, clientKeys.nonce, sizeof(clientKeys.nonce));
    113   payloadt payload;
    114   // set timestamp in encrypted message to avoid replay attacks
    115   payload.time = getCurrentUnixTime() /*- 2 */; // uncomment to introduce an error
    116   memcpy(payload.buf, msg, strlen(msg));
    117   data.len = selPublicEncrypt((u8*)&data.payload, sizeof(data.payload), (u8*)&payload, sizeof(payload.time) + strlen(msg), &clientKeys);
    118 
    119   logVarG(data.len);
    120 
    121   if (sendto(sock, &data, data.len + sizeof(data.len) + sizeof(data.nonce), 0, (const struct sockaddr *)&server, sizeof(server)) < 0) {
    122     perror("send failed");
    123     close(sock);
    124     exit(1);
    125   }
    126 
    127   close(sock);
    128 }
    129 // vim: set expandtab ts=2 sw=2: