💾 Archived View for gmi.noulin.net › gitRepositories › sodiumTest › file › sodiumTest.c.gmi captured on 2024-08-31 at 13:31:32. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
sodiumTest.c (12173B)
1 #! /usr/bin/env sheepy 2 /* or direct path to sheepy: #! /usr/local/bin/sheepy */ 3 4 /* Libsheepy documentation: https://spartatek.se/libsheepy/ */ 5 #include "libsheepyObject.h" 6 #include "sodium.h" 7 8 // detect entropy quality 9 #include <fcntl.h> 10 #include <unistd.h> 11 #include <sys/ioctl.h> 12 #include <linux/random.h> 13 14 int urandomfd; 15 16 /* void randombytes(u8 *buffer, size_t size) { */ 17 /* read(urandomfd, buffer, size); */ 18 /* } */ 19 20 typ struct { 21 u8 publicKey[crypto_box_PUBLICKEYBYTES]; 22 u8 secretKey[crypto_box_SECRETKEYBYTES]; 23 } keyst; 24 25 void newKeys(keyst *keys) { 26 crypto_box_keypair(keys->publicKey, keys->secretKey); 27 } 28 29 typ struct { 30 u8 publicKey[crypto_sign_PUBLICKEYBYTES]; 31 u8 secretKey[crypto_sign_SECRETKEYBYTES]; 32 } signKeyst; 33 34 void newSignKeys(signKeyst *keys) { 35 crypto_sign_keypair(keys->publicKey, keys->secretKey); 36 } 37 38 /* int isZero( const u8 *data, int len ) { */ 39 /* int r = 0; */ 40 /* */ 41 /* range(i, len) { */ 42 /* r |= data[i]; */ 43 /* } */ 44 /* */ 45 /* return r; */ 46 /* } */ 47 48 #define MAX_MSG_SIZE 1400 49 50 /* int encrypts(u8 *encrypted, const u8 *pk, const u8 *sk, const u8 *nonce, const u8 *plain, size_t length) { */ 51 /* u8 temp_plain[MAX_MSG_SIZE]; */ 52 /* u8 temp_encrypted[MAX_MSG_SIZE]; */ 53 /* int rc; */ 54 /* */ 55 /* logD("encrypt %zu", length); */ 56 /* */ 57 /* if(length+crypto_box_ZEROBYTES >= MAX_MSG_SIZE) { */ 58 /* return -2; */ 59 /* } */ 60 /* */ 61 /* memset(temp_plain, 0, crypto_box_ZEROBYTES); */ 62 /* memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); */ 63 /* */ 64 /* rc = crypto_box(temp_encrypted, temp_plain, crypto_box_ZEROBYTES + length, nonce, pk, sk); */ 65 /* */ 66 /* if( rc != 0 ) { */ 67 /* return -1; */ 68 /* } */ 69 /* */ 70 /* if( isZero(temp_plain, crypto_box_BOXZEROBYTES) != 0 ) { */ 71 /* return -3; */ 72 /* } */ 73 /* */ 74 /* memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, crypto_box_ZEROBYTES + length); */ 75 /* */ 76 /* return crypto_box_ZEROBYTES + length - crypto_box_BOXZEROBYTES; */ 77 /* } */ 78 /* */ 79 /* int decrypts(u8 plain[], const u8 pk[], const u8 sk[], const u8 nonce[], const u8 encrypted[], int length) { */ 80 /* u8 temp_encrypted[MAX_MSG_SIZE]; */ 81 /* u8 temp_plain[MAX_MSG_SIZE]; */ 82 /* int rc; */ 83 /* */ 84 /* logD("decrypt\n"); */ 85 /* */ 86 /* if(length+crypto_box_BOXZEROBYTES >= MAX_MSG_SIZE) { */ 87 /* return -2; */ 88 /* } */ 89 /* */ 90 /* memset(temp_encrypted, '\0', crypto_box_BOXZEROBYTES); */ 91 /* memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); */ 92 /* */ 93 /* rc = crypto_box_open(temp_plain, temp_encrypted, crypto_box_BOXZEROBYTES + length, nonce, pk, sk); */ 94 /* */ 95 /* if( rc != 0 ) { */ 96 /* return -1; */ 97 /* } */ 98 /* */ 99 /* if( isZero(temp_plain, crypto_box_ZEROBYTES) != 0 ) { */ 100 /* return -3; */ 101 /* } */ 102 /* */ 103 /* memcpy(plain, temp_plain + crypto_box_ZEROBYTES, crypto_box_BOXZEROBYTES + length); */ 104 /* */ 105 /* return crypto_box_BOXZEROBYTES + length - crypto_box_ZEROBYTES; */ 106 /* } */ 107 108 // return ciphertext (encrypted message) length 109 int selPublicEncrypt(u8 *ciphertext/*result*/, size_t csize, const u8 *msg, size_t mlen, const u8 *nonce, const u8 *publicKey, const u8 *secretKey) { 110 // csize is ciphertext buffer size 111 // check is there is enough space in ciphertext 112 if (csize < mlen + crypto_box_MACBYTES) ret 0; 113 if (crypto_box_easy(ciphertext, msg, mlen, nonce, publicKey, secretKey) != 0) ret 0; 114 ret mlen + crypto_box_MACBYTES; 115 } 116 117 // return message length 118 int selPublicDecrypt(u8 *msg/*result*/, size_t msize, const u8 *ciphertext, size_t clen, const u8 *nonce, const u8 *publicKey, const u8 *secretKey) { 119 // msize is message buffer size 120 // check ciphertext has minimal length, the message has to be at least one byte 121 // check is there is enough space in message buffer 122 if (clen <= crypto_box_MACBYTES or msize < clen - crypto_box_MACBYTES) ret 0; 123 if (crypto_box_open_easy(msg, ciphertext, clen, nonce, publicKey, secretKey) != 0) ret 0; 124 ret clen - crypto_box_MACBYTES; 125 } 126 127 int main(int ARGC, char** ARGV) { 128 129 initLibsheepy(ARGV[0]); 130 setLogMode(LOG_VERBOSE); 131 132 // detect entropy quality 133 if ((urandomfd = open("/dev/urandom", O_RDONLY)) != -1) { 134 int c; 135 if (ioctl(urandomfd, RNDGETENTCNT, &c) == 0 && c < 160) { 136 logN("This system doesn't provide enough entropy to quickly generate high-quality random numbers.\n" 137 "Installing the rng-utils/rng-tools, jitterentropy or haveged packages may help.\n" 138 "On virtualized Linux environments, also consider using virtio-rng.\n" 139 "The service will not start until enough entropy has been collected.\n", stderr); 140 } 141 close(urandomfd); 142 } 143 if (sodium_init() == -1) { 144 logC("Panic! libsodium couldn't be initialized; it is not safe to use"); 145 ret 1; 146 } 147 148 149 /////////////////////////////////////////////////////////////////////////////////////////////// 150 // public key crypto 151 keyst alice, bob; 152 153 newKeys(&alice); 154 newKeys(&bob); 155 156 u8 nonce[crypto_box_NONCEBYTES]; 157 randombytes_buf(nonce, sizeof(nonce)); 158 159 char *msg = "12345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568123456812345681234568"; 160 161 logI("message: %s\n", msg); 162 163 int elen; 164 /* u8 encrypted[1000]; */ 165 /* //elen = encrypts(encrypted, bob.publicKey, alice.secretKey, nonce, msg, strlen(msg)); */ 166 /* elen = crypto_box_easy(encrypted, msg, strlen(msg), nonce, bob.publicKey, alice.secretKey); */ 167 /* if (elen < 0) { */ 168 /* logE("failed to encrypt"); */ 169 /* ret 1; */ 170 /* } */ 171 /* elen = crypto_box_MACBYTES + strlen(msg); */ 172 /* */ 173 /* uint8_t decrypted[1000]; */ 174 /* int r; */ 175 /* //r = decrypts(decrypted, alice.publicKey, bob.secretKey, nonce, encrypted, elen); */ 176 /* r = crypto_box_open_easy(decrypted, encrypted, elen, nonce, alice.publicKey, bob.secretKey); */ 177 /* if (r < 0) { */ 178 /* logE("failed to decrypt"); */ 179 /* ret 1; */ 180 /* } */ 181 /* r = elen - crypto_box_MACBYTES; */ 182 /* */ 183 /* decrypted[r] = '\0'; */ 184 /* logI("decrypted: %s", decrypted); */ 185 close(urandomfd); 186 187 u8 encrypted[1000]; 188 u8 decrypted[1000]; 189 int r; 190 stopwatchStart; 191 loop(1000) { 192 r = selPublicEncrypt(encrypted, sizeof(encrypted), msg, strlen(msg), nonce, bob.publicKey, alice.secretKey); 193 if (!r) { 194 logE("failed to encrypt"); 195 ret 1; 196 } 197 } 198 stopwatchLogMs; 199 200 r = selPublicDecrypt(decrypted, sizeof(decrypted), encrypted, r, nonce, alice.publicKey, bob.secretKey); 201 if (!r) { 202 logE("failed to decrypt"); 203 ret 1; 204 } 205 decrypted[r] = '\0'; 206 logI("decrypted: %s", decrypted); 207 208 209 ////////////////////////////////////////////////////////////////////////////////////////////// 210 // public key signature 211 212 signKeyst rob; 213 newSignKeys(&rob); 214 215 216 char *m = "bonjour"; 217 218 logD("crypto_sign_BYTES %d", crypto_sign_BYTES); 219 220 u8 signed_message[crypto_sign_BYTES + 2000] = init0Var; 221 unsigned long long signed_message_len = 0; 222 223 logVarG(msg); 224 225 logVarG(crypto_sign(signed_message, &signed_message_len, m, strlen(m), rob.secretKey)); 226 227 logVarG(crypto_sign_BYTES); 228 logVarG((u64)signed_message_len); 229 230 loghex(signed_message, sizeof signed_message); 231 put 232 233 logD("%s", signed_message); 234 235 u8 unsigned_message[2000] = init0Var; 236 unsigned long long unsigned_message_len; 237 if (crypto_sign_open(unsigned_message, &unsigned_message_len, signed_message, signed_message_len, rob.publicKey) != 0) { 238 logE("incorrect signature!"); 239 } 240 else { 241 logP("Correct signature"); 242 } 243 244 ////////////////////////////////////////////////////////////////////////////////////////////// 245 // one shot encryption with secret key 246 u8 k1[crypto_secretbox_KEYBYTES]; 247 248 crypto_secretbox_keygen(k1); 249 250 // TODO generate nonce 251 252 stopwatchStart; 253 loop(1000) { 254 elen = crypto_secretbox_easy(encrypted, msg, strlen(msg), nonce, k1); 255 if (elen < 0) { 256 logE("failed to encrypt"); 257 ret 1; 258 } 259 elen = crypto_secretbox_MACBYTES + strlen(msg); 260 } 261 stopwatchLogMs; 262 263 r = crypto_secretbox_open_easy(decrypted, encrypted, elen, nonce, k1); 264 if (r < 0) { 265 logE("failed to decrypt"); 266 return 1; 267 } 268 r = elen - crypto_secretbox_MACBYTES; 269 270 decrypted[r] = '\0'; 271 logI("decrypted: %s", decrypted); 272 273 274 ////////////////////////////////////////////////////////////////////////////////////////////// 275 // password hash key derivation and one shot encryption 276 // https://doc.libsodium.org/password_hashing/default_phf 277 // Keep in mind that to produce the same key from the same password, 278 // the same algorithm, the same salt, and the same values for opslimit 279 // and memlimit must be used. Therefore, these parameters must be stored for each user. 280 281 logD("crypto_pwhash_PASSWD_MIN %"PRIu64,crypto_pwhash_PASSWD_MIN); 282 logD("crypto_pwhash_PASSWD_MAX %"PRIu64,crypto_pwhash_PASSWD_MAX); 283 logD("crypto_pwhash_BYTES_MIN %"PRIu64,crypto_pwhash_BYTES_MIN); 284 logD("crypto_pwhash_BYTES_MAX %"PRIu64,crypto_pwhash_BYTES_MAX); 285 logD("crypto_pwhash_OPSLIMIT_MIN %"PRIu64,crypto_pwhash_OPSLIMIT_MIN); 286 logD("crypto_pwhash_OPSLIMIT_MAX %"PRIu64,crypto_pwhash_OPSLIMIT_MAX); 287 logD("crypto_pwhash_MEMLIMIT_MIN %"PRIu64,crypto_pwhash_MEMLIMIT_MIN); 288 logD("crypto_pwhash_MEMLIMIT_MAX %"PRIu64,crypto_pwhash_MEMLIMIT_MAX); 289 290 #define PASSWORDp "Correct Horse Battery Staple" 291 292 unsigned char saltp[crypto_pwhash_SALTBYTES] = init0Var; // save the salt 293 unsigned char keyp[crypto_secretbox_KEYBYTES] = init0Var; 294 295 randombytes_buf(saltp, sizeof saltp); 296 297 stopwatchStart; 298 if (crypto_pwhash 299 (keyp, sizeof keyp, PASSWORDp, strlen(PASSWORDp), saltp, 300 crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, 301 crypto_pwhash_ALG_DEFAULT) != 0) { 302 logE("out of memory"); 303 } 304 stopwatchLogMs; 305 306 loghex(keyp, sizeof keyp);put; 307 308 logD("encrypt/decrypt data with the generated key from password"); 309 310 elen = crypto_secretbox_easy(encrypted, msg, strlen(msg), nonce, keyp); 311 if (elen < 0) { 312 logE("failed to encrypt"); 313 ret 1; 314 } 315 elen = crypto_secretbox_MACBYTES + strlen(msg); 316 317 logD("elen %d %d", elen, crypto_secretbox_MACBYTES); 318 319 r = crypto_secretbox_open_easy(decrypted, encrypted, elen, nonce, keyp); 320 if (r < 0) { 321 logE("failed to decrypt"); 322 return 1; 323 } 324 r = elen - crypto_secretbox_MACBYTES; 325 326 decrypted[r] = '\0'; 327 logI("decrypted: %s", decrypted); 328 329 ////////////////////////////////////////////////////////////////////////////////////////////// 330 // password hash password storage 331 332 // key derivation 333 #define PASSWORD "Correct Horse Battery Staple" 334 #define KEY_LEN crypto_box_SEEDBYTES 335 u8 salt[crypto_pwhash_SALTBYTES]; 336 u8 key[KEY_LEN]; 337 338 logVarG(KEY_LEN); 339 logVarG(crypto_secretstream_xchacha20poly1305_KEYBYTES); 340 341 randombytes_buf(salt, sizeof salt); 342 343 if (crypto_pwhash( 344 key, sizeof key, PASSWORD, strlen(PASSWORD), salt, 345 crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, 346 crypto_pwhash_ALG_DEFAULT) != 0) { 347 logE("out of memory"); 348 } 349 350 // password hashing 351 #define PASSWORD2 "Correct Horse Battery Staple" 352 char hashed_PASSWORD2[crypto_pwhash_STRBYTES]; 353 354 logI("Hashing password"); 355 if (crypto_pwhash_str 356 (hashed_PASSWORD2, PASSWORD2, strlen(PASSWORD2), 357 crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE) != 0) { 358 logE("out of memory"); 359 } 360 361 logI("Verifying password"); 362 //#define PASSWORD3 "Correct Horse Battery Stapl" 363 #define PASSWORD3 PASSWORD2 364 if (crypto_pwhash_str_verify 365 (hashed_PASSWORD2, PASSWORD3, strlen(PASSWORD3)) != 0) { 366 logE("wrong password"); 367 } 368 else { 369 logP("Password ok"); 370 } 371 ret 0; 372 } 373 // vim: set expandtab ts=2 sw=2: