💾 Archived View for gmi.noulin.net › gitRepositories › sodiumTest › file › client4.c.gmi captured on 2023-01-29 at 13:28:16. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
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: