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]