💾 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

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

sodiumTest

Log

Files

Refs

README

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: