tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

index.rst (7164B)


      1 .. _mozilla_projects_nss_nss_sample_code_sample1:
      2 
      3 sample1
      4 =======
      5 
      6 .. container::
      7 
      8   1. A program to compute the hash of a file and save it to another file.
      9 
     10   .. code:: c
     11 
     12       /* NSPR Headers */
     13       #include <prprf.h>
     14       #include <prtypes.h>
     15       #include <plgetopt.h>
     16       #include <prio.h>
     17       #include <prprf.h>
     18 
     19       /* NSS headers */
     20       #include <secoid.h>
     21       #include <secmodt.h>
     22       #include <sechash.h>
     23 
     24       typedef struct {
     25           const char *hashName;
     26           SECOidTag oid;
     27       } NameTagPair;
     28 
     29       /* The hash algorithms supported */
     30       static const NameTagPair HASH_NAMES[] = {
     31           { "MD2", SEC_OID_MD2 },
     32           { "MD5", SEC_OID_MD5 },
     33           { "SHA1", SEC_OID_SHA1 },
     34           { "SHA256", SEC_OID_SHA256 },
     35           { "SHA384", SEC_OID_SHA384 },
     36           { "SHA512", SEC_OID_SHA512 }
     37       };
     38 
     39       /* Maps a hash name to a SECOidTag.
     40        * Returns NULL if the name is not a supported algorithm
     41        */
     42       static SECOidTag HashNameToOIDTag(const char *hashName)
     43       {
     44           int i, nhashes = sizeof(HASH_NAMES);
     45           SECOidTag hashtag = SEC_OID_UNKNOWN;
     46 
     47           for (i = 0; i < nhashes; i++) {
     48               if (PORT_Strcasecmp(hashName, HASH_NAMES[i].hashName) == 0) {
     49                   hashtag = HASH_NAMES[i].oid;
     50                   break;
     51               }
     52           }
     53           return hashtag;
     54       }
     55 
     56       /*  Newline  */
     57       static void Newline(PRFileDesc* out)
     58       {
     59           PR_fprintf(out, "\n");
     60       }
     61 
     62       /*  PrintAsHex  */
     63       void PrintAsHex(PRFileDesc* out, unsigned char *data, unsigned int len)
     64       {
     65           unsigned i;
     66           int column;
     67           unsigned int limit = 15;
     68           unsigned int level = 1;
     69 
     70           column = level;
     71           if (!len) {
     72               PR_fprintf(out, "(empty)\n");
     73               return;
     74           }
     75 
     76           for (i = 0; i < len; i++) {
     77               if (i != len - 1) {
     78                   PR_fprintf(out, "%02x:", data[i]);
     79                   column += 3;
     80               } else {
     81                   PR_fprintf(out, "%02x", data[i]);
     82                   column += 2;
     83                   break;
     84               }
     85               if (column > 76 || (i % 16 == limit)) {
     86                   Newline(out);
     87                   column = level;
     88                   limit = i % 16;
     89               }
     90           }
     91           if (column != level) {
     92               Newline(out);
     93           }
     94       }
     95 
     96 
     97       /*  Prints a usage message and exits  */
     98       static void Usage(const char *progName)
     99       {
    100           int htype;
    101           int HASH_AlgTOTAL = sizeof(HASH_NAMES) / sizeof(HASH_NAMES[0]);
    102 
    103           fprintf(stderr, "Usage:  %s -t type [ < input ] [ > output ]\n", progName);
    104           fprintf(stderr, "%-20s Specify the digest method (must be one of\n",
    105                   "-t type");
    106           fprintf(stderr, "%-20s ", "");
    107           for (htype = 0; htype < HASH_AlgTOTAL; htype++) {
    108               fprintf(stderr, HASH_NAMES[htype].hashName);
    109               if (htype == (HASH_AlgTOTAL - 2))
    110                   fprintf(stderr, " or ");
    111               else if (htype != (HASH_AlgTOTAL - 1))
    112                   fprintf(stderr, ", ");
    113           }
    114           fprintf(stderr, " (case ignored))\n");
    115           fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
    116                   "< input");
    117           fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
    118                   "> output");
    119           exit(-1);
    120       }
    121 
    122       /*  Check for the missing arguments  */
    123       static void
    124       PrintMsgAndExit(const char *progName, char opt)
    125       {
    126           fprintf(stderr, "%s: option -%c requires an argument\n", progName, opt);
    127           Usage(progName);
    128       }
    129 
    130       #define REQUIRE_ARG(opt,value) if (!(value)) PrintMsgAndExit(progName, opt)
    131 
    132       /* Digests a file according to the specified algorithm.
    133        * It writes out the digest as a hexadecimal string.
    134        */
    135       static int
    136       DigestFile(PRFileDesc *outFile, PRFileDesc *inFile, SECOidTag hashOIDTag)
    137       {
    138           unsigned int  nb;
    139           unsigned char ibuf[4096];
    140           unsigned char digest[64];
    141           unsigned int  len;
    142           unsigned int  digestLen;
    143           HASH_HashType hashType;
    144           HASHContext   *hashContext = NULL;
    145 
    146           hashType    = HASH_GetHashTypeByOidTag(hashOIDTag);
    147           hashContext = HASH_Create(hashType);
    148           if (hashContext == NULL) {
    149               return SECFailure;
    150           }
    151 
    152           do {
    153               HASH_Begin(hashContext);
    154 
    155               /* Incrementally hash the file contents */
    156               while ((nb = PR_Read(inFile, ibuf, sizeof(ibuf))) > 0) {
    157                   HASH_Update(hashContext, ibuf, nb);
    158               }
    159 
    160               HASH_End(hashContext, digest, &len, 64);
    161 
    162               /*  Normally we would write it out in binary with
    163                *  nb = PR_Write(outFile, digest, len);
    164                *  but for illustration let's print it in hex.
    165                */
    166               PrintAsHex(outFile, digest, len);
    167 
    168           } while (0);
    169 
    170           /* cleanup */
    171           if (hashContext != NULL)
    172               HASH_Destroy(hashContext);
    173 
    174           return SECSuccess;
    175       }
    176 
    177       /*
    178        * This sample computes the hash of a file and saves it to another file. It illustrates the use of NSS message APIs.
    179        */
    180       int main(int argc, char **argv)
    181       {
    182           SECOidTag     hashOIDTag;
    183           PLOptState    *optstate;
    184           PLOptStatus   status;
    185           SECStatus  rv;
    186           char *hashName  = NULL;
    187           char  *progName = strrchr(argv[0], '/');
    188 
    189           progName = progName ? progName + 1 : argv[0];
    190 
    191           rv = NSS_NoDB_Init("/tmp");
    192           if (rv != SECSuccess) {
    193               fprintf(stderr, "%s: NSS_Init failed in directory %s\n", progName, "/tmp");
    194               return -1;
    195           }
    196 
    197           /* Parse command line arguments */
    198           optstate = PL_CreateOptState(argc, argv, "t:");
    199           while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
    200               switch (optstate->option) {
    201               case 't':
    202                   REQUIRE_ARG(optstate->option, optstate->value);
    203                   hashName = strdup(optstate->value);
    204                   break;
    205               }
    206           }
    207 
    208           if (!hashName)
    209               Usage(progName);
    210 
    211           /* convert and validate */
    212           hashOIDTag = HashNameToOIDTag(hashName);
    213           if (hashOIDTag == SEC_OID_UNKNOWN) {
    214               fprintf(stderr, "%s: invalid digest type - %s\n", progName, hashName);
    215               Usage(progName);
    216           }
    217 
    218           /* Digest it and print the result */
    219           rv = DigestFile(PR_STDOUT, PR_STDIN, hashOIDTag);
    220           if (rv != SECSuccess) {
    221               fprintf(stderr, "%s: problem digesting data (%d)\n", progName, PORT_GetError());
    222           }
    223 
    224           rv = NSS_Shutdown();
    225           if (rv != SECSuccess) {
    226               exit(-1);
    227           }
    228 
    229           return 0;
    230       }