Skip to main content

The FNV Non-Cryptographic Hash Algorithm
draft-eastlake-fnv-15

The information below is for an old version of the document.
Document Type
This is an older version of an Internet-Draft whose latest revision state is "Active".
Authors Glenn Fowler , Landon Curt Noll , Kiem-Phong Vo , Donald E. Eastlake 3rd , Tony Hansen
Last updated 2018-06-12 (Latest revision 2017-12-08)
RFC stream (None)
Formats
Additional resources
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-eastlake-fnv-15
" incremental", teststring[i], eUint32,
                  FNV32svalues[i] );
    }
if ( Terr )
    printf ( "%s test of return values failed %i times.0,
             funcName, Terr );
else
    printf ( "%s test of return values passed.0, funcName );
}    /* end Test32 */

/* start Test32Value
 *****************************************************************/
void Test32Value ( char *subfunc,
                   char *string,
                   uint32_t was,
                   uint32_t should )
{
  TestNValue(subfunc, string, sizeof(uint32_t), (uint8_t*)&was,
                                                (uint8_t*)&should);
}   /* end Test32Value */

#ifdef FNV_64bitIntegers
/*****************************************************************
 * Code for FNV64 using 64-bit integers
 *****************************************************************/

void Test64 ()
{
int    i, err;
uint64_t   eUint64 = 42;
FNV64context   eContext;
uint64_t   FNV64svalues[NTstrings] = {
 0xcbf29ce484222325, 0xaf63dc4c8601ec8c, 0x85944171f73967e8 };
uint64_t   FNV64bvalues[NTstrings] = {
 0xaf63bd4c8601b7df, 0x089be207b544f1e4, 0x34531ca7168b8f38 };

funcName = "FNV64";

/* test error checks */
Terr = 0;
TestR ( "init", fnvSuccess, FNV64init (&eContext) );
    TestR ( "string", fnvNull,
            FNV64string ( (char *)0, &eUint64 ) );
    TestR ( "string", fnvNull,

G. Fowler, L. Noll, K. Vo, et. al                             [Page 100]
INTERNET-DRAFT                                                       FNV

            FNV64string ( errteststring, (uint64_t *)0 ) );
    TestR ( "block", fnvNull,
            FNV64block ( (uint8_t *)0, 1, &eUint64 ) );
    TestR ( "block", fnvBadParam,
            FNV64block ( errtestbytes, -1, &eUint64 ) );
    TestR ( "block", fnvNull,
            FNV64block ( errtestbytes, 1, (uint64_t *)0 ) );
    TestR ( "init", fnvNull,
            FNV64init ( (FNV64context *)0 ) );
    TestR ( "initBasis", fnvNull,
            FNV64initBasis ( (FNV64context *)0, 42 ) );
    TestR ( "blockin", fnvNull,
            FNV64blockin ( (FNV64context *)0,
                           errtestbytes, NTestBytes ) );
    TestR ( "blockin", fnvNull,
            FNV64blockin ( &eContext, (uint8_t *)0,
                           NTestBytes ) );
    TestR ( "blockin", fnvBadParam,
            FNV64blockin ( &eContext, errtestbytes, -1 ) );
    eContext.Computed = FNVclobber+FNV64state;
    TestR ( "blockin", fnvStateError,
            FNV64blockin ( &eContext, errtestbytes,
                           NTestBytes ) );
    TestR ( "stringin", fnvNull,
            FNV64stringin ( (FNV64context *)0, errteststring ) );
    TestR ( "stringin", fnvNull,
            FNV64stringin ( &eContext, (char *)0 ) );
    TestR ( "stringin", fnvStateError,
            FNV64stringin ( &eContext, errteststring ) );
    TestR ( "result", fnvNull,
            FNV64result ( (FNV64context *)0, &eUint64 ) );
    TestR ( "result", fnvNull,
            FNV64result ( &eContext, (uint64_t *)0  ) );
    TestR ( "result", fnvStateError,
            FNV64result ( &eContext, &eUint64  ) );
if ( Terr )
    printf ( "%s test of error checks failed %i times.0,
             funcName, Terr );
else
    printf ( "%s test of error checks passed0, funcName );

/* test actual results */
Terr = 0;
for ( i = 0; i < NTstrings; ++i )
    {
    err = TestR ( "string", fnvSuccess,
                  FNV64string ( teststring[i], &eUint64 ) );
    if ( err == fnvSuccess )
        Test64Value ( "string", teststring[i], eUint64,
                      FNV64svalues[i] );

G. Fowler, L. Noll, K. Vo, et. al                             [Page 101]
INTERNET-DRAFT                                                       FNV

    err = TestR ( "block", fnvSuccess,
                  FNV64block ( (uint8_t *)teststring[i],
                               (unsigned long)(strlen(teststring[i])+1),
                               &eUint64 ) );
    if ( err == fnvSuccess )
         Test64Value ( "block", teststring[i], eUint64,
                       FNV64bvalues[i] );
    /* now try testing the incremental stuff */
    err = TestR ( "init", fnvSuccess, FNV64init ( &eContext ) );

    }
if ( Terr )
    printf ( "%s test of return values failed %i times.0,
            funcName, Terr );
else
    printf ( "%s test of return values passed.0, funcName );
}    /* end Test64 */

/* start Test64Value
 *****************************************************************/
 void Test64Value ( char *subfunc,
                   char *string,
                   uint64_t should,
                   uint64_t was )
{
  TestNValue(subfunc, string, sizeof(uint64_t), (uint8_t*)&was,
.                                        (uint8_t*)&should);
}   /* end Test64Value */
#else
void Test64 ()
{
  /* TBD */
}
#endif /* FNV_64bitIntegers */

/*****************************************************************
 * Code for FNV128 using 64-bit integers
 *****************************************************************/

void Test128 ()
{
//int            i, err;
uint8_t        eUint128[FNV128size];
FNV128context  eContext;

funcName = "FNV128";

/* test error checks */
Terr = 0;

G. Fowler, L. Noll, K. Vo, et. al                             [Page 102]
INTERNET-DRAFT                                                       FNV

TestR ( "init", fnvSuccess, FNV128init (&eContext) );
    TestR ( "string", fnvNull,
            FNV128string ( (char *)0, eUint128 ) );
    TestR ( "string", fnvNull,
            FNV128string ( errteststring, (uint8_t *)0 ) );
    TestR ( "block", fnvNull,
            FNV128block ( (uint8_t *)0, 1, eUint128 ) );
    TestR ( "block", fnvBadParam,
            FNV128block ( errtestbytes, -1, eUint128 ) );
    TestR ( "block", fnvNull,
            FNV128block ( errtestbytes, 1, (uint8_t *)0 ) );
    TestR ( "init", fnvNull,
            FNV128init ( (FNV128context *)0 ) );
    TestR ( "initBasis", fnvNull,
            FNV128initBasis ( (FNV128context *)0, eUint128 ) );
    TestR ( "blockin", fnvNull,
            FNV128blockin ( (FNV128context *)0,
                           errtestbytes, NTestBytes ) );
    TestR ( "blockin", fnvNull,
            FNV128blockin ( &eContext, (uint8_t *)0,
                           NTestBytes ) );
    TestR ( "blockin", fnvBadParam,
            FNV128blockin ( &eContext, errtestbytes, -1 ) );
    eContext.Computed = FNVclobber+FNV128state;
    TestR ( "blockin", fnvStateError,
            FNV128blockin ( &eContext, errtestbytes,
                           NTestBytes ) );
    TestR ( "stringin", fnvNull,
            FNV128stringin ( (FNV128context *)0, errteststring ) );
    TestR ( "stringin", fnvNull,
            FNV128stringin ( &eContext, (char *)0 ) );
    TestR ( "stringin", fnvStateError,
            FNV128stringin ( &eContext, errteststring ) );
    TestR ( "result", fnvNull,
            FNV128result ( (FNV128context *)0, eUint128 ) );
    TestR ( "result", fnvNull,
            FNV128result ( &eContext, (uint8_t *)0  ) );
    TestR ( "result", fnvStateError,
            FNV128result ( &eContext, eUint128  ) );
if ( Terr )
    printf ( "%s test of error checks failed %i times.0,
             funcName, Terr );
else
    printf ( "%s test of error checks passed0, funcName );

/* test actual results */
Terr = 0;
/* tbd */
}    /* end Test128 */

G. Fowler, L. Noll, K. Vo, et. al                             [Page 103]
INTERNET-DRAFT                                                       FNV

/*****************************************************************
 * Code for FNV256 using 64-bit integers
 *****************************************************************/

void Test256 ()
{
//int            i, err;
uint8_t        eUint256[FNV256size];
FNV256context  eContext;

funcName = "FNV256";

/* test error checks */
Terr = 0;
TestR ( "init", fnvSuccess, FNV256init (&eContext) );
    TestR ( "string", fnvNull,
            FNV256string ( (char *)0, eUint256 ) );
    TestR ( "string", fnvNull,
            FNV256string ( errteststring, (uint8_t *)0 ) );
    TestR ( "block", fnvNull,
            FNV256block ( (uint8_t *)0, 1, eUint256 ) );
    TestR ( "block", fnvBadParam,
            FNV256block ( errtestbytes, -1, eUint256 ) );
    TestR ( "block", fnvNull,
            FNV256block ( errtestbytes, 1, (uint8_t *)0 ) );
    TestR ( "init", fnvNull,
            FNV256init ( (FNV256context *)0 ) );
    TestR ( "initBasis", fnvNull,
            FNV256initBasis ( (FNV256context *)0, eUint256 ) );
    TestR ( "blockin", fnvNull,
            FNV256blockin ( (FNV256context *)0,
                           errtestbytes, NTestBytes ) );
    TestR ( "blockin", fnvNull,
            FNV256blockin ( &eContext, (uint8_t *)0,
                           NTestBytes ) );
    TestR ( "blockin", fnvBadParam,
            FNV256blockin ( &eContext, errtestbytes, -1 ) );
    eContext.Computed = FNVclobber+FNV256state;
    TestR ( "blockin", fnvStateError,
            FNV256blockin ( &eContext, errtestbytes,
                           NTestBytes ) );
    TestR ( "stringin", fnvNull,
            FNV256stringin ( (FNV256context *)0, errteststring ) );
    TestR ( "stringin", fnvNull,
            FNV256stringin ( &eContext, (char *)0 ) );
    TestR ( "stringin", fnvStateError,
            FNV256stringin ( &eContext, errteststring ) );
    TestR ( "result", fnvNull,
            FNV256result ( (FNV256context *)0, eUint256 ) );
    TestR ( "result", fnvNull,

G. Fowler, L. Noll, K. Vo, et. al                             [Page 104]
INTERNET-DRAFT                                                       FNV

            FNV256result ( &eContext, (uint8_t *)0  ) );
    TestR ( "result", fnvStateError,
            FNV256result ( &eContext, eUint256  ) );
if ( Terr )
    printf ( "%s test of error checks failed %i times.0,
             funcName, Terr );
else
    printf ( "%s test of error checks passed0, funcName );

/* test actual results */
Terr = 0;
/* tbd */
}    /* end Test256 */

/*****************************************************************
 * Code for FNV512 using 64-bit integers
 *****************************************************************/

void Test512 ()
{
//int            i, err;
uint8_t        eUint512[FNV512size];
FNV512context  eContext;

funcName = "FNV512";

/* test error checks */
Terr = 0;
TestR ( "init", fnvSuccess, FNV512init (&eContext) );
    TestR ( "string", fnvNull,
            FNV512string ( (char *)0, eUint512 ) );
    TestR ( "string", fnvNull,
            FNV512string ( errteststring, (uint8_t *)0 ) );
    TestR ( "block", fnvNull,
            FNV512block ( (uint8_t *)0, 1, eUint512 ) );
    TestR ( "block", fnvBadParam,
            FNV512block ( errtestbytes, -1, eUint512 ) );
    TestR ( "block", fnvNull,
            FNV512block ( errtestbytes, 1, (uint8_t *)0 ) );
    TestR ( "init", fnvNull,
            FNV512init ( (FNV512context *)0 ) );
    TestR ( "initBasis", fnvNull,
            FNV512initBasis ( (FNV512context *)0, eUint512 ) );
    TestR ( "blockin", fnvNull,
            FNV512blockin ( (FNV512context *)0,
                           errtestbytes, NTestBytes ) );
    TestR ( "blockin", fnvNull,
            FNV512blockin ( &eContext, (uint8_t *)0,
                           NTestBytes ) );

G. Fowler, L. Noll, K. Vo, et. al                             [Page 105]
INTERNET-DRAFT                                                       FNV

    TestR ( "blockin", fnvBadParam,
            FNV512blockin ( &eContext, errtestbytes, -1 ) );
    eContext.Computed = FNVclobber+FNV512state;
    TestR ( "blockin", fnvStateError,
            FNV512blockin ( &eContext, errtestbytes,
                           NTestBytes ) );
    TestR ( "stringin", fnvNull,
            FNV512stringin ( (FNV512context *)0, errteststring ) );
    TestR ( "stringin", fnvNull,
            FNV512stringin ( &eContext, (char *)0 ) );
    TestR ( "stringin", fnvStateError,
            FNV512stringin ( &eContext, errteststring ) );
    TestR ( "result", fnvNull,
            FNV512result ( (FNV512context *)0, eUint512 ) );
    TestR ( "result", fnvNull,
            FNV512result ( &eContext, (uint8_t *)0  ) );
    TestR ( "result", fnvStateError,
            FNV512result ( &eContext, eUint512  ) );
if ( Terr )
    printf ( "%s test of error checks failed %i times.0,
             funcName, Terr );
else
    printf ( "%s test of error checks passed0, funcName );

/* test actual results */
Terr = 0;
/* tbd */
}    /* end Test512 */

/*****************************************************************
 * Code for FNV1024 using 64-bit integers
 *****************************************************************/

void Test1024 ()
{
//int            i, err;
uint8_t        eUint1024[FNV1024size];
FNV1024context  eContext;

funcName = "FNV1024";

/* test error checks */
Terr = 0;
TestR ( "init", fnvSuccess, FNV1024init (&eContext) );
    TestR ( "string", fnvNull,
            FNV1024string ( (char *)0, eUint1024 ) );
    TestR ( "string", fnvNull,
            FNV1024string ( errteststring, (uint8_t *)0 ) );
    TestR ( "block", fnvNull,

G. Fowler, L. Noll, K. Vo, et. al                             [Page 106]
INTERNET-DRAFT                                                       FNV

            FNV1024block ( (uint8_t *)0, 1, eUint1024 ) );
    TestR ( "block", fnvBadParam,
            FNV1024block ( errtestbytes, -1, eUint1024 ) );
    TestR ( "block", fnvNull,
            FNV1024block ( errtestbytes, 1, (uint8_t *)0 ) );
    TestR ( "init", fnvNull,
            FNV1024init ( (FNV1024context *)0 ) );
    TestR ( "initBasis", fnvNull,
            FNV1024initBasis ( (FNV1024context *)0, eUint1024 ) );
    TestR ( "blockin", fnvNull,
            FNV1024blockin ( (FNV1024context *)0,
                           errtestbytes, NTestBytes ) );
    TestR ( "blockin", fnvNull,
            FNV1024blockin ( &eContext, (uint8_t *)0,
                           NTestBytes ) );
    TestR ( "blockin", fnvBadParam,
            FNV1024blockin ( &eContext, errtestbytes, -1 ) );
    eContext.Computed = FNVclobber+FNV1024state;
    TestR ( "blockin", fnvStateError,
            FNV1024blockin ( &eContext, errtestbytes,
                           NTestBytes ) );
    TestR ( "stringin", fnvNull,
            FNV1024stringin ( (FNV1024context *)0, errteststring ) );
    TestR ( "stringin", fnvNull,
            FNV1024stringin ( &eContext, (char *)0 ) );
    TestR ( "stringin", fnvStateError,
            FNV1024stringin ( &eContext, errteststring ) );
    TestR ( "result", fnvNull,
            FNV1024result ( (FNV1024context *)0, eUint1024 ) );
    TestR ( "result", fnvNull,
            FNV1024result ( &eContext, (uint8_t *)0  ) );
    TestR ( "result", fnvStateError,
            FNV1024result ( &eContext, eUint1024  ) );
if ( Terr )
    printf ( "%s test of error checks failed %i times.0,
             funcName, Terr );
else
    printf ( "%s test of error checks passed0, funcName );

/* test actual results */
Terr = 0;
/* tbd */
}    /* end Test1024 */
   <CODE ENDS>

G. Fowler, L. Noll, K. Vo, et. al                             [Page 107]
INTERNET-DRAFT                                                       FNV

7. Security Considerations

   This document is intended to provide convenient open source access by
   the Internet community to the FNV non-cryptographic hash. No
   assertion of suitability for cryptographic applications is made for
   the FNV hash algorithms.

7.1 Why is FNV Non-Cryptographic?

   A full discussion of cryptographic hash requirements and strength is
   beyond the scope of this document. However, here are three
   characteristics of FNV that would generally be considered to make it
   non-cryptographic:

   1. Sticky State - A cryptographic hash should not have a state in
      which it can stick for a plausible input pattern. But, in the very
      unlikely event that the FNV hash variable becomes zero and the
      input is a sequence of zeros, the hash variable will remain at
      zero until there is a non-zero input byte and the final hash value
      will be unaffected by the length of that sequence of zero input
      bytes. Of course, for the common case of fixed length input, this
      would usually not be significant because the number of non-zero
      bytes would vary inversely with the number of zero bytes and for
      some types of input, runs of zeros do not occur. Furthermore, the
      inclusion of even a little unpredictable input may be sufficient
      to stop an adversary from inducing a zero hash variable.

   2. Diffusion - Every output bit of a cryptographic hash should be an
      equally complex function of every input bit. But it is easy to see
      that the least significant bit of a direct FNV hash is the XOR of
      the least significant bits of every input byte and does not depend
      on any other input bit. While more complex, the second through
      seventh least significant bits of an FNV hash have a similar
      weakness; only the top bit of the bottom byte of output, and
      higher order bits, depend on all input bits. If these properties
      are considered a problem, they can be easily fixed by XOR folding
      (see Section 3).

   3. Work Factor - Depending on intended use, it is frequently
      desirable that a hash function should be computationally expensive
      for general purpose and graphics processors since these may be
      profusely available through elastic cloud services or botnets.
      This is to slow down testing of possible inputs if the output is
      known. But FNV is designed to be very inexpensive on a general-
      purpose processor. (See Appendix A.)

   Nevertheless, none of the above have proven to be a problem in actual
   practice for the many applications of FNV.

G. Fowler, L. Noll, K. Vo, et. al                             [Page 108]
INTERNET-DRAFT                                                       FNV

7.2 Inducing Collisions

   While use of a cryptographic hash should be considered when active
   adversaries are a factor, the following attack can be made much more
   difficult with very minor changes in the use of FNV.

   If FNV is being used in a known way for hash tables in a network
   server or the like, for example some part of a web server, an
   adversary could send requests calculated to cause hash table
   collisions and induce substantial processing delays. As mentioned in
   Section 2.2, use of an offset_basis not knownable by the adversary
   will substantially eliminate this problem.

G. Fowler, L. Noll, K. Vo, et. al                             [Page 109]
INTERNET-DRAFT                                                       FNV

8. IANA Considerations

   This document requires no IANA Actions. RFC Ediotor: Please delete
   this section before publication.

Normative References

   [RFC20] - Cerf, V., "ASCII format for network interchange", STD 80,
         RFC 20, October 1969, <http://www.rfc-editor.org/info/rfc20>.

Informative References

   [FNV] - FNV web site:
         http://www.isthe.com/chongo/tech/comp/fnv/index.html

   [IEEE] - http://www.ieee.org

   [IPv6flow] - https://researchspace.auckland.ac.nz/bitstream/handle/
         2292/13240/flowhashRep.pdf

   [RFC2460] - Deering, S. and R. Hinden, "Internet Protocol, Version 6
         (IPv6) Specification", RFC 2460, December 1998,
         <http://www.rfc-editor.org/info/rfc2460>.

   [RFC3174] - Eastlake 3rd, D. and P. Jones, "US Secure Hash Algorithm
         1 (SHA1)", RFC 3174, September 2001.

   [RFC6194] - Polk, T., Chen, L., Turner, S., and P. Hoffman, "Security
         Considerations for the SHA-0 and SHA-1 Message-Digest
         Algorithms", RFC 6194, March 2011.

   [RFC6234] - Eastlake 3rd, D. and T. Hansen, "US Secure Hash
         Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, May
         2011.

   [RFC6437] - Amante, S., Carpenter, B., Jiang, S., and J. Rajahalme,
         "IPv6 Flow Label Specification", RFC 6437, November 2011,
         <http://www.rfc-editor.org/info/rfc6437>.

G. Fowler, L. Noll, K. Vo, et. al                             [Page 110]
INTERNET-DRAFT                                                       FNV

Acknowledgements

   The contributions of the following are gratefully acknowledged:

      Roman Donchenko, Frank Ellermann, Tony Finch, Bob Moskowitz,
      Gayle Noble, Stefan Santesson, and Mukund Sivaraman.

G. Fowler, L. Noll, K. Vo, et. al                             [Page 111]
INTERNET-DRAFT                                                       FNV

Appendix A: Work Comparison with SHA-1

   This section provides a simplistic rough comparison of the level of
   effort required per input byte to compute FNV-1a and SHA-1 [RFC3174].

   Ignoring transfer of control and conditional tests and equating all
   logical and arithmetic operations, FNV requires 2 operations per
   byte, an XOR and a multiply.

   SHA-1 is a relatively weak cryptographic hash producing a 160-bit
   hash. It has been partially broken [RFC6194]. It is actually designed
   to accept a bit vector input although almost all computer uses apply
   it to an integer number of bytes. It processes blocks of 512 bits (64
   bytes) and we estimate the effort involved in SHA-1 processing a full
   block. Ignoring SHA-1 initial set up, transfer of control, and
   conditional tests, but counting all logical and arithmetic
   operations, including counting indexing as an addition, SHA-1
   requires 1,744 operations per 64 bytes block or 27.25 operations per
   byte. So by this rough measure, it is a little over 13 times the
   effort of FNV for large amounts of data. However, FNV is commonly
   used for small inputs. Using the above method, for inputs of N bytes,
   where N is <= 55 so SHA-1 will take one block (SHA-1 includes padding
   and an 8-byte length at the end of the data in the last block), the
   ratio of the effort for SHA-1 to the effort for FNV will be 872/N.
   For example, with an 8 byte input, SHA-1 will take 109 times as much
   effort as FNV.

   Stronger cryptographic functions than SHA-1 generally have an even
   higher work factor.

G. Fowler, L. Noll, K. Vo, et. al                             [Page 112]
INTERNET-DRAFT                                                       FNV

Appendix B: Previous IETF Reference to FNV

   FNV-1a was referenced in draft-ietf-tls-cached-info-08.txt that has
   since expired. It was later decided that it would be better to use a
   cryptographic hash for that application.

   Below is the Java code for FNV64 from that TLS draft included by the
   kind permission of the author:

   <CODE BEGINS>
    /**
    * Java code sample, implementing 64 bit FNV-1a
    * By Stefan Santesson
    */

   import java.math.BigInteger;

   public class FNV {

      static public BigInteger getFNV1aToByte(byte[] inp) {

          BigInteger m = new BigInteger("2").pow(64);
          BigInteger fnvPrime = new BigInteger("1099511628211");
          BigInteger fnvOffsetBasis =
                  new BigInteger("14695981039346656037");

          BigInteger digest = fnvOffsetBasis;

          for (byte b : inp) {
              digest = digest.xor(BigInteger.valueOf((int) b & 255));
              digest = digest.multiply(fnvPrime).mod(m);
          }
          return digest;

      }
   }
   <CODE ENDS>

G. Fowler, L. Noll, K. Vo, et. al                             [Page 113]
INTERNET-DRAFT                                                       FNV

Appendix C: A Few Test Vectors

   Below are a few test vectors in the form of ASCII strings and their
   FNV32 and FNV64 hashes using the FNV-1a algorithm.

         Strings without null (zero byte) termination:

         String       FNV32       FNV64
          ""        0x811c9dc5  0xcbf29ce484222325
          "a"       0xe40c292c  0xaf63dc4c8601ec8c
          "foobar"  0xbf9cf968  0x85944171f73967e8

         Strings including null (zero byte) termination:

         String       FNV32       FNV64
          ""        0x050c5d1f  0xaf63bd4c8601b7df
          "a"       0x2b24d044  0x089be207b544f1e4
          "foobar"  0x0c1c9eb8  0x34531ca7168b8f38

G. Fowler, L. Noll, K. Vo, et. al                             [Page 114]
INTERNET-DRAFT                                                       FNV

Appendix Z: Change Summary

   RFC Editor Note: Please delete this appendix on publication.

From -00 to -01

   1. Add Security Considerations section on why FNV is non-
      cryptographic.

   2. Add Appendix A on a work factor comparison with SHA-1.

   3. Add Appendix B concerning previous IETF draft referenced to FNV.

   4. Minor editorial changes.

From -01 to -02

   1. Correct FNV_Prime determination criteria and add note as to why s
      < 5 and s > 10 are not considered.

   2. Add acknowledgements list.

   3. Add a couple of references.

   4. Minor editorial changes.

From -02 to -03

   1. Replace direct reference to US-ASCII standard with reference to
      RFC 20.

   2. Update dates and version number.

   3. Minor editing changes.

From -03 to -04

   1. Change reference to RFC 20 back to a reference to the ANSI 1968
      ASCII standard.

   2. Minor addition to Section 6, point 3.

G. Fowler, L. Noll, K. Vo, et. al                             [Page 115]
INTERNET-DRAFT                                                       FNV

   3. Update dates and version number.

   4. Minor editing changes.

From -04 to -05

   1. Add Twitter as a use example and IPv6 flow hash study reference.

   2. Update dates and version number.

From -05 to -06

   1. Add code subsections.

   2. Update dates and version number.

From -06 to -07 to -08

   1. Update Author info.

   2. Minor edits.

From -08 to -09

   1. Change reference for ASCII to [RFC20].

   2. Add more details on history of the string used to compute
      offset_basis.

   3. Re-write "Work Factor" part of Section 6 to be more precise.

   4. Minor editorial changes.

From -09 to -10

   1. Inclusion of initial partial version of code and some
      documentation about the code, Section 6.

   2. Insertion of new Section 4 on hashing values.

G. Fowler, L. Noll, K. Vo, et. al                             [Page 116]
INTERNET-DRAFT                                                       FNV

From -10 to -11

   Changes based on code improvements primarily from Tony Hansen who has
   been added as an author. Changes based on comments from Mukund
   Sivaraman and Roman Donchenko.

From -11 to -12

   Keep alive update.

From -12 to -13

   Fixed bug in pseudocode in Section 2.3.

   Change code to eliminate the BigEndian flag and so there are separate
   byte vector output routines for FNV32 and FNV64, equivalent to the
   other routines, and integer output routines for cases where
   Endianness consistency is not required.

From -13 to -14 to -15

   Keep alive updates.

G. Fowler, L. Noll, K. Vo, et. al                             [Page 117]
INTERNET-DRAFT                                                       FNV

Author's Address

   Glenn Fowler
   Google

   Email:       glenn.s.fowler@gmail.com

   Landon Curt Noll
   Cisco Systems
   170 West Tasman Drive
   San Jose, CA 95134 USA

   Telephone:   +1-408-424-1102
   Email:       fnv-ietf4-mail@asthe.com
   URL:         http://www.isthe.com/chongo/index.html

   Kiem-Phong Vo
   Google

   Email:       phongvo@gmail.com

   Donald Eastlake
   Huawei Technologies
   155 Beaver Street
   Milford, MA 01757 USA

   Telephone:   +1-508-333-2270
   EMail:       d3e3e3@gmail.com

   Tony Hansen
   AT&T Laboratories
   200 Laurel Ave. South
   Middletown, NJ  07748
   USA

   Email: tony@att.com

G. Fowler, L. Noll, K. Vo, et. al                             [Page 118]
INTERNET-DRAFT                                                       FNV

Copyright, Disclaimer, and Additional IPR Provisions

   Copyright (c) 2018 IETF Trust and the persons identified as the
   document authors. All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents
   (http://trustee.ietf.org/license-info) in effect on the date of
   publication of this document. Please review these documents
   carefully, as they describe your rights and restrictions with respect
   to this document. Code Components extracted from this document must
   include Simplified BSD License text as described in Section 4.e of
   the Trust Legal Provisions and are provided without warranty as
   described in the Simplified BSD License.  This Internet-Draft is
   submitted to IETF in full conformance with the provisions of BCP 78
   and BCP 79.

G. Fowler, L. Noll, K. Vo, et. al                             [Page 119]