RFC 3797

Publicly Verifiable Nominations Committee (NomCom) Random Selection

๐Ÿ“… published June 2004, from ietf

Publicly Verifiable Nominations Committee (NomCom) Random Selection โœจ

Okay bestie, here's the header situation ๐ŸŽ€ This is RFC 3797, written by D. Eastlake 3rd at Motorola Laboratories and dated June 2004. It's Informational ๐ŸŒธ, which means it gives info to the Internet community and doesn't set a standard. It also obsoletes RFC 2777 ๐Ÿ’…, so this one replaces that older doc. The group is the Network Working Group ๐Ÿฆ‹


Status of This Memo

This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited. ๐Ÿ’–

Copyright (C) The Internet Society (2004). โœจ

Abstract

Okay so this doc describes a way to make random picks where anyone can check that the choice was fair ๐Ÿ”ฅ The example they use is picking the voting members of the IETF Nominations Committee (NomCom) from the pool of eligible volunteers. Other cases could use similar techniques too ๐Ÿซถ

Table of Contents

   1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . .  2
   2. General Flow of a Publicly Verifiable Process . . . . . . . . .  2
      2.1.  Determination of the Pool . . . . . . . . . . . . . . . .  2
      2.2.  Publication of the Algorithm. . . . . . . . . . . . . . .  3
      2.3.  Publication of Selection. . . . . . . . . . . . . . . . .  3
   3. Randomness. . . . . . . . . . . . . . . . . . . . . . . . . . .  3
      3.1.  Sources of Randomness . . . . . . . . . . . . . . . . . .  3
      3.2.  Skew. . . . . . . . . . . . . . . . . . . . . . . . . . .  4
      3.3.  Entropy Needed. . . . . . . . . . . . . . . . . . . . . .  4
   4. A Suggested Precise Algorithm . . . . . . . . . . . . . . . . .  5
   5. Handling Real World Problems. . . . . . . . . . . . . . . . . .  7
      5.1.  Uncertainty as to the Pool. . . . . . . . . . . . . . . .  7
      5.2.  Randomness Ambiguities. . . . . . . . . . . . . . . . . .  7
   6. Fully Worked Example. . . . . . . . . . . . . . . . . . . . . .  8
   7. Security Considerations . . . . . . . . . . . . . . . . . . . .  9
   8. Reference Code. . . . . . . . . . . . . . . . . . . . . . . . . 10
   Appendix A: History of NomCom Member Selection . . . . . . . . . . 16
   Appendix B: Changes from RFC 2777. . . . . . . . . . . . . . . . . 16
   Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . 17
   References . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
      Normative References. . . . . . . . . . . . . . . . . . . . . . 17
      Informative References. . . . . . . . . . . . . . . . . . . . . 17
   Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 18
   Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 19

1. Introduction ๐ŸŒˆ

Under the IETF rules, every year ten people get randomly picked from the eligible volunteers to be the voting members of the IETF nominations committee (NomCom) ๐ŸŽฒ The NomCom nominates members of the Internet Engineering Steering Group (IESG) and the Internet Architecture Board (IAB), as described in [RFC 3777]. Lately there have been around 100 eligible volunteers.

It's highly desirable that this random pick is done in a way nobody can dispute, so no reasonable charges of bias or favoritism can be made ๐Ÿ‘‘ This protects the selection administrator (currently the appointed non-voting NomCom chair) from suspicion of bias, and it protects the IETF too. It's giving fairness ๐Ÿ’…

A method where public information lets any person verify the randomness meets this goal โœจ This document gives an example of one.

The method, as it appears in RFC 2777, was also used by IANA in February 2003 to pick the ACE prefix for Internationalized Domain Names [RFC 3490], so that claim jumping was avoided ๐Ÿฆ‹

2. General Flow of a Publicly Verifiable Process ๐ŸŽ€

A selection of NomCom members that is publicly verifiable as unbiased, or something similar, could follow the three steps below ๐Ÿซถ

2.1. Determination of the Pool

First, determine the pool to select from, as provided in [RFC 3777] or its successor.

The selection administrator solicits volunteers. Their names then go through the IETF Secretariat to check eligibility. (Current eligibility criteria relate to IETF meeting attendance, and the Secretariat maintains those records ๐Ÿ“‹) The full list of eligible volunteers is made public early enough that a reasonable amount of time can be given to resolve any disputes about who should be in the pool.

2.2. Publication of the Algorithm

The exact algorithm to be used is made public, including the future sources of randomness ๐Ÿ”ฎ For example, the members of the final list of eligible volunteers are ordered by publicly numbering them. Some public future sources of randomness, such as government run lotteries, are specified. Then an exact algorithm is specified, where eligible volunteers are selected based on a strong hash function [RFC 1750] of those future sources of randomness ๐Ÿงš

2.3. Publication of Selection

When the pre-specified sources of randomness produce their output, those values should be announced, along with a summary of how the selection algorithm was executed. That way anyone can verify that the correct randomness source values were used and that the algorithm was run properly ๐Ÿ” The algorithm can select a larger number, in an ordered way, than is actually needed. If any of the selected people need to be passed over or replaced for any reason, there's an ordered set of extra alternate selections ready to go ๐Ÿ“ A cut off time for any complaint that the algorithm was run with the wrong inputs or not faithfully executed must be specified, to finalize the output and provide a stable selection โฐ

3. Randomness ๐ŸŽฒ

The whole point of the unbiased nature of the selection is that it's based, in an exact and predetermined way, on random information that will be revealed in the future ๐Ÿ˜ญ That means nobody specifying the algorithm can know it ahead of time. That random information is what controls the selection. The random information must be publicly and unambiguously revealed in a timely fashion โญ

The random sources must not include anything that any reasonable person would believe to be under the control or influence of the IETF or its components. Examples of that would be IETF meeting attendance statistics, numbers of documents issued, or things like that ๐Ÿ™ˆ

3.1. Sources of Randomness

Good information to use includes the winning lottery numbers for specified runnings of specified public lotteries ๐ŸŽฐ Particularly for government run lotteries, great care is taken to make sure they happen on time and produce random quantities. Even in the unlikely case one were rigged, it would almost certainly be in connection with winning money in the lottery, not in connection with IETF use ๐Ÿ’ฐ

Other options include things like the daily balance in the US Treasury on a specified day, or the volume of trading on the New York Stock exchange on a specified day, etc. (However, the reference code given below will not handle integers that are too large.) Sporting events can also be used. (Experience has shown that stock prices and/or volumes are a poor source of unambiguous data, due to trading suspensions, company mergers, delistings, splits, multiple markets, etc. ๐Ÿ“‰) In all cases, great care must be taken to specify exactly what quantities are presumed random, and what will be done if their issuance is cancelled, delayed, or advanced ๐Ÿšฆ

It's important that the last source of randomness, chronologically, produces a substantial amount of the entropy needed. If most of the randomness comes from the earlier sources, and someone has even limited influence over the final source, they might do an exhaustive analysis and exert that influence to bias the selection in the direction they wanted. ๐Ÿ˜ค So it's best for the last source to be an especially strong and unbiased source of a large amount of randomness, such as a government run lottery.

It's best not to use too many different sources. Every additional source increases the probability that one or more sources might be delayed, cancelled, or just plain screwed up somehow. That calls contingency provisions into play or, worst of all, creates a situation that was not anticipated ๐Ÿ’€ This would either require arbitrary judgment by the selection administrator, defeating the randomness of the selection, or a re-run with a new set of sources, causing a lot of delay. Three or four would be a good number of sources. Ten is too many ๐Ÿ™…โ€โ™€๏ธ

3.2. Skew

Some sources of randomness produce data that isn't uniformly distributed. This is certainly true of volumes, prices, and horse race results, for example ๐Ÿ‡ However, use of a strong mixing function [RFC 1750] will extract the available entropy and produce a hash value whose bits, remainder modulo a small divisor, etc., deviate from a uniform distribution only by an insignificant amount ๐Ÿ’œ

3.3. Entropy Needed

What we're doing is selecting N items without replacement from a population of P items ๐Ÿงฎ The number of different ways to do this is as follows, where "!" represents the factorial function:

                            P!
                       -------------
                       N! * (P - N)!

To do this in a completely random fashion, you need as many random bits as the logarithm base 2 of that quantity ๐Ÿค“ Here are some sample calculated approximate numbers of random bits for the completely random selection of 10 NomCom members from various pool sizes:

               Random Selection of Ten Items From Pool

     Pool size     20   25   30   35   40   50   60   75  100  120
     Bits needed   18   22   25   28   30   34   37   40   44   47

Using an inadequate number of bits means that not all of the possible sets of ten selected items would be available ๐Ÿ™€ For a substantially inadequate amount of entropy, there could be a significant correlation between the selection of two different members of the pool, for example. However, as a practical matter, for pool sizes likely to come up in IETF NomCom membership selection, 40 bits of entropy should always be adequate. Even if there's a large pool and more bits are needed for perfect randomness, 40 bits of entropy will assure only an insignificant deviation from completely random selection. That covers the difference in probability of selection for different pool members, the correlation between the selection of any pair of pool members, and so on ๐ŸŒธ

An MD5 [RFC 1321] hash has 128 bits, so it can produce no more than that many bits of entropy. However, that's more than three times what's likely to ever be needed for IETF NomCom membership selection ๐Ÿฐ An even stronger hash, such as SHA-1 [RFC 3174], can be used if desired ๐Ÿ”

4. A Suggested Precise Algorithm โœจ

okay bestie, this part is the actual recipe ๐Ÿ“ and it has to be precise, because if two people run it on the same inputs they need to get the exact same answer. the sources we talked about give you either one positive number (like NY Stock Exchange volume in thousands of shares) or a small set of positive numbers (lotteries usually give 6 numbers from 1 through 40 or so, a sporting event could give you the scores of two teams, etc.). here's the suggested precise algorithm ๐Ÿ’…

  1. For each source producing multiple numeric values, represent each as a decimal number terminated by a period (or with a period separating the whole from the fractional part), without leading zeroes (except for a single leading zero if the integer part is zero), and without trailing zeroes after the period.
  2. Order the values from each source from smallest to the largest and concatenate them and suffix the result with a "/". For each source producing a single number, simply represent it as above with a suffix "/". (This sorting is necessary because the same lottery results, for example, are sometimes reported in the order numbers were drawn and sometimes in numeric order, and such things as the scores of two sports teams that play a game has no inherent order. ๐Ÿ€)
  3. At this point you have a string for each source, say s1/, s2/, ... Concatenate these strings in a pre-specified order, the order in which the sources were listed if not otherwise specified, and represent each character as its ASCII code [ASCII] producing "s1/s2/.../".

okay so then you make a whole sequence of random values from that string by doing a strong mixing of the sources ๐ŸŒ€. you calculate the MD5 hash [RFC 1321] of this string prefixed and suffixed with an all zeros two byte sequence for the first value, the string prefixed and suffixed by 0x0001 for the second value, etc., treating the two bytes as a big endian counter. treat each of these derived "random" MD5 output values as a positive 128-bit multiprecision big endian integer. the vibe is very "every value gets its own little wrapper" ๐ŸŽ€

then you totally order the pool of listed volunteers. if there are P volunteers, you select the first by dividing the first derived random value by P and using the remainder plus one as the position of the selectee in the published list. you select the second by dividing the second derived random value by P-1 and using the remainder plus one as the position in the list with the first selected person eliminated. etc. ๐Ÿฆ‹

Heads up, babe: It is STRONGLY recommended that alphanumeric random sources be avoided due to the much greater difficulty in canonicalizing them in an independently repeatable fashion. however, if you choose to ignore this advice and use an ASCII or similar Roman alphabet source or sources, all white space, punctuation, accents, and special characters should be removed and all letters set to upper case. this will leave only an unbroken sequence of letters A-Z and digits 0-9, which can be treated as a canonicalized number above and suffixed with a "./". if you choose to not just ignore but flagrantly flout this advice and try to use even more complex and harder to canonicalize internationalized text, such as UNICODE, you are on your own. ๐Ÿ’€

5. Handling Real World Problems ๐ŸŒ

in the real world, stuff goes wrong while you're following the steps and flow from Sections 2 through 4 above ๐Ÿ˜ญ. some problems that have actually happened are described below, with recommendations for handling them.

5.1. Uncertainty as to the Pool

every reasonable effort should be made to make sure the published pool from which selection is made is made of certain and eligible persons ๐Ÿซถ. but, especially with compressed schedules, or someone whose claim that they volunteered and are eligible hasn't been resolved by the deadline, or a determination that someone is not eligible that happens after the pool is published, there may still be uncertainties ๐Ÿ™ˆ.

the best way to handle this is to maintain the announced schedule, INCLUDE in the published pool all those whose eligibility is uncertain, and keep the published pool list numbering IMMUTABLE after its publication ๐Ÿ”’. if someone in the pool is later selected by the algorithm and random input but it has been determined they are ineligible, they can be skipped and the algorithm run further to make an additional selection. so the uncertainty only effects one selection, and in general no more than a maximum of U selections where there are U uncertain pool members. โœจ

other courses of action are way worse ๐Ÿ˜ฉ. actually inserting or deleting entries in the pool after its publication changes the length of the list and totally scrambles who is selected, possibly changing every selection. insertion into the pool also raises questions of where to insert: at the beginning, end, alphabetic order, ... any such choices by the selection administrator after the random numbers are known destroys the public verifiability of fair choice. even if it's done before the random numbers are known, messing with the list after its publication just smells bad ๐Ÿคข. there should be clear fixed public deadlines, and someone who challenges their absence from the pool after the published deadline should have their challenge automatically denied for tardiness โฐ.

5.2. Randomness Ambiguities

the best good faith efforts have been made to specify precise and unambiguous sources of randomness ๐ŸŽฒ. these sources have been made public in advance and there has not been objection to them. however, it has happened that when the time comes to actually get and use this randomness, the real world has thrown a curve ball and it isn't quite clear what data to use ๐ŸŒ€. problems have particularly come up with stock prices, volumes, and financial exchange rates or indices. if volumes that were published in thousands are published in hundreds, you have a rounding problem. prices that were quoted in fractions or decimals can change to the other. if you take care of every contingency that has come up in the past, you can still get hit with a new one ๐Ÿ˜ค. when this sort of thing happens, it's generally too late to announce new sources, and doing that could raise suspicions of its own. the best course of action is basically to make a reasonable choice within the ambiguity and depend on confidence in the good faith of the selection administrator. with care, such cases should be extremely rare ๐Ÿ’–.

based on these experiences, it is again recommended that public lottery numbers or the like be used as the random inputs, and stock prices and volumes avoided ๐ŸŽฐ.


6. Fully Worked Example ๐Ÿงš

okay this is the part where we actually do the math together, and it's giving "show your work" energy ๐Ÿค“. assume the following ordered list of 25 eligible volunteers is published in advance of selection:

      1. John         11. Pollyanna       21. Pride
      2. Mary         12. Pendragon       22. Sloth
      3. Bashful      13. Pandora         23. Envy
      4. Dopey        14. Faith           24. Anger
      5. Sleepy       15. Hope            25. Kasczynski
      6. Grouchy      16. Charity
      7. Doc          17. Lee
      8. Sneazy       18. Longsuffering
      9. Handsome     19. Chastity
     10. Cassandra    20. Smith

assume the following (fake example) ordered list of randomness sources:

  1. The Kingdom of Alphaland State Lottery daily number for 1 November 2004 treated as a single four digit integer.
  2. Numbers of the winning horses at Hialeia for all races for the first day on or after 13 October 2004 on which at least two races are run.
  3. The People's Democratic Republic of Betastani State Lottery six winning numbers (ignoring the seventh "extra" number) for 1 November 2004.

hypothetical randomness publicly produced ๐ŸŽฑ:

    Source 1:  9319
    Source 2:  2, 5, 12, 8, 10
    Source 3:  9, 18, 26, 34, 41, 45

resulting key string ๐Ÿ”‘:

    9319./2.5.8.10.12./9.18.26.34.41.45./

the table below gives the hex of the MD5 of the above key string bracketed with a two byte string that is successively 0x0000, 0x0001, 0x0002, through 0x0010 (16 decimal). the divisor for the number size of the remaining pool at each stage is given, and the index of the selectee as per the original number of those in the pool. ๐Ÿ“Š

   index        hex value of MD5        div  selected
    1  990DD0A5692A029A98B5E01AA28F3459  25  -> 17 <-
    2  3691E55CB63FCC37914430B2F70B5EC6  24  ->  7 <-
    3  FE814EDF564C190AC1D25753979990FA  23  ->  2 <-
    4  1863CCACEB568C31D7DDBDF1D4E91387  22  -> 16 <-
    5  F4AB33DF4889F0AF29C513905BE1D758  21  -> 25 <-
    6  13EAEB529F61ACFB9A29D0BA3A60DE4A  20  -> 23 <-
    7  992DB77C382CA2BDB9727001F3CDCCD9  19  ->  8 <-
    8  63AB4258ECA922976811C7F55C383CE7  18  -> 24 <-
    9  DFBC5AC97CED01B3A6E348E3CC63F40D  17  -> 19 <-
   10  31CB111C4A4EBE9287CEAE16FE51B909  16  -> 13 <-
   11  07FA46C122F164C215BBC72793B189A3  15  -> 22 <-
   12  AC52F8D75CCBE2E61AFEB3387637D501  14  ->  5 <-
   13  53306F73E14FC0B2FBF434218D25948E  13  -> 18 <-
   14  B5D1403501A81F9A47318BE7893B347C  12  ->  9 <-
   15  85B10B356AA06663EF1B1B407765100A  11  ->  1 <-
   16  3269E6CE559ABD57E2BA6AAB495EB9BD  10  ->  4 <-

resulting first ten selected, in order selected ๐Ÿ†:

      1. Lee (17)           6. Envy (23)
      2. Doc (7)            7. Sneazy (8)
      3. Mary (2)           8. Anger (24)
      4. Charity (16)       9. Chastity (19)
     5. Kasczynski (25)    10. Pandora (13)
Backup plan: Should one of the above turn out to be ineligible or decline to serve, the next would be Sloth, number 22. ๐ŸŒธ

7. Security Considerations ๐Ÿ’€

careful choice of should be made of randomness inputs, so that there is no reasonable suspicion that they are under the control of the administrator ๐Ÿ•ต๏ธโ€โ™€๏ธ. the guidelines given above to use a small number of inputs with a substantial amount of entropy from the last should be followed. and equal care needs to be given that the algorithm selected is faithfully executed with the designated input values. this is the part where we don't get sloppy, bestie ๐Ÿซ .

publication of the results, plus a week or so window for the community of interest to duplicate the calculations, should give a reasonable assurance against implementation tampering ๐Ÿ‘‘.

8. Reference Code โœจ

okay so this part is the actual C code, and it's giving full nerd moment ๐Ÿค“๐Ÿ’– The MD5 reference code comes from [RFC 1321] ("RSA Data Security, Inc. MD5 Message-Digest Algorithm"), so we're borrowing that. Matt Crawford wrote the bit that handles multiple floating point numbers ๐Ÿซถ The original code in [RFC 2777] could only handle pools of up to 255 members, and Erik Nordmark stretched that to 2**16-1 ๐Ÿ”ฅ This code got pulled out of this doc, compiled, and tested. No flaws have turned up so far, but bestie, some compiler on some system might still find one ๐Ÿ’€

  /****************************************************************
   *
   *  Reference code for
   *      "Publicly Verifiable Random Selection"
   *          Donald E. Eastlake 3rd
   *              February 2004
   *
   ****************************************************************/
  #include <limits.h>
  #include <math.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  /* From RFC 1321 */
  #include "global.h"
  #include "MD5.h"

  /* local prototypes */
  int longremainder ( unsigned short divisor,
                      unsigned char dividend[16] );
  long int getinteger ( char *string );
  double NPentropy ( int N, int P );


  /* limited to up to 16 inputs of up to sixteen integers each */
  /* pool limit of 2**8-1 extended to 2**16-1 by Erik Nordmark */
  /****************************************************************/

  main ()
  {
  int         i, j,  k, k2, err, keysize, selection, usel;
  unsigned short   remaining, *selected;
  long int    pool, temp, array[16];
  MD5_CTX     ctx;
  char        buffer[257], key [800], sarray[16][256];
  unsigned char    uc16[16], unch1, unch2;

  pool = getinteger ( "Type size of pool:\n" );
  if ( pool > 65535 )

      {
      printf ( "Pool too big.\n" );
      exit ( 1 );
      }
  selected = (unsigned short *) malloc ( (size_t)pool );
  if ( !selected )
      {
      printf ( "Out of memory.\n" );
      exit ( 1 );
      }
  selection = getinteger ( "Type number of items to be selected:\n" );
  if ( selection > pool )
      {
      printf ( "Pool too small.\n" );
      exit ( 1 );
      }
  if ( selection == pool )
      printf ( "All of the pool is selected.\n" );
  else
      {
      err = printf ( "Approximately %.1f bits of entropy needed.\n",
                      NPentropy ( selection, pool ) + 0.1 );
      if ( err <= 0 ) exit ( 1 );
      }
  for ( i = 0, keysize = 0; i < 16; ++i )
      {
      if ( keysize > 500 )
          {
          printf ( "Too much input.\n" );
          exit ( 1 );
          }
      /* get the "random" inputs. echo back to user so the user may
         be able to tell if truncation or other glitches occur.  */
      err = printf (
          "\nType #%d randomness or 'end' followed by new line.\n"
          "Up to 16 integers or the word 'float' followed by up\n"
          "to 16 x.y format reals.\n", i+1 );
      if ( err <= 0 ) exit ( 1 );
      gets ( buffer );
      j = sscanf ( buffer,
              "%ld%ld%ld%ld%ld%ld%ld%ld%ld%ld%ld%ld%ld%ld%ld%ld",
          &array[0], &array[1], &array[2], &array[3],
          &array[4], &array[5], &array[6], &array[7],
          &array[8], &array[9], &array[10], &array[11],
          &array[12], &array[13], &array[14], &array[15] );
      if ( j == EOF )
          exit ( j );
      if ( !j )
          if ( buffer[0] == 'e' )
              break;

          else
              {   /* floating point code by Matt Crawford */
              j = sscanf ( buffer,
                  "float %ld.%[0-9]%ld.%[0-9]%ld.%[0-9]%ld.%[0-9]"
                  "%ld.%[0-9]%ld.%[0-9]%ld.%[0-9]%ld.%[0-9]"
                  "%ld.%[0-9]%ld.%[0-9]%ld.%[0-9]%ld.%[0-9]"
                  "%ld.%[0-9]%ld.%[0-9]%ld.%[0-9]%ld.%[0-9]",
                  &array[0], sarray[0], &array[1], sarray[1],
                  &array[2], sarray[2], &array[3], sarray[3],
                  &array[4], sarray[4], &array[5], sarray[5],
                  &array[6], sarray[6], &array[7], sarray[7],
                  &array[8], sarray[8], &array[9], sarray[9],
                  &array[10], sarray[10], &array[11], sarray[11],
                  &array[12], sarray[12], &array[13], sarray[13],
                  &array[14], sarray[14], &array[15], sarray[15] );
              if ( j == 0 || j & 1 )
                  printf ( "Bad format." );
              else {
                   for ( k = 0, j /= 2; k < j; k++ )
                   {
                         /* strip trailing zeros */
                   for ( k2=strlen(sarray[k]); sarray[k][--k2]=='0';)
                         sarray[k][k2] = '\0';
                   err = printf ( "%ld.%s\n", array[k], sarray[k] );
                   if ( err <= 0 ) exit ( 1 );
                   keysize += sprintf ( &key[keysize], "%ld.%s",
                                        array[k], sarray[k] );
                   }
                   keysize += sprintf ( &key[keysize], "/" );
                   }
              }
      else
          {   /* sort values, not a very efficient algorithm */
          for ( k2 = 0; k2 < j - 1; ++k2 )
              for ( k = 0; k < j - 1; ++k )
                  if ( array[k] > array[k+1] )

                      {
                      temp = array[k];
                      array[k] = array[k+1];
                      array[k+1] = temp;
                      }
          for ( k = 0; k < j; ++k )
              { /* print for user check */
              err = printf ( "%ld ", array[k] );
              if ( err <= 0 ) exit ( 1 );
              keysize += sprintf ( &key[keysize], "%ld.", array[k] );
              }
          keysize += sprintf ( &key[keysize], "/" );
          }
      }   /* end for i */

  /* have obtained all the input, now produce the output */
  err = printf ( "Key is:\n %s\n", key );
  if ( err <= 0 ) exit ( 1 );
  for ( i = 0; i < pool; ++i )
      selected [i] = (unsigned short)(i + 1);
  printf ( "index        hex value of MD5        div  selected\n" );
  for (   usel = 0, remaining = (unsigned short)pool;
          usel < selection;
          ++usel, --remaining )
      {
      unch1 = (unsigned char)usel;
      unch2 = (unsigned char)(usel>>8);
      /* prefix/suffix extended to 2 bytes by Donald Eastlake */
      MD5Init ( &ctx );
      MD5Update ( &ctx, &unch2, 1 );
      MD5Update ( &ctx, &unch1, 1 );
      MD5Update ( &ctx, (unsigned char *)key, keysize );
      MD5Update ( &ctx, &unch2, 1 );
      MD5Update ( &ctx, &unch1, 1 );
      MD5Final ( uc16, &ctx );
      k = longremainder ( remaining, uc16 );
  /* printf ( "Remaining = %d, remainder = %d.\n", remaining, k ); */
      for ( j = 0; j < pool; ++j )
          if ( selected[j] )
              if ( --k < 0 )
                  {
                  printf ( "%2d  "
  "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X  "
  "%2d  -> %2d <-\n",
  usel+1, uc16[0],uc16[1],uc16[2],uc16[3],uc16[4],uc16[5],uc16[6],
  uc16[7],uc16[8],uc16[9],uc16[10],uc16[11],uc16[12],uc16[13],
  uc16[14],uc16[15], remaining, selected[j] );
                  selected[j] = 0;
                  break;
                  }
      }
   printf ( "\nDone, type any character to exit.\n" );
   getchar ();
   return 0;
   }

   /* prompt for a positive non-zero integer input */
   /****************************************************************/
   long int getinteger ( char *string )
   {
   long int     i;
   int          j;
   char    tin[257];

   while ( 1 )
   {
   printf ( string );
   printf ( "(or 'exit' to exit) " );
   gets ( tin );
   j = sscanf ( tin, "%ld", &i );
   if (    ( j == EOF )

       ||  ( !j && ( ( tin[0] == 'e' ) || ( tin[0] == 'E' ) ) )
           )
       exit ( j );
   if ( ( j == 1 ) &&
        ( i > 0 ) )
       return i;
   }   /* end while */
   }

   /* get remainder of dividing a 16 byte unsigned int
      by a small positive number */
   /****************************************************************/
   int longremainder ( unsigned short divisor,
                       unsigned char dividend[16] )
   {
   int i;
   long int kruft;

   if ( !divisor )
       return -1;
   for ( i = 0, kruft = 0; i < 16; ++i )
       {
       kruft = ( kruft << 8 ) + dividend[i];
       kruft %= divisor;
       }
   return kruft;
   }   /* end longremainder */

  /* calculate how many bits of entropy it takes to select N from P */
  /****************************************************************/
  /*             P!
    log  ( ----------------- )
       2    N! * ( P - N )!
  */

  double NPentropy ( int N, int P )
  {
  int         i;
  double      result = 0.0;

  if (    ( N < 1 )   /* not selecting anything? */
     ||   ( N >= P )  /* selecting all of pool or more? */
     )
      return 0.0;     /* degenerate case */
  for ( i = P; i > ( P - N ); --i )
      result += log ( i );
  for ( i = N; i > 1; --i )
      result -= log ( i );
  /* divide by [ log (base e) of 2 ] to convert to bits */
  result /= 0.69315;

  return result;
  }   /* end NPentropy */

Appendix A: History of NomCom Member Selection ๐ŸŽ€

okay the history time is lowkey iconic ๐Ÿ‘‘ Here's the whole list of IETF Nominations Committee member selection techniques and chairs so far, for reference purposes ๐Ÿงš

        YEAR      CHAIR               SELECTION METHOD

     1993/1994  Jeff Case             Clergy
     1994/1995  Fred Baker            Clergy
     1995/1996  Guy Almes             Clergy
     1996/1997  Geoff Huston          Spouse
     1997/1998  Mike St.Johns         Algorithm
     1998/1999  Donald Eastlake 3rd   RFC 2777
     1999/2000  Avri Doria            RFC 2777
     2000/2001  Bernard Aboba         RFC 2777
     2001/2002  Theodore Ts'o         RFC 2777
     2002/2003  Phil Roberts          RFC 2777
     2003/2004  Rich Draves           RFC 2777

So the methods, decoded ๐Ÿซ  Clergy means names went on pieces of paper, got dropped into a receptacle, and a member of the clergy pulled out the NomCom members. Spouse is basically the same vibe, except the chair's spouse did the picking ๐Ÿ’€ Algorithm means it was algorithmic selection using concepts similar to the ones in [RFC 2777] and this document. RFC 2777 means algorithmic selection using the algorithm and reference code from [RFC 2777], but not the fake example sources of randomness ๐Ÿ™ˆ

Appendix B: Changes from RFC 2777 ๐Ÿ’…

This doc is the glow-up of [RFC 2777], the previous version, and it changes three main things. Okay, five, technically ๐Ÿ˜ญ

  1. Section 5 got added. It covers problems that actually showed up when people used these recommendations to pick an IETF NomCom, and how to handle them ๐Ÿ”ฅ
  2. The selection algorithm code now handles pools of up to 2**16-1 elements, and the counter-based prefix and suffix that gets stuck onto the key string before hashing was stretched to two bytes ๐Ÿฆ‹
  3. It's mentioned that IANA used the algorithm in this document to pick the Internationalized Domain Name ACE prefix, plus some minor wording tweaks โœจ
  4. References got split into Informative and Normative ๐Ÿ“š
  5. The list in Appendix A got updated to the present ๐ŸŒˆ

Acknowledgements ๐Ÿซถ

Matt Crawford and Erik Nordmark were the real MVPs of this doc, no cap ๐Ÿ‘‘ Bernard Aboba, Theodore Ts'o, Jim Galvin, Steve Bellovin, and others left comments that got worked into the text, and we love a community that shows up ๐Ÿ’œ

References ๐ŸŒธ

Author's Address โœจ

Okay so this is where you find the author, bestie! ๐ŸŽ€ Donald E. Eastlake, 3rd was at Motorola Laboratories, and here's how to reach him ๐Ÿ’Œ

   Donald E. Eastlake, 3rd
   Motorola Laboratories
   155 Beaver Street
   Milford, MA 01757 USA

   Phone: +1-508-786-7554(w)
          +1-508-634-2066(h)
   EMail: Donald.Eastlake@motorola.com

Okay, legal stuff time, but it's giving protective energy ๐Ÿ›ก๏ธ The Internet Society holds the copyright (2004). This document is covered by the rights, licenses and restrictions in BCP 78, and unless that says otherwise, the authors keep all their rights ๐Ÿ’œ

The document and everything in it is provided "AS IS", and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ๐Ÿ’€

Intellectual Property ๐Ÿ’…

The IETF doesn't take a side on whether any IPR (intellectual property rights) claims are valid, how far they reach, or whether you can get a license for them. It also doesn't claim it went looking for them ๐Ÿ™ˆ If you want the rules on RFC document rights, check BCP 78 and BCP 79.

If you want to see IPR disclosures that were sent to the IETF Secretariat, or any license assurances, or results from trying to get a general license for implementers or users, look in the IETF online IPR repository at http://www.ietf.org/ipr ๐Ÿ”

And if you know about any copyrights, patents, patent applications, or other proprietary rights that could cover tech needed to implement this standard, the IETF wants to hear about it! Send it to ietf-ipr@ietf.org ๐Ÿ“ฌ Telling them early is the iconic move ๐Ÿ‘‘


Acknowledgement ๐Ÿซถ

Shoutout to the people keeping the RFC Editor function running! Right now, that funding comes from the Internet Society ๐ŸŒธ

๐Ÿ“ฆ where this page comes from