rfc9923.original   rfc9923.txt 
Network Working Group G. Fowler Independent Submission G. Fowler
Internet-Draft Google Request for Comments: 9923 Google
Intended status: Informational L. Noll Category: Informational L. Noll
Expires: 8 December 2025 Cisco Systems ISSN: 2070-1721 Cisco Systems
K. Vo K. Vo
Google Google
D. Eastlake D. Eastlake 3rd
Independent Independent
T. Hansen T. Hansen
AT&T AT&T
6 June 2025 December 2025
The FNV Non-Cryptographic Hash Algorithm The FNV Non-Cryptographic Hash Algorithm
draft-eastlake-fnv-35
Abstract Abstract
FNV (Fowler/Noll/Vo) is a fast, non-cryptographic hash algorithm with FNV (Fowler/Noll/Vo) is a fast, non-cryptographic hash algorithm with
good dispersion that has been widely used and is referenced in a good dispersion that has been widely used and is referenced in a
number of standards documents. The purpose of this document is to number of standards documents. The purpose of this document is to
make information on FNV and open-source code performing all specified make information on FNV and open-source code performing all specified
sizes of FNV conveniently available to the Internet community. sizes of FNV conveniently available to the Internet community.
Status of This Memo Status of This Memo
This Internet-Draft is submitted in full conformance with the This document is not an Internet Standards Track specification; it is
provisions of BCP 78 and BCP 79. published for informational purposes.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months This is a contribution to the RFC Series, independently of any other
and may be updated, replaced, or obsoleted by other documents at any RFC stream. The RFC Editor has chosen to publish this document at
time. It is inappropriate to use Internet-Drafts as reference its discretion and makes no statement about its value for
material or to cite them other than as "work in progress." implementation or deployment. Documents approved for publication by
the RFC Editor are not candidates for any level of Internet Standard;
see Section 2 of RFC 7841.
This Internet-Draft will expire on 8 December 2025. Information about the current status of this document, any errata,
and how to provide feedback on it may be obtained at
https://www.rfc-editor.org/info/rfc9923.
Copyright Notice Copyright Notice
Copyright (c) 2025 IETF Trust and the persons identified as the Copyright (c) 2025 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/ Provisions Relating to IETF Documents
license-info) in effect on the date of publication of this document. (https://trustee.ietf.org/license-info) in effect on the date of
Please review these documents carefully, as they describe your rights publication of this document. Please review these documents
and restrictions with respect to this document. Code Components carefully, as they describe your rights and restrictions with respect
extracted from this document must include Revised BSD License text as to this document.
described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Revised BSD License.
Table of Contents Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 1. Introduction
1.1. Applicability of Non-Cryptographic Hashes and FNV . . . . 3 1.1. Conventions Used in This Document
1.2. FNV Hash Uses . . . . . . . . . . . . . . . . . . . . . . 4 1.2. Applicability of Non-Cryptographic Hashes and FNV
1.3. Why is FNV Non-Cryptographic? . . . . . . . . . . . . . . 6 1.3. FNV Hash Uses
2. FNV Basics . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.4. Why Is FNV Non-Cryptographic?
2.1. FNV Primes . . . . . . . . . . . . . . . . . . . . . . . 7 2. FNV Basics
2.2. FNV offset_basis . . . . . . . . . . . . . . . . . . . . 8 2.1. FNV Primes
2.3. FNV Endianism . . . . . . . . . . . . . . . . . . . . . . 9 2.2. FNV offset_basis
3. Other Hash Sizes and XOR Folding . . . . . . . . . . . . . . 9 2.3. FNV Endianism
4. Hashing Multiple Values Together . . . . . . . . . . . . . . 10 3. Other Hash Sizes and XOR Folding
5. FNV Constants . . . . . . . . . . . . . . . . . . . . . . . . 12 4. Hashing Multiple Values Together
6. Security Considerations . . . . . . . . . . . . . . . . . . . 14 5. FNV Constants
6.1. Inducing Collisions . . . . . . . . . . . . . . . . . . . 15 6. Security Considerations
7. Historical Notes . . . . . . . . . . . . . . . . . . . . . . 16 6.1. Inducing Collisions
8. The Source Code . . . . . . . . . . . . . . . . . . . . . . . 16 7. Historical Notes
8.1. Source Code Details . . . . . . . . . . . . . . . . . . . 17 8. The Source Code
8.1.1. FNV Functions Available . . . . . . . . . . . . . . . 17 8.1. Source Code Details
8.1.2. Source Files and 64-bit Support . . . . . . . . . . . 18 8.1.1. FNV Functions Available
8.1.3. Command Line Interface . . . . . . . . . . . . . . . 18 8.1.2. Source Files and 64-Bit Support
8.2. FNV-1a C Code . . . . . . . . . . . . . . . . . . . . . . 19 8.1.3. Command Line Interface
8.2.1. FNV32 Code . . . . . . . . . . . . . . . . . . . . . 23 8.2. FNV-1a C Code
8.2.2. FNV64 Code . . . . . . . . . . . . . . . . . . . . . 33 8.2.1. FNV32 Code
8.2.3. FNV128 Code . . . . . . . . . . . . . . . . . . . . . 49 8.2.2. FNV64 Code
8.2.4. FNV256 Code . . . . . . . . . . . . . . . . . . . . . 61 8.2.3. FNV128 Code
8.2.5. FNV512 Code . . . . . . . . . . . . . . . . . . . . . 73 8.2.4. FNV256 Code
8.2.6. FNV1024 Code . . . . . . . . . . . . . . . . . . . . 86 8.2.5. FNV512 Code
8.3. FNV Test Code . . . . . . . . . . . . . . . . . . . . . . 98 8.2.6. FNV1024 Code
8.4. Makefile . . . . . . . . . . . . . . . . . . . . . . . . 124 8.3. FNV Test Code
9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 125 8.4. Makefile
10. Normative References . . . . . . . . . . . . . . . . . . . . 125 9. IANA Considerations
11. Informative References . . . . . . . . . . . . . . . . . . . 126 10. References
Appendix A. Work Comparison with SHA-1 and SHA-256 . . . . . . . 129 10.1. Normative References
Appendix B. Previous IETF FNV Code . . . . . . . . . . . . . . . 130 10.2. Informative References
Appendix C. Change History . . . . . . . . . . . . . . . . . . . 131 Appendix A. Work Comparison with SHA-1 and SHA-256
C.1. From -00 to -01 . . . . . . . . . . . . . . . . . . . . . 131 Appendix B. Previous IETF FNV Code
C.2. From -01 to -02 . . . . . . . . . . . . . . . . . . . . . 131 Acknowledgements
C.3. From -02 to -05 . . . . . . . . . . . . . . . . . . . . . 132 Authors' Addresses
C.4. From -05 to -08 . . . . . . . . . . . . . . . . . . . . . 132
C.5. From -08 to -09 . . . . . . . . . . . . . . . . . . . . . 132
C.6. From -09 to -10 . . . . . . . . . . . . . . . . . . . . . 132
C.7. From -10 to -12 . . . . . . . . . . . . . . . . . . . . . 132
C.8. From -12 to -13 . . . . . . . . . . . . . . . . . . . . . 133
C.9. From -13 to -17 . . . . . . . . . . . . . . . . . . . . . 133
C.10. From -17 to -19 . . . . . . . . . . . . . . . . . . . . . 133
C.11. From -19 to -20 . . . . . . . . . . . . . . . . . . . . . 133
C.12. From -20 to -21 . . . . . . . . . . . . . . . . . . . . . 133
C.13. From -21 to -22 . . . . . . . . . . . . . . . . . . . . . 133
C.14. From -22 to -23 . . . . . . . . . . . . . . . . . . . . . 133
C.15. From -23 to -25 . . . . . . . . . . . . . . . . . . . . . 134
C.16. From -25 to -28 . . . . . . . . . . . . . . . . . . . . . 134
C.17. From -28 to -29 . . . . . . . . . . . . . . . . . . . . . 134
C.18. From -29 to -30 . . . . . . . . . . . . . . . . . . . . . 134
C.19. From -30 to -31 . . . . . . . . . . . . . . . . . . . . . 135
C.20. From -31 to -32 . . . . . . . . . . . . . . . . . . . . . 135
C.21. From -32 to -33 . . . . . . . . . . . . . . . . . . . . . 135
C.22. From -33 to -34 . . . . . . . . . . . . . . . . . . . . . 135
C.23. From -34 to -35 . . . . . . . . . . . . . . . . . . . . . 135
Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 136
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 136
1. Introduction 1. Introduction
FNV (Fowler/Noll/Vo) hashes are designed to be fast and have a small FNV (Fowler/Noll/Vo) hashes are designed to be fast and have a small
code footprint. Their good dispersion makes them particularly well- code footprint. Their good dispersion makes them particularly well
suited for hashing nearly identical strings, including URLs, suited for hashing nearly identical strings, including URLs,
hostnames, filenames, text, and IP and MAC addresses. Their speed hostnames, filenames, text, and IP and Media Access Control (MAC)
allows one to quickly hash lots of data. addresses. Their speed allows one to quickly hash lots of data.
The purpose of this document is to make information on FNV and open- The purpose of this document is to make information on FNV and open-
source code performing all specified sizes of FNV conveniently source code performing all specified sizes of FNV conveniently
available to the Internet community. This work is not an Internet available to the Internet community. This work is not an Internet
standard and is not the result of consensus of the IETF community. Standard and does not have the consensus of the IETF community.
1.1. Applicability of Non-Cryptographic Hashes and FNV 1.1. Conventions Used in This Document
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.
1.2. Applicability of Non-Cryptographic Hashes and FNV
While a general theory of hash function strength and utility is While a general theory of hash function strength and utility is
beyond the scope of this document, typical attacks on hash function beyond the scope of this document, typical attacks on hash functions
involve one of the following: involve one of the following:
Collision: Finding two data inputs that yield the same hash output. Collision: Finding two data inputs that yield the same hash output.
First Pre-Image: Given a hash output, finding a data input that First Pre-Image: Given a hash output, finding a data input that
hashes to that output. hashes to that output.
Second Pre-Image: Given a first data input, finding a second input Second Pre-Image: Given a first data input, finding a second input
that produces the same hash output as the first. that produces the same hash output as the first.
For a hash function producing N bits, there necessarily will be For a hash function producing N bits, there necessarily will be
collisions among the hashes of more than 2**N distinct inputs. And collisions among the hashes of more than 2**N distinct inputs. And
if the hash function can produce hashes covering all 2**N possible if the hash function can produce hashes covering all 2**N possible
outputs, then there will exist first and second pre-images. FNV is outputs, then there will exist first and second pre-images. FNV is
NOT RECOMMENDED for any application that requires that it be NOT RECOMMENDED for any application that requires that it be
computationally infeasible to succeed in one of the above attacks. computationally infeasible for one of the above types of attacks to
succeed.
FNV hashes are generally not applicable for use when faced with an FNV hashes are generally not applicable for use when faced with an
active adversary in a security scheme where the modest effort active adversary in a security scheme where the modest effort
required to compute FNV hashes (see Appendix A) and their other required to compute FNV hashes (see Appendix A) and their other non-
noncryptographic characteristics (see Section 1.3) would make the cryptographic characteristics (see Section 1.4) would make the scheme
scheme ineffective against the threat model being considered. It is ineffective against the threat model being considered. It is
sometimes hard to determine whether or not there are attack vectors sometimes hard to determine whether or not there are attack vectors
via a hash. via a hash.
For a discussion of adversarial inducement of collisions, see For a discussion of adversarial inducement of collisions, see
Section 6.1. Section 6.1.
1.2. FNV Hash Uses 1.3. FNV Hash Uses
The FNV hash has been widely used. Examples include the following: The FNV hash has been widely used. Examples include the following:
* NFS implementations (e.g., FreeBSD 4.3 [FreeBSD], IRIX, Linux (NFS * NFS implementations (e.g., FreeBSD 4.3 [FreeBSD], IRIX, Linux (NFS
v4)), v4)),
* text based referenced resources for video games on the PS2, * text-based referenced resources for video games on the PS2,
Gamecube, and XBOX Gamecube, and XBOX,
* [Cohesia] MASS project server collision avoidance, * Cohesia MASS project server collision avoidance [Cohesia],
* to improve the fragment cache [FragCache] at X (formerly Twitter), * to improve the fragment cache [FragCache] at X (formerly Twitter),
* the flatassembler open source x86 assembler - user-defined symbol * the flatassembler open-source x86 assembler - user-defined symbol
hashtree [flatassembler], hashtree [flatassembler],
* Used in the speed-sensitive guts of [twistylists], an open-source * used in the speed-sensitive guts of [twistylists], an open-source
structured namespace manager, structured namespace manager,
* database indexing hashes, * database indexing hashes,
* PowerBASIC [BASIC] inline assembly routine, * PowerBASIC inline assembly routine [BASIC],
* major web search / indexing engines, * major web search / indexing engines,
* the [calc] calculator, * the "calc" C-style calculator [calc],
* netnews history file Message-ID lookup functions, * netnews history file Message-ID lookup functions,
* [FRET] - a tool to identify file data structures / helps to * [FRET] - a tool to identify file data structures / help understand
understand file formats file formats,
* anti-spam filters, * anti-spam filters,
* used in an implementation of libketama for use in items such as * used in an implementation of libketama for use in items such as
[memcache], [memcache],
* a spellchecker programmed in Ada 95, * a spellchecker programmed in Ada 95,
* used in the BSD IDE project [fasmlab], * used in the BSD IDE project [fasmlab],
* non-cryptographic file fingerprints, * non-cryptographic file fingerprints,
* used in the deliantra game server for its shared string * used in the deliantra game server for its shared string
implementation [deliantra] implementation [deliantra],
* computing Unique IDs in DASM (DTN (Delay Tolerant Networking) * computing Unique IDs in DASM (DTN (Delay Tolerant Networking)
Applications for Symbian Mobile-phones), Applications for Symbian Mobile-phones),
* Microsoft's hash_map implementation for VC++ 2005, * Microsoft's hash_map implementation for VC++ 2005,
* the realpath cache in PHP 5.x (php-5.2.3/TSRM/tsrm_virtual_cwd.c), * the realpath cache in PHP 5.x (php-5.2.3/TSRM/tsrm_virtual_cwd.c),
* DNS (Domain Name System) servers, * DNS (Domain Name System) servers,
* used to improve [Leprechaun], an extremely fast word list creator, * used to improve [Leprechaun], an extremely fast wordlist creator,
* the [Vely] framework for C language, * the Vely framework [Vely] for the C language,
* Golf language hash tables [GolfHash], * Golf language hash tables [GolfHash],
* the libstr logging library [libstr], * the libsir logging library [libsir],
* a standard library for modern fortran [Fortran], * a standard library for modern Fortran [Fortran],
* to help seeding a pseudo random number generator [Vortetty], * to help with seeding a pseudorandom number generator [Vortetty],
and many other uses. It is also referenced in the [RFC7357], and many other uses. It is also referenced in the following
[RFC7873], and [IEEE8021Qbp] standards documents. standards documents: [RFC7357], [RFC7873], and [IEEE8021Qbp].
A study has recommended FNV in connection with the IPv6 Flow Label A study has recommended FNV in connection with the IPv6 Flow Label
field [IPv6flow]. Additionally, there was a proposal to use FNV for field [IPv6flow]. Additionally, there was a proposal to use FNV for
BFD sequence number generation [BFDseq] and a recent article and BFD sequence number generation [ISAAC-Auth] and a recent article and
study on non-cryptographic hash functions [NCHF]. study on non-cryptographic hash functions [NCHF].
If you use an FNV function in an application, you are kindly If you use an FNV function in an application, you are kindly
requested to send an EMail about it to <fnvhash-mail@asthe.com> with requested to send an email about it to <fnvhash-mail@asthe.com> with
"FNV hash function" forming part of the subject line. "FNV hash function" forming part of the subject line.
1.3. Why is FNV Non-Cryptographic? 1.4. Why Is FNV Non-Cryptographic?
A full discussion of cryptographic hash requirements and strength is A full discussion of cryptographic hash requirements and strength is
beyond the scope of this document. However, here are three beyond the scope of this document. However, here are three
characteristics of FNV that would generally be considered to make it characteristics of FNV that would generally be considered to make it
non-cryptographic: non-cryptographic:
1. Sticky State - A cryptographic hash should not have a state in 1. Sticky State - A cryptographic hash should not have a state in
which it can stick for a plausible input pattern. But, in the which it can stick for a plausible input pattern. But in the
very unlikely event that the FNV hash variable accidentally very unlikely event that the FNV hash variable accidentally
becomes zero and the input is a sequence of zero bytes, the hash becomes zero and the input is a sequence of zero bytes, the hash
variable will remain at zero until there is a non-zero input byte 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 and the final hash value will be unaffected by the length of that
sequence of zero input bytes. For the common case of fixed sequence of zero input bytes. For the common case of fixed-
length input, this would usually not be significant because the length input, this would usually not be significant because the
number of non-zero bytes would vary inversely with the number of 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 zero bytes and for some types of input, runs of zeros do not
occur. Furthermore, the use of a different offset_basis or the occur. Furthermore, the use of a different offset_basis or the
inclusion of even a little unpredictable input may be sufficient, inclusion of even a little unpredictable input may be sufficient,
under some circumstances, to stop an adversary from inducing a under some circumstances, to stop an adversary from inducing a
zero hash variable (see Section 6.1). zero hash variable (see Section 6.1).
2. Diffusion - Every output bit of a cryptographic hash should be an 2. Diffusion - Every output bit of a cryptographic hash should be an
equally complex function of every input bit. But it is easy to 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 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 XOR of the least significant bits of every input byte and does
not depend on any other input bits. While more complex, the not depend on any other input bits. While more complex, the
second through seventh least significant bits of an FNV hash have second through seventh least significant bits of an FNV hash have
a similar weakness; only the top bit of the bottom byte of a similar weakness; only the top bit of the bottom byte of
output, and higher order bits, depend on all input bits. If output, and higher-order bits, depend on all input bits. If
these properties are considered a problem, they can be easily these properties are considered a problem, they can be easily
fixed by XOR folding (see Section 3). fixed by XOR folding (see Section 3).
3. Work Factor - Depending on intended use, it is frequently 3. Work Factor - Depending on intended use, it is frequently
desirable that a hash function should be computationally desirable that a hash function should be computationally
expensive for general purpose and graphics processors since these expensive for general-purpose and graphics processors, since
may be profusely available through elastic cloud services or these may be profusely available through elastic cloud services
botnets. This is to slow down testing of possible inputs if the or botnets. This is applied to slow down testing of possible
output is known or the like. But FNV is designed to be inputs if the output is known or the like. But FNV is designed
inexpensive on a general-purpose processor. (See Appendix A.) to be inexpensive on a general-purpose processor (see
Appendix A).
Nevertheless, none of the above have proven to be a problem in actual Nevertheless, none of the above have proven to be a problem in actual
practice for the many non-cryptographic applications of FNV (see practice for the many non-cryptographic applications of FNV (see
Section 1.2). Section 1.3).
2. FNV Basics 2. FNV Basics
This document focuses on the FNV-1a function whose pseudo-code is as This document focuses on the FNV-1a function, whose pseudocode is as
follows: follows:
hash = offset_basis hash = offset_basis
for each octet_of_data to be hashed for each octet_of_data to be hashed
hash = hash xor octet_of_data hash = hash xor octet_of_data
hash = hash * FNV_Prime mod 2**HashSize hash = hash * FNV_Prime mod 2**HashSize
return hash return hash
In the pseudo-code above, hash is a power-of-two number of bits In the pseudocode above, hash is a power-of-2 number of bits
(HashSize is 32, 64, 128, 256, 512, or 1024) and offset_basis and (HashSize is 32, 64, 128, 256, 512, or 1024), and offset_basis and
FNV_Prime depend on the size of hash. FNV_Prime depend on the size of hash.
The FNV-1 algorithm is the same, including the values of offset_basis The FNV-1 algorithm is the same, including the values of offset_basis
and FNV_Prime, except that the order of the two lines with the "xor" and FNV_Prime, except that the order of the two lines with the "xor"
and multiply operations are reversed. Operational experience and multiply operations is reversed. Operational experience
indicates better hash dispersion for small amounts of data with FNV- indicates better hash dispersion for small amounts of data with FNV-
1a. FNV-0 is the same as FNV-1 but with offset_basis set to zero. 1a. FNV-0 is the same as FNV-1 but with offset_basis set to zero.
FNV-1a is suggested for general use. FNV-1a is suggested for general use.
2.1. FNV Primes 2.1. FNV Primes
The theory behind FNV_Prime's is beyond the scope of this document The theory behind FNV_Primes is beyond the scope of this document,
but the basic property to look for is how an FNV_Prime would impact but the basic property to look for is how an FNV_Prime would impact
dispersion. Now, consider any n-bit FNV hash where n >= 32 and is dispersion. Now, consider any n-bit FNV hash where n >= 32 and is
also a power of 2, in particular n = 2**s. For each such n-bit FNV also a power of 2 -- in particular, n = 2**s. For each such n-bit
hash, an FNV_Prime p is defined as: FNV hash, an FNV_Prime p is defined as follows:
* When s is an integer and 4 < s < 11, then FNV_Prime is the * When s is an integer and 4 < s < 11, FNV_Prime is the smallest
smallest prime p of the form: prime p of the form:
256**int((5 + 2**s)/12) + 2**8 + b 256**int((5 + 2**s)/12) + 2**8 + b
* where b is an integer such that: * where b is an integer such that:
0 < b < 2**8 0 < b < 2**8
* The number of one-bits in b is 4 or 5 * The number of one-bits in b is four or five
* and where * and where
( p mod (2**40 - 2**24 - 1) ) > ( 2**24 + 2**8 + 2**7 ) ( p mod (2**40 - 2**24 - 1) ) > ( 2**24 + 2**8 + 2**7 )
Experimentally, FNV_Primes matching the above constraints tend to Experimentally, FNV_Primes matching the above constraints tend to
have better dispersion properties. They improve the polynomial have better dispersion properties. They improve the polynomial
feedback characteristic when an FNV_Prime multiplies an intermediate feedback characteristic when an FNV_Prime multiplies an intermediate
hash value. As such, the hash values produced are more scattered hash value. As such, the hash values produced are more scattered
throughout the n-bit hash space. throughout the n-bit hash space.
The case where s < 5 is not considered due to the resulting low hash The case where s < 5 is not considered due to the resulting low hash
quality. Such small hashes can, if desired, be derived from a 32 bit quality. Such small hashes can, if desired, be derived from a 32-bit
FNV hash by XOR folding (see Section 3). The case where s > 10 is FNV hash by XOR folding (see Section 3). The case where s > 10 is
not considered because of the doubtful utility of such large FNV not considered because of the doubtful utility of such large FNV
hashes and because the criteria for such large FNV_Primes is more hashes and because the criteria for such large FNV_Primes is more
complex, due to the sparsity of such large primes, and would complex, due to the sparsity of such large primes, and would
needlessly clutter the criteria given above. needlessly clutter the criteria given above.
Per the above constraints, an FNV_Prime should have only 6 or 7 one- Per the above constraints, an FNV_Prime should have only six or seven
bits in it: one relatively high order one bit, the 2**9 bit, and 4 or one-bits in it: one relatively high-order one bit, the 2**9 bit, and
5 one bits in the low order byte. Therefore, some compilers may seek four or five one bits in the low-order byte. Therefore, some
to improve the performance of a multiplication with an FNV_Prime by compilers may seek to improve the performance of a multiplication
replacing the multiplication with shifts and adds. However, the with an FNV_Prime by replacing the multiplication with shifts and
performance of this substitution is highly hardware-dependent and adds. However, the performance of this substitution is highly
should be done with care. The selection of FNV_Primes prioritizes hardware dependent and should be done with care. The selection of
the quality of the resulting hash function, not compiler optimization FNV_Primes prioritizes the quality of the resulting hash function,
considerations. not compiler optimization considerations.
2.2. FNV offset_basis 2.2. FNV offset_basis
The offset_basis values for the n-bit FNV-1a algorithms are computed The offset_basis values for the n-bit FNV-1a algorithms are computed
by applying the n-bit FNV-0 algorithm to the following 32-octet ASCII by applying the n-bit FNV-0 algorithm to the following 32-octet ASCII
[RFC0020] character string: [RFC0020] character string:
chongo <Landon Curt Noll> /\../\ chongo <Landon Curt Noll> /\../\
or, in [C] notation, the following string: or, in C notation [C], the following string:
"chongo <Landon Curt Noll> /\\../\\" "chongo <Landon Curt Noll> /\\../\\"
In the general case, almost any offset_basis would serve as long as In the general case, almost any offset_basis would serve as long as
it is non-zero. However, FNV hashes calculated with different it is non-zero. However, FNV hashes calculated with different
offset_basis values will not interoperate. The choice of a non- offset_basis values will not interoperate. The choice of a non-
standard offset_basis may be beneficial in some limited circumstances standard offset_basis may be beneficial in some limited circumstances
to defend against attacks that try to induce hash collisions as to defend against attacks that try to induce hash collisions as
discussed in Section 6.1. Any entity that can observe the FNV hash discussed in Section 6.1. Any entity that can observe the FNV hash
output, and can cause the null string (the string of length zero) to output, and can cause the null string (the string of length zero) to
be hashed, will thereby be able to directly observe the offset_basis be hashed, will thereby be able to directly observe the offset_basis
which will be the hash output. which will be the hash output.
skipping to change at page 9, line 18 skipping to change at line 376
platforms, an FNV hash shall be represented in the little endian platforms, an FNV hash shall be represented in the little endian
format [IEN137]. That is, the FNV hash will be stored in an array format [IEN137]. That is, the FNV hash will be stored in an array
hash[N] with N bytes such that its integer value can be retrieved as hash[N] with N bytes such that its integer value can be retrieved as
follows: follows:
unsigned char hash[N]; unsigned char hash[N];
for ( i = N-1, value = 0; i >= 0; --i ) for ( i = N-1, value = 0; i >= 0; --i )
value = ( value << 8 ) + hash[i]; value = ( value << 8 ) + hash[i];
However, when FNV hashes are used in a single process or a group of However, when FNV hashes are used in a single process or a group of
processes sharing memory on processors with compatible endian-ness, processes sharing memory on processors with compatible endianness,
the natural endian-ness of those processors can be used, as long as the natural endianness of those processors can be used, as long as it
it is used consistently, regardless of its type, little, big, or some is used consistently, regardless of its type -- little, big, or some
other exotic form. other exotic form.
The code provided in Section 6 has FNV hash functions that return a The code provided in Section 6 has FNV hash functions that return a
little endian byte vector for all lengths. Because they are more little endian byte vector for all lengths. Because they are more
efficient, the code also provides functions that return FNV hashes as efficient, the code also provides functions that return FNV hashes as
32-bit integers or, where supported, 64-bit integers, for those sizes 32-bit integers or, where supported, 64-bit integers, for those sizes
of FNV hash. Such integers are compatible with the same size byte of FNV hash. Such integers are compatible with the same-size byte
vectors on little endian computers but use of the functions returning vectors on little endian computers, but the use of the functions
integers on big endian or other non-little-endian machines will be returning integers on big endian or other non-little-endian machines
byte-reversed or otherwise incompatible with the byte vector return will be byte-reversed or otherwise incompatible with the byte vector
values. return values.
3. Other Hash Sizes and XOR Folding 3. Other Hash Sizes and XOR Folding
Many hash uses require a hash that is not one of the FNV sizes for Many hash uses require a hash that is not one of the FNV sizes for
which constants are provided in Section 5. If a larger hash size is which constants are provided in Section 5. If a larger hash size is
needed, please contact the authors of this document. needed, please contact the authors of this document.
For scenarios where a fixed-size binary field of k bits is desired For scenarios where a fixed-size binary field of k bits is desired
with k < 1024 but not among the provided constants in Section 5, the with k < 1024 but not among the constants provided in Section 5, the
recommended approach involves using the smallest FNV hash of size S recommended approach involves using the smallest FNV hash of size S
where S > k and employing xor folding, as shown below. The final bit where S > k and employing xor folding, as shown below. The final
masking operation is logically unnecessary if the size of the bit-masking operation is logically unnecessary if the size of the
variable k-bit-hash is exactly k bits. variable k-bit-hash is exactly k bits.
temp = FNV_S ( data-to-be-hashed ) temp = FNV_S ( data-to-be-hashed )
k-bit-hash = ( temp xor temp>>k ) bitwise-and ( 2**k - 1 ) k-bit-hash = ( temp xor temp>>k ) bitwise-and ( 2**k - 1 )
A somewhat stronger hash may be obtained for exact FNV sizes by A somewhat stronger hash may be obtained for exact FNV sizes by
calculating an FNV twice as long as the desired output ( S = 2*k ) calculating an FNV twice as long as the desired output ( S = 2*k )
and performing such xor data folding using a k equal to the size of and performing such xor data folding using a k equal to the size of
the desired output. However, if a much stronger hash is desired, the desired output. However, if a much stronger hash is desired,
cryptographic algorithms, such as those in [FIPS202] or [RFC6234], cryptographic algorithms, such as those specified in [FIPS202] or
should be used. [RFC6234], should be used.
If it is desired to obtain a hash result that is a value between 0 If it is desired to obtain a hash result that is a value between 0
and max, where max+1 is a not a power of two, simply choose an FNV and max, where max+1 is not a power of 2, simply choose an FNV hash
hash size S such that 2**S > max. Then calculate the following: size S such that 2**S > max. Then, calculate the following:
FNV_S mod ( max+1 ) FNV_S mod ( max+1 )
The resulting remainder will be in the range desired but will suffer The resulting remainder will be in the range desired but will suffer
from a bias against large values with the bias being larger if 2**S from a bias against large values, with the bias being larger if 2**S
is only a little bigger than max. If this bias is acceptable, no is only slightly larger than max. If this bias is acceptable, no
further processing is needed. If this bias is unacceptable, it can further processing is needed. If this bias is unacceptable, it can
be avoided by retrying for certain high values of hash, as follows, be avoided by retrying for certain high values of hash, as follows,
before applying the mod operation above: before applying the mod operation above:
X = ( int( ( 2**S - 1 ) / ( max+1 ) ) ) * ( max+1 ) X = ( int( ( 2**S - 1 ) / ( max+1 ) ) ) * ( max+1 )
while ( hash >= X ) while ( hash >= X )
hash = ( hash * FNV_Prime ) + offset_basis hash = ( hash * FNV_Prime ) + offset_basis
4. Hashing Multiple Values Together 4. Hashing Multiple Values Together
Sometimes there are multiple different component values, say three Sometimes, there are multiple different component values, say three
strings X, Y, and Z, where a hash over all of them is desired. The strings X, Y, and Z, where a hash over all of them is desired. The
simplest thing to do is to concatenate them in a fixed order and simplest thing to do is to concatenate them in a fixed order and
compute the hash of that concatenation, as in compute the hash of that concatenation, as in
hash ( X | Y | Z ) hash ( X | Y | Z )
where the vertical bar character ("|") represents string where the vertical bar character ("|") represents string
concatenation. If the components being combined are of variable concatenation. If the components being combined are of variable
length, some information is lost by simple concatenation. For length, some information is lost by simple concatenation. For
example, X = "12" and Y = "345" would not be distinguished from X = example, X = "12" and Y = "345" would not be distinguished from X =
"123" and Y = "45". To preserve that information, each component "123" and Y = "45". To preserve that information, each component
should be preceded by an encoding of its length, or end with some should be preceded by an encoding of its length or should end with
sequence that cannot occur within the component, or some similar some sequence that cannot occur within the component, or some similar
technique should be used. technique should be used.
For FNV, the same hash results if X, Y, and Z are actually For FNV, the same hash results if X, Y, and Z are actually
concatenated and the FNV hash applied to the resulting string or if concatenated and the FNV hash applied to the resulting string or if
FNV is calculated on an initial substring and the result used as the FNV is calculated on an initial substring and the result used as the
offset_basis when calculating the FNV hash of the remainder of the offset_basis when calculating the FNV hash of the remainder of the
string. This can be done several times. Assuming FNVoffset_basis ( string. This can be done several times. Assuming that
v, w ) is FNV of w using v as the offset_basis, then in the example FNVoffset_basis ( v, w ) is the FNV of w using v as the offset_basis,
above, fnvx = FNV ( X ) could be calculated and then fnvxy = then in the example above, fnvx = FNV ( X ) could be calculated and
FNVoffset_basis ( fnvx, Y ), and finally fnvxyz = FNVoffset_basis ( then fnvxy = FNVoffset_basis ( fnvx, Y ), and finally fnvxyz =
fnvxy, Z). The resulting fnvxyz would be the same as FNV ( X | Y | Z FNVoffset_basis ( fnvxy, Z ). The resulting fnvxyz would be the same
). as FNV ( X | Y | Z ).
This means that if you have the value of FNV ( X ) and you want to This means that if you have the value of FNV ( X ) and you want to
calculate FNV ( X | Y ), you do not need to find X. You can simply calculate FNV ( X | Y ), you do not need to find X. You can simply
calculate FNVoffset_basis ( FNV ( X ), Y ) and thereby get FNV ( X |Y calculate FNVoffset_basis ( FNV ( X ), Y ) and thereby get FNV ( X |
). Y ).
Sometimes such a hash needs to be repeatedly calculated and the Sometimes, such a hash needs to be repeatedly calculated; the
component values vary but some vary more frequently than others. For component values vary, but some vary more frequently than others.
example, assume some sort of computer network traffic flow ID, such For example, assume that some sort of computer network traffic flow
as the IPv6 flow ID [RFC6437], is to be calculated for network ID, such as the IPv6 flow ID [RFC6437], is to be calculated for
packets based on the source and destination IPv6 address and the network packets based on the source and destination IPv6 addresses
Traffic Class [RFC8200]. If the Flow ID is calculated in the and the Traffic Class [RFC8200]. If the Flow ID is calculated in the
originating host, the source IPv6 address would likely always be the originating host, the source IPv6 address would likely always be the
same or perhaps assume one of a very small number of values. By same or would perhaps assume one of a very small number of values.
placing this quasi-constant IPv6 source address first in the string By placing this quasi-constant IPv6 source address first in the
being FNV hashed, FNV ( IPv6source ) could be calculated and used as string being FNV-hashed, FNV ( IPv6source ) could be calculated and
the offset_basis for calculating FNV of the IPv6 destination address used as the offset_basis for calculating the FNV of the IPv6
and Traffic Class for each packet. As a result, the per packet hash destination address and Traffic Class for each packet. As a result,
would be over 17 bytes rather than over 33 bytes saving computational the per-packet hash would be over 17 bytes rather than over 33 bytes,
resources. The source code in this document includes functions saving computational resources. The source code in this document
facilitating the use of a non-standard offset_basis. includes functions facilitating the use of a non-standard
offset_basis.
An alternative method of hashing multiple values is to concatenate An alternative method of hashing multiple values is to concatenate
the hashes of those values and then hash the concatenation, this is, the hashes of those values and then hash the concatenation -- that
compute something like is, compute something like
hash ( hash(X) | hash (Y) | hash (Z) ) hash ( hash (X) | hash (Y) | hash (Z) )
This will involve more computation than simply computing the hash of This will involve more computation than simply computing the hash of
the concatenation of the values and thus, unless parallel the concatenation of the values and thus, unless parallel
computational resources are available, greater latency; however, if computational resources are available, greater latency; however, if
parallel computational resources are available and the values being parallel computational resources are available and the values being
hashed together are long enough to overcome any initial/final hash hashed together are long enough to overcome any initial/final hash
function overhead, which is very small for FNV, latency can be function overhead, which is very small for FNV, latency can be
reduced by hashing the concatenation of the hashes of the values. reduced by hashing the concatenation of the hashes of the values.
For another example of a similar technique, assume a desire to use For another example of a similar technique, assume a desire to use
FNV-N to hash a byte string of length L. Let B = N/8, the number of FNV-N to hash a byte string of length L. Let B = N/8, the number of
bytes of FNV-N output. If that string is divided into k successive bytes of FNV-N output. If that string is divided into k successive
equal length substrings and assuming, for simplicity, that L is an substrings of equal length and assuming, for simplicity, that L is an
integer multiple of k, hashing the substrings and then hashing the integer multiple of k, hashing the substrings and then hashing the
concatenation of their hashes will hash a total of L + k*B bytes, concatenation of their hashes will hash a total of L + k*B bytes,
clearly more than the initial string size L. However, if sufficient clearly more than the initial string size L. However, if sufficient
parallel computational resources are available to hash all the parallel computational resources are available to hash all the
substrings simultaneously, the elapsed time can be changed substrings simultaneously, the elapsed time can be changed
approximately from on the order of L to on the order of L/k + k*B. approximately from on the order of L to on the order of L/k + k*B.
For sufficiently large L, this parallelization will reduce the For sufficiently large L, this parallelization will reduce the
elapsed time to produce the overall hash. elapsed time to produce the overall hash.
5. FNV Constants 5. FNV Constants
skipping to change at page 14, line 49 skipping to change at line 645
| AFF4B16C71EE90B3 | | AFF4B16C71EE90B3 |
+-------------------------------------------------------------------+ +-------------------------------------------------------------------+
Table 2 Table 2
6. Security Considerations 6. Security Considerations
No assertion of suitability for cryptographic applications is made No assertion of suitability for cryptographic applications is made
for the FNV hash algorithms. for the FNV hash algorithms.
Use of a cryptographic hash function should be considered when active The use of a cryptographic hash function should be considered when
adversaries are a factor (see Section 1.1). active adversaries are a factor (see Section 1.2).
6.1. Inducing Collisions 6.1. Inducing Collisions
An attacker could attempt to induce collisions to cause denial or An attacker could attempt to induce collisions to cause denial or
degradation of service. Consider the following simplified example: a degradation of service. Consider the following simplified example: A
hash table of n buckets is being maintained with the bucket used by hash table of n buckets is being maintained with the bucket used by
some item i determined by some item i determined by
hash(i) mod n hash(i) mod n
and with a linked list out of each bucket of the items that all hash and with a linked list out of each bucket of the items that all hash
to that bucket. Such an arrangement might be used for the symbol to that bucket. Such an arrangement might be used for the symbol
table in a compiler or for some of the routing information (i.e., RIB table in a compiler or for some of the routing information (i.e., a
(Routing Information Base)) in a router. Then a large number of RIB (Routing Information Base)) in a router. A large number of items
items hashing to the same bucket will likely result in much slower hashing to the same bucket will then likely result in much slower
times to retrieve from or update the information stored through the times to retrieve from or update the information stored through the
table for one of those items. Typically, an attacker could arrange table for one of those items. Typically, an attacker could arrange
for the number of distinct items being hashed to be orders of for the number of distinct items being hashed to be orders of
magnitude larger than n, even if n was tens or hundreds of thousands, magnitude larger than n, even if n was tens or hundreds of thousands,
so collisions are guaranteed to occur in this example regardless of so collisions are guaranteed to occur in this example regardless of
the nature of the hash function. the nature of the hash function.
There are a number of different circumstances that might surround There are a number of different circumstances that might surround
this example of which the following three are illustrative: this example, of which the following three are illustrative:
* If a hash function is being used in an exactly known way for the * If a hash function is being used in an exactly known way for the
above scenario, including a known offset_basis such as a standard above scenario, including a known offset_basis such as a standard
offset_basis specified in this document, then an adversary could offset_basis specified in this document, then an adversary could
test items off-line and generate an arbitrary set of items whose test items offline and generate an arbitrary set of items whose
hash table indexes would collide. Under these circumstances, the hash table indexes would collide. Under these circumstances, the
adversary would not have to conduct any trials of actually adversary would not have to conduct any trials of actually
submitting items and would not have to measure performance to find submitting items and would not have to measure performance to find
collisions. Then submitting such a set of items would degrade or collisions. Submitting such a set of items would then degrade or
deny service. For FNV, use of an offset_basis not known by the deny service. For FNV, the use of an offset_basis not known by
adversary is adequate to defeat this case. the adversary is adequate to defeat this case.
* If the adversary cannot detect when collisions occur, or service * If the adversary cannot detect when collisions occur or when
is degraded, then it is sufficient for the adversary to be unable service is degraded, then it is sufficient for the adversary to be
to predict the hash outcomes. For FNV, use of an offset_basis not unable to predict the hash outcomes. For FNV, the use of an
known by the adversary may be adequate to defend against this offset_basis not known by the adversary may be adequate to defend
case. against this case.
* If the adversary can detect the degradation in service caused by * If the adversary can detect the degradation in service caused by
collisions in the above example and can feed large numbers of collisions in the above example and can feed large numbers of
variable items to the process, then they can collect sets of items variable items to the process, then they can collect sets of items
that appear to collide. Even if there are limits to the number of that appear to collide. Even if there are limits to the number of
items that can be submitted, if there can be multiple trials, the items that can be submitted, if there can be multiple trials, the
adversary can collect multiple sets of items that collide within adversary can collect multiple sets of items that collide within
each set or one growing set of items all of which collide. Then, each set or one growing set of items, all of which collide. Then,
by submitting such items, the adversary can degrade or deny by submitting such items, the adversary can degrade or deny
service. That is true regardless of whether the hash function service. That is true regardless of whether the hash function
used is a non-cryptographic hash function such as FNV or a used is a non-cryptographic hash function such as FNV or a
cryptographic hash function such as those in [FIPS202] or cryptographic hash function such as those specified in [FIPS202]
[RFC6234]. One defense in this case is to detect when a large or [RFC6234]. One defense in this case is to detect when a large
number of collisions are happening (which could, but would be number of collisions are happening (which could, but would be
unlikely to, occur by chance) and, when that is detected, rehash unlikely to, occur by chance) and, when that is detected, rehash
the items with some change to the hash algorithm and use the the items with some change to the hash algorithm and use the
changed hash algorithm for subsequent items; for example, if FNV changed hash algorithm for subsequent items -- for example, if FNV
is being used, to rehash with a different offset_basis and then is being used, to rehash with a different offset_basis and then
continue using that new offset_basis. There exist commercially continue using that new offset_basis. There exist commercially
deployed routers that use this technique to ameliorate excessive deployed routers that use this technique to ameliorate excessive
hash collisions in internal tables. hash collisions in internal tables.
7. Historical Notes 7. Historical Notes
The FNV hash algorithm originated from an idea submitted as reviewer The FNV hash algorithm originated from an idea submitted as reviewer
comments to the [IEEE] POSIX P1003.2 committee in 1991 by Glenn comments to the IEEE POSIX P1003.2 committee [IEEE] in 1991 by Glenn
Fowler and Phong Vo. Subsequently, during a ballot round, Landon Fowler and Phong Vo. Subsequently, during a ballot round, Landon
Curt Noll proposed an enhancement to their algorithm. Some people Curt Noll proposed an enhancement to their algorithm. Some people
tried this hash and found that it worked rather well. In an EMail tried this hash and found that it worked rather well. In an email
message to Landon, they named it the "Fowler/Noll/Vo" or FNV hash message to Landon, they named it the "Fowler/Noll/Vo" or FNV hash
from their last names in alphabetic order. [FNV] from their last names in alphabetical order [FNV].
The string used to calculate the offset_basis values (see The string used to calculate the offset_basis values (see
Section 2.2) was selected because the person testing FNV with non- Section 2.2) was selected because the person testing FNV with non-
zero offset_basis values was looking at an email message from Landon zero offset_basis values was looking at an email message from Landon
and was copying his standard email signature line; however, they and was copying his standard email signature line; however, they "did
"didn't see very well" [FNV] and copied it incorrectly. In fact, not see very well" [FNV] and copied it incorrectly. In fact, Landon
Landon uses uses
chongo (Landon Curt Noll) /\oo/\ chongo (Landon Curt Noll) /\oo/\
but, since it doesn't matter, no effort has been made to correct but, since it doesn't matter, no effort has been made to correct
this. this.
8. The Source Code 8. The Source Code
The following sub-sections provide reference [C] source code and a The following subsections provide reference C source code [C] and a
test driver with command line interface for FNV-1a. test driver with a command line interface for FNV-1a.
Section 8.2 provides the C header and code source files for the FNV Section 8.2 provides the C header and code source files for the FNV
functions. Section 8.3 provides the test driver. Section 8.4 functions. Section 8.3 provides the test driver. Section 8.4
provides a simple makefile to build the test driver or a library file provides a simple makefile to build the test driver or a library file
with all FNV sizes. with all FNV sizes.
Alternative source code for 32- and 64-bit FNV is available at Alternative source code for 32- and 64-bit FNV is available at
[LCN2]. Other alternative source code, including in x86 assembler, [LCN2]. Other alternative source code, including in x86 assembler,
is currently available at [FNV]. In some cases, this further source is currently available at [FNV]. In some cases, this further source
code has been further optimized. code has been further optimized.
8.1. Source Code Details 8.1. Source Code Details
8.1.1. FNV Functions Available 8.1.1. FNV Functions Available
The functions provided are listed below. The "xxx" in the function The functions provided are listed below. The "xxx" in the function
names is "32", "64", "128", "256", "512", or "1024" depending on the names is "32", "64", "128", "256", "512", or "1024", depending on the
length of the FNV. All of the FNV hash functions have as their length of the FNV. All of the FNV hash functions have as their
return value an integer whose meaning is specified in return value an integer whose meaning is specified in
FNVErrorCodes.h. FNVErrorCodes.h.
Functions providing a byte vector hash are available for all lengths. Functions providing a byte vector hash are available for all lengths.
For FNV-32, versions are available that provide a 32-bit integer and For FNV-32, versions are available that provide a 32-bit integer and
are identified by replacing "xxx" with "32INT". For example, are identified by replacing "xxx" with "32INT". For example,
FNV32string provides a 4-byte vector but FNV32INTstring provides a FNV32string provides a 4-byte vector, but FNV32INTstring provides a
32-bit integer. For FNV-64, if compiled with 64-bit integers enabled 32-bit integer. For FNV-64, if compiled with 64-bit integers enabled
(i.e., FNV_64bitIntegers defined, see FNVconfig.h), versions are (i.e., FNV_64bitIntegers defined; see FNVconfig.h), versions are
available that provide a 64-bit integer and are identified by available that provide a 64-bit integer and are identified by
replacing "xxx" with "64INT"`. Versions providing an integer hash replacing "xxx" with "64INT". Versions providing an integer hash
will not be compatible between systems of different endian-ness (see will not be compatible between systems of different endianness (see
Section 2.3). Section 2.3).
If you want to copy the source code from this document, note that it If you want to copy the source code from this document, note that it
is indented by three spaces in the ".txt" version. It may be is indented by three spaces in the ".txt" version. It may be
simplest to copy from the ".html" version of this document. simplest to copy from the ".html" version of this document.
FNVxxxstring, FNVxxxblock, FNVxxxfile: FNVxxxstring, FNVxxxblock, FNVxxxfile:
FNVxxxstringBase, FNVxxxblockBase, FNVxxxfileBase: FNVxxxstringBase, FNVxxxblockBase, FNVxxxfileBase:
FNVxxxINTstring, FNVxxxINTblock, FNVxxxINTfile: FNVxxxINTstring, FNVxxxINTblock, FNVxxxINTfile:
FNVxxxINTstringBase, FNVxxxINTblockBase, FNVxxxINTfileBase: These FNVxxxINTstringBase, FNVxxxINTblockBase, FNVxxxINTfileBase: These
are simple functions for directly returning the FNV hash of a zero are simple functions for directly returning the FNV hash of a
terminated byte string not including that zero byte, the FNV hash zero-terminated byte string not including that zero byte, the FNV
of a counted block of bytes, and the FNV of a file, respectively. hash of a counted block of bytes, and the FNV of a file,
The functions whose name has the "Base" suffix take an additional respectively. The functions whose names have the "Base" suffix
parameter specifying the offset_basis. Note that for applications take an additional parameter specifying the offset_basis. Note
of FNV-32 and of FNV-64 where integers of that size are supported that for applications of FNV-32 and of FNV-64 where integers of
and an integer data type output is acceptable, the code is that size are supported and an integer data type output is
sufficiently simple that, to maximize performance, use of open acceptable, the code is sufficiently simple that, to maximize
coding or macros may be more appropriate than calling a performance, the use of open coding or macros may be more
subroutine. appropriate than calling a subroutine.
FNVxxxinit, FNVxxxinitBasis: FNVxxxinit, FNVxxxinitBasis:
FNVxxxINTinitBasis: These functions and the next two sets of FNVxxxINTinitBasis: These functions and the next two sets of
functions below provide facilities for incrementally calculating functions below provide facilities for incrementally calculating
FNV hashes. They all assume a data structure of type FNV hashes. They all assume a data structure of type
FNVxxxcontext that holds the current state of the hash. FNVxxxcontext that holds the current state of the hash.
FNVxxxinit initializes that context to the standard offset_basis. FNVxxxinit initializes that context to the standard offset_basis.
FNVxxxinitBasis takes an offset_basis value as a parameter and may FNVxxxinitBasis takes an offset_basis value as a parameter and may
be useful for hashing concatenations, as described in Section 4, be useful for hashing concatenations, as described in Section 4,
as well as for simply using a non-standard offset_basis. as well as for simply using a non-standard offset_basis.
FNVxxxblockin, FNVxxxstringin, FNVxxxfilein: These functions hash a FNVxxxblockin, FNVxxxstringin, FNVxxxfilein: These functions hash a
sequence of bytes into an FNVxxxcontext that was originally sequence of bytes into an FNVxxxcontext that was originally
initialized by FNVxxxinit or FNVxxxinitBasis. FNVxxxblockin initialized by FNVxxxinit or FNVxxxinitBasis. FNVxxxblockin
hashes in a counted block of bytes. FNVxxxstringin hashes in a hashes in a counted block of bytes. FNVxxxstringin hashes in a
zero terminated byte string not including the final zero byte. zero-terminated byte string not including the final zero byte.
FNVxxxfilein hashes in the contents of a file. FNVxxxfilein hashes in the contents of a file.
FNVxxxresult, FNVxxxINTresult: This function extracts the final FNV FNVxxxresult, FNVxxxINTresult: This function extracts the final FNV
hash result from an FNVxxxcontext. hash result from an FNVxxxcontext.
8.1.2. Source Files and 64-bit Support 8.1.2. Source Files and 64-Bit Support
Code optimized for 64-bit integer support, that is, support of 64-bit Code optimized for 64-bit integer support -- that is, support of
integer addition and 32x32-bit multiplication producing a 64-bit 64-bit integer addition and 32-bit x 32-bit multiplication producing
product, is provided based on whether or not the FNV_64bitIntegers a 64-bit product -- is provided based on whether or not the
symbol is defined. By default, this is set in FNVconfig.h based on FNV_64bitIntegers symbol is defined. By default, this is set in
the compilation target; however, this can be overridden by editing FNVconfig.h based on the compilation target; however, this can be
that file or by defining certain symbols in, for example, a command overridden by editing that file or by defining certain symbols in,
line invoking compilation. for example, a command line invoking compilation.
For support of a single FNV size, say "xxx", in an application, the For support of a single FNV size, say "xxx" (e.g., FNV64), in an
application itself needs to include the FNVxxx.h (which will, in application, the application itself needs to include the appropriate
turn, include the FNVconfig.h and FNVErrorCodes.h) files. To build FNVxxx.h file (which will, in turn, include the FNVconfig.h and
the particular FNVxxx code itself, compile the FNVxxx.c file with FNVErrorCodes.h files). To build the particular FNVxxx code itself,
FNVconfig.h, fnv-private.h, FNVErrorCodes.h, and FNVxxx.h available. compile the FNVxxx.c file with FNVconfig.h, fnv-private.h,
Since the test program in Section 8.3 uses all sizes of FNV, all the FNVErrorCodes.h, and FNVxxx.h (available in Section 8.2). Since the
test program provided in Section 8.3 uses all sizes of FNV, all the
.c and .h files are needed to compile it. .c and .h files are needed to compile it.
8.1.3. Command Line Interface 8.1.3. Command Line Interface
The test program provided in Section 8.3 has a command line The test program provided in Section 8.3 has a command line
interface. By default, with no command line arguments, it runs tests interface. By default, with no command line arguments, it runs tests
of all FNV lengths. Command line options are as follows: of all FNV lengths. Command line options are as follows:
FNVhash [-a] [-h] [-t nnn] [-u nnn] [-v] [-f filename] [token ...] FNVhash [-a] [-h] [-t nnn] [-u nnn] [-v] [-f filename] [token ...]
The option letters have the following meaning: The option letters have the following meanings:
-a Run tests for all lengths. -a Run tests for all lengths.
-h Print a help message about the command line. -h Print a help message about the command line.
-v Complement the Verbose flag which is initially off. When the -v Complement the Verbose flag, which is initially off. When the
flag is on, the program prints more information during tests, etc. flag is on, the program prints more information during tests, etc.
-t nnn Run tests for length nnn which must be one of 32, 64, 128, -t nnn Run tests for length nnn, which must be one of 32, 64, 128,
256, 512, or 1024. 256, 512, or 1024.
-u nnn Use hash size nnn which must be one of 32, 64, 128, 256, 512, -u nnn Use hash size nnn, which must be one of 32, 64, 128, 256,
or 1024. This is useful to set the hash size for use by the -f 512, or 1024. This is useful for setting the hash size for use by
option or in hashing tokens on the command line after the options. the -f option or in hashing tokens on the command line after the
options.
-f filename Hash the contents of the file with name filename. The -f filename Hash the contents of the file with name filename. The
hash size must have been set by a prior -t or -u option in the hash size must have been set by a prior -t or -u option in the
command line. command line.
token Tokens appearing on the command line after the options are token Tokens appearing on the command line after the options are
hashed with the current hash size which must have been set by a hashed with the current hash size, which must have been set by a
prior -t or -u option in the command line. prior -t or -u option in the command line.
For example, For example,
FNVhash -t 128 -h -v -t 64 -v -u 256 -f foobar.txt RabOof 1234 FNVhash -t 128 -h -v -t 64 -v -u 256 -f foobar.txt RabOof 1234
runs tests for FNV128, then prints a command line help message, then runs tests for FNV128, then prints a command line help message, then
turns on Verbose, then runs the tests for FNV64, then turns off turns on Verbose, then runs the tests for FNV64, then turns off
Verbose, then sets the hash size to 256, then hashes the contents of Verbose, then sets the hash size to 256, then hashes the contents of
file foobar.txt, then hashes the token "RabOof", and finally hashes file foobar.txt, then hashes the token "RabOof", and finally hashes
the token "1234". the token "1234".
8.2. FNV-1a C Code 8.2. FNV-1a C Code
This section provides the direct FNV-1a function for each of the This section provides the direct FNV-1a function for each of the
lengths for which it is specified in this document. lengths for which it is specified in this document.
The following is a configuration header to set whether 64-bit The following is a configuration header to set whether 64-bit
integers are supported and establish an enum used for return values. integers are supported and establish an enum used for return values.
<CODE BEGINS> file "FNVconfig.h" <CODE BEGINS> file "FNVconfig.h"
//************************ FNVconfig.h **************************// //************************ FNVconfig.h **************************//
//**************** See RFC NNNN for details. ********************// //**************** See RFC 9923 for details. ********************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
*
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
#ifndef _FNVconfig_H_ #ifndef _FNVconfig_H_
#define _FNVconfig_H_ #define _FNVconfig_H_
/* Description: /*
* Description:
* This file provides configuration ifdefs for the * This file provides configuration ifdefs for the
* FNV-1a non-cryptographic hash algorithms. */ * FNV-1a non-cryptographic hash algorithms. */
/* FNV_64bitIntegers - Define this if your system supports /* FNV_64bitIntegers - Define this if your system supports
* 64-bit arithmetic including 32-bit x 32-bit * 64-bit arithmetic including 32-bit x 32-bit
* multiplication producing a 64-bit product. If * multiplication producing a 64-bit product. If
* undefined, it will be assumed that 32-bit arithmetic * undefined, it will be assumed that 32-bit arithmetic
* is supported including 16-bit x 16-bit multiplication * is supported including 16-bit x 16-bit multiplication
* producing a 32-bit result. * producing a 32-bit result.
*/ */
#include <stdint.h> #include <stdint.h>
/* Check if 64-bit integers are supported in the target */ /* Check if 64-bit integers are supported in the target */
#ifdef UINT64_MAX #ifdef UINT64_MAX
skipping to change at page 21, line 7 skipping to change at line 941
#endif #endif
#endif /* _FNVconfig_H_ */ #endif /* _FNVconfig_H_ */
<CODE ENDS> <CODE ENDS>
The following code is a simple header file to define the return value The following code is a simple header file to define the return value
error codes for the FNV routines. error codes for the FNV routines.
<CODE BEGINS> file "FNVErrorCodes.h" <CODE BEGINS> file "FNVErrorCodes.h"
//********************** FNVErrorCodes.h **************************// //********************** FNVErrorCodes.h **************************//
//**************** See RFC NNNN for details. **********************// //**************** See RFC 9923 for details. **********************//
/* Copyright (c) 2016, 2023, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2023, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
#ifndef _FNV_ErrCodes_ #ifndef _FNV_ErrCodes_
#define _FNV_ErrCodes_ #define _FNV_ErrCodes_
//****************************************************************// //****************************************************************//
// //
// All FNV functions, except the FNVxxxfile functions, // All FNV functions, except the FNVxxxfile functions,
skipping to change at page 21, line 31 skipping to change at line 965
// //
enum { /* success and errors */ enum { /* success and errors */
fnvSuccess = 0, fnvSuccess = 0,
fnvNull, // 1 Null pointer parameter fnvNull, // 1 Null pointer parameter
fnvStateError, // 2 called Input after Result or before Init fnvStateError, // 2 called Input after Result or before Init
fnvBadParam // 3 passed a bad parameter fnvBadParam // 3 passed a bad parameter
}; };
#endif /* _FNV_ErrCodes_ */ #endif /* _FNV_ErrCodes_ */
<CODE ENDS> <CODE ENDS>
The following code is a private header file used by all the FNV The following code is a private header file that is used by all the
functions further below and which states the terms for use and FNV functions further below and that states the terms for use and
redistribution of all of this source code. redistribution of all of this source code.
<CODE BEGINS> file "fnv-private.h" <CODE BEGINS> file "fnv-private.h"
//********************** fnv-private.h ************************// //************************ fnv-private.h **************************//
//**************** See RFC NNNN for details *******************// //****************** See RFC 9923 for details. ********************//
/* Copyright (c) 2016, 2023, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2023, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
skipping to change at page 22, line 13 skipping to change at line 996
* *
* * Neither the name of Internet Society, IETF or IETF Trust, nor * * Neither the name of Internet Society, IETF or IETF Trust, nor
* the names of specific contributors, may be used to endorse or * the names of specific contributors, may be used to endorse or
* promote products derived from this software without specific * promote products derived from this software without specific
* prior written permission. * prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
skipping to change at page 22, line 38 skipping to change at line 1021
* Six FNV-1a hashes are defined with these sizes: * Six FNV-1a hashes are defined with these sizes:
* FNV32 32 bits, 4 bytes * FNV32 32 bits, 4 bytes
* FNV64 64 bits, 8 bytes * FNV64 64 bits, 8 bytes
* FNV128 128 bits, 16 bytes * FNV128 128 bits, 16 bytes
* FNV256 256 bits, 32 bytes * FNV256 256 bits, 32 bytes
* FNV512 512 bits, 64 bytes * FNV512 512 bits, 64 bytes
* FNV1024 1024 bits, 128 bytes * FNV1024 1024 bits, 128 bytes
*/ */
/* Private stuff used by this implementation of the FNV /* Private stuff used by this implementation of the FNV
* (Fowler, Noll, Vo) non-cryptographic hash function FNV-1a. * (Fowler/Noll/Vo) non-cryptographic hash function FNV-1a.
* External callers don't need to know any of this. */ * External callers don't need to know any of this. */
enum { /* State value bases for context->Computed */ enum { /* State value bases for context->Computed */
FNVinited = 22, FNVinited = 22,
FNVcomputed = 76, FNVcomputed = 76,
FNVemptied = 220, FNVemptied = 220,
FNVclobber = 122 /* known bad value for testing */ FNVclobber = 122 /* known bad value for testing */
}; };
/* Deltas to assure distinct state values for different lengths */ /* Deltas to assure distinct state values for different lengths */
enum { enum {
skipping to change at page 23, line 15 skipping to change at line 1046
FNV256state = 7, FNV256state = 7,
FNV512state = 11, FNV512state = 11,
FNV1024state = 13 FNV1024state = 13
}; };
#endif /* _FNV_PRIVATE_H_ */ #endif /* _FNV_PRIVATE_H_ */
<CODE ENDS> <CODE ENDS>
8.2.1. FNV32 Code 8.2.1. FNV32 Code
The header and C source for 32-bit FNV-1a providing a 32-bit integer The following code is the header and C source for 32-bit FNV-1a
or 4-byte vector hash. providing a 32-bit integer or 4-byte vector hash.
<CODE BEGINS> file "FNV32.h" <CODE BEGINS> file "FNV32.h"
//*************************** FNV32.h ****************************// //*************************** FNV32.h ****************************//
//****************** See RFC NNNN for details ********************// //****************** See RFC 9923 for details. *******************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
#ifndef _FNV32_H_ #ifndef _FNV32_H_
#define _FNV32_H_ #define _FNV32_H_
/* /*
* Description: * Description:
skipping to change at page 23, line 46 skipping to change at line 1077
#include "FNVErrorCodes.h" #include "FNVErrorCodes.h"
#include <stdint.h> #include <stdint.h>
#define FNV32size (32/8) #define FNV32size (32/8)
#define FNV32basis 0x811C9DC5 #define FNV32basis 0x811C9DC5
/* If you do not have the ISO standard stdint.h header file, then /* If you do not have the ISO standard stdint.h header file, then
* you must typedef the following types: * you must typedef the following types:
* *
* type meaning * type meaning
* uint32_t unsigned 32-bit integer * uint32_t unsigned 32-bit integer
* uint8_t unsigned 8-bit integer (i.e., unsigned char) * uint8_t unsigned 8-bit integer (i.e., unsigned char)
*/ */
/* /*
* This structure holds context information for an FNV32 hash * This structure holds context information for an FNV32 hash
*/ */
typedef struct FNV32context_s { typedef struct FNV32context_s {
int Computed; /* state */ int Computed; /* state */
uint32_t Hash; uint32_t Hash;
} FNV32context; } FNV32context;
/* /* Function Prototypes:
* Function Prototypes:
* *
* FNV32string: hash a zero-terminated string not including * FNV32string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV32stringBasis: also takes an offset_basis parameter * FNV32stringBasis: also takes an offset_basis parameter
* *
* FNV32block: hash a specified length byte vector * FNV32block: hash a specified length byte vector
* FNV32blockBasis: also takes an offset_basis parameter * FNV32blockBasis: also takes an offset_basis parameter
* *
* FNV32file: hash the contents of a file * FNV32file: hash the contents of a file
* FNV32fileBasis: also takes an offset_basis parameter * FNV32fileBasis: also takes an offset_basis parameter
skipping to change at page 26, line 19 skipping to change at line 1193
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _FNV32_H_ */ #endif /* _FNV32_H_ */
<CODE ENDS> <CODE ENDS>
<CODE BEGINS> file "FNV32.c" <CODE BEGINS> file "FNV32.c"
//************************** FNV32.c **************************// //************************** FNV32.c **************************//
//**************** See RFC NNNN for details. ******************// //**************** See RFC 9923 for details. ******************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
/* This code implements the FNV (Fowler, Noll, Vo) non-cryptographic /* This code implements the FNV (Fowler/Noll/Vo) non-cryptographic
* hash function FNV-1a for 32-bit hashes. * hash function FNV-1a for 32-bit hashes.
*/ */
#include <stdio.h> #include <stdio.h>
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV32.h" #include "FNV32.h"
/* 32-bit FNV_prime = 2^24 + 2^8 + 0x93 */ /* 32-bit FNV_prime = 2^24 + 2^8 + 0x93 */
#define FNV32prime 0x01000193 #define FNV32prime 0x01000193
/* FNV32 hash a zero-terminated string not including the zero /* FNV32 hash a zero-terminated string not including the zero
*****************************************************************/ *****************************************************************/
int FNV32INTstring ( const char *in, uint32_t * const out ) { int FNV32INTstring ( const char *in, uint32_t * const out ) {
return FNV32INTstringBasis( in, out, FNV32basis ); return FNV32INTstringBasis ( in, out, FNV32basis );
} /* end FNV32INTstring */ } /* end FNV32INTstring */
/* FNV32 hash a zero-terminated string not including the zero /* FNV32 hash a zero-terminated string not including the zero
* with a non-standard basis * with a non-standard basis
*****************************************************************/ *****************************************************************/
int FNV32INTstringBasis ( const char *in, int FNV32INTstringBasis ( const char *in,
uint32_t * const out, uint32_t * const out,
uint32_t basis ) { uint32_t basis ) {
uint8_t ch; uint8_t ch;
skipping to change at page 33, line 40 skipping to change at line 1552
ctx->Computed = FNVemptied+FNV32state; ctx->Computed = FNVemptied+FNV32state;
for ( int i=0; i<FNV32size; ++i ) for ( int i=0; i<FNV32size; ++i )
out[i] = ((uint8_t *)&ctx->Hash)[i]; out[i] = ((uint8_t *)&ctx->Hash)[i];
ctx->Hash = 0; ctx->Hash = 0;
return fnvSuccess; return fnvSuccess;
} /* end FNV32result */ } /* end FNV32result */
<CODE ENDS> <CODE ENDS>
8.2.2. FNV64 Code 8.2.2. FNV64 Code
The header and C source for 64-bit FNV-1a. Provides an 8-byte vector The following code is the header and C source for 64-bit FNV-1a
or, optionally, if 64-bit integers are supported, a 64-bit integer providing an 8-byte vector or, optionally, if 64-bit integers are
hash. supported, a 64-bit integer hash.
<CODE BEGINS> file "FNV64.h" <CODE BEGINS> file "FNV64.h"
//*************************** FNV64.h ****************************// //*************************** FNV64.h ****************************//
//***************** See RFC NNNN for details. ********************// //***************** See RFC 9923 for details. ********************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
#ifndef _FNV64_H_ #ifndef _FNV64_H_
#define _FNV64_H_ #define _FNV64_H_
/* Description: /*
* Description:
* This file provides headers for the 64-bit version of * This file provides headers for the 64-bit version of
* the FNV-1a non-cryptographic hash algorithm. * the FNV-1a non-cryptographic hash algorithm.
*/ */
#include "FNVconfig.h" #include "FNVconfig.h"
#include "FNVErrorCodes.h" #include "FNVErrorCodes.h"
#include <stdint.h> #include <stdint.h>
#define FNV64size (64/8) #define FNV64size (64/8)
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
#define FNV64basis 0xCBF29CE484222325 #define FNV64basis 0xCBF29CE484222325
#endif #endif
/* If you do not have the ISO standard stdint.h header file, then /* If you do not have the ISO standard stdint.h header file, then
* you must typedef the following types: * you must typedef the following types:
* *
* type meaning * type meaning
* uint64_t unsigned 64-bit integer (ifdef FNV_64bitIntegers) * uint64_t unsigned 64-bit integer (ifdef FNV_64bitIntegers)
* uint32_t unsigned 32-bit integer * uint32_t unsigned 32-bit integer
* uint16_t unsigned 16-bit integer * uint16_t unsigned 16-bit integer
* uint8_t unsigned 8-bit integer (i.e., unsigned char) * uint8_t unsigned 8-bit integer (i.e., unsigned char)
*/ */
/* /*
* This structure holds context information for an FNV64 hash * This structure holds context information for an FNV64 hash
*/ */
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
/* version if 64-bit integers supported */ /* version if 64-bit integers supported */
typedef struct FNV64context_s { typedef struct FNV64context_s {
int Computed; /* state */ int Computed; /* state */
uint64_t Hash; uint64_t Hash;
skipping to change at page 35, line 6 skipping to change at line 1615
int Computed; /* state */ int Computed; /* state */
uint16_t Hash[FNV64size/2]; uint16_t Hash[FNV64size/2];
} FNV64context; } FNV64context;
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
/* Function Prototypes: /* Function Prototypes:
* *
* FNV64string: hash a zero-terminated string not including * FNV64string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV164stringBasis: also takes an offset_basis parameter * FNV64stringBasis: also takes an offset_basis parameter
* *
* FNV64block: hash a specified length byte vector * FNV64block: hash a specified length byte vector
* FNV64blockBasis: also takes an offset_basis parameter * FNV64blockBasis: also takes an offset_basis parameter
* *
* FNV64file: hash the contents of a file * FNV64file: hash the contents of a file
* FNV128fileBasis: also takes an offset_basis parameter * FNV128fileBasis: also takes an offset_basis parameter
* *
* FNV64init: initializes an FNV64 context * FNV64init: initializes an FNV64 context
* FNV64initBasis: initializes an FNV64 context with a * FNV64initBasis: initializes an FNV64 context with a
* provided 8-byte vector basis * provided 8-byte vector basis
skipping to change at page 37, line 4 skipping to change at line 1709
extern int FNV64INTfile ( const char * fname, extern int FNV64INTfile ( const char * fname,
uint64_t * const out ); uint64_t * const out );
extern int FNV64INTfileBasis ( const char * fname, extern int FNV64INTfileBasis ( const char * fname,
uint64_t * const out, uint64_t * const out,
uint64_t basis ); uint64_t basis );
extern int FNV64INTinitBasis ( FNV64context * const, extern int FNV64INTinitBasis ( FNV64context * const,
uint64_t basis ); uint64_t basis );
extern int FNV64INTresult ( FNV64context * const, extern int FNV64INTresult ( FNV64context * const,
uint64_t * const out ); uint64_t * const out );
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _FNV64_H_ */ #endif /* _FNV64_H_ */
<CODE ENDS> <CODE ENDS>
<CODE BEGINS> file "FNV64.c" <CODE BEGINS> file "FNV64.c"
//*************************** FNV64.c ****************************// //*************************** FNV64.c ****************************//
//****************** See RFC NNNN for details ********************// //****************** See RFC 9923 for details. *******************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
/* This file implements the FNV (Fowler, Noll, Vo) non-cryptographic /* This file implements the FNV (Fowler/Noll/Vo) non-cryptographic
* hash function FNV-1a for 64-bit hashes. * hash function FNV-1a for 64-bit hashes.
*/ */
#include <stdio.h> #include <stdio.h>
#include "FNVconfig.h" #include "FNVconfig.h"
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV64.h" #include "FNV64.h"
//***************************************************************** //*****************************************************************
skipping to change at page 39, line 21 skipping to change at line 1823
//***************************************************************** //*****************************************************************
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
/* 64-bit FNV_prime = 2^40 + 2^8 + 0xb3 */ /* 64-bit FNV_prime = 2^40 + 2^8 + 0xb3 */
#define FNV64prime 0x00000100000001B3 #define FNV64prime 0x00000100000001B3
/* FNV64 hash a zero-terminated string not including the zero /* FNV64 hash a zero-terminated string not including the zero
* to a 64-bit integer (64-bit) * to a 64-bit integer (64-bit)
******************************************************************/ ******************************************************************/
int FNV64INTstring ( const char *in, uint64_t * const out ) { int FNV64INTstring ( const char *in, uint64_t * const out ) {
return FNV64INTstringBasis (in, out, FNV64basis ); return FNV64INTstringBasis ( in, out, FNV64basis );
} /* end FNV64INTstring */ } /* end FNV64INTstring */
/* FNV64 hash a zero-terminated string not including the zero /* FNV64 hash a zero-terminated string not including the zero
* to a 64-bit integer (64-bit) with a non-standard basis * to a 64-bit integer (64-bit) with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV64INTstringBasis ( const char *in, int FNV64INTstringBasis ( const char *in,
uint64_t * const out, uint64_t * const out,
uint64_t basis ) { uint64_t basis ) {
uint64_t temp; uint64_t temp;
uint8_t ch; uint8_t ch;
skipping to change at page 42, line 4 skipping to change at line 1950
if ( !in || !out || !basis ) if ( !in || !out || !basis )
return fnvNull; /* Null input/out pointer */ return fnvNull; /* Null input/out pointer */
if ( length < 0 ) if ( length < 0 )
return fnvBadParam; return fnvBadParam;
temp = basis[7]; temp = basis[7];
for ( i = FNV64size-2; i>=0; --i ) for ( i = FNV64size-2; i>=0; --i )
temp = (temp<<8) + basis[i]; temp = (temp<<8) + basis[i];
for (; length > 0; length-- ) for (; length > 0; length-- )
temp = FNV64prime * ( temp ^ *in++ ); temp = FNV64prime * ( temp ^ *in++ );
for ( i=0; i<FNV64size; ++i ) for ( i=0; i<FNV64size; ++i )
out[i] = ((uint8_t *)&temp)[i]; out[i] = ((uint8_t *)&temp)[i];
return fnvSuccess; return fnvSuccess;
} /* end FNV64blockBasis */ } /* end FNV64blockBasis */
//***************************************************************** //*****************************************************************
// Set of init, input, and output functions below // Set of init, input, and output functions below
// to incrementally compute FNV64 // to incrementally compute FNV64
//***************************************************************** //*****************************************************************
/* initialize context (64-bit) /* initialize context (64-bit)
******************************************************************/ ******************************************************************/
int FNV64init( FNV64context * const ctx ) { int FNV64init( FNV64context * const ctx ) {
return FNV64INTinitBasis ( ctx, FNV64basis ); return FNV64INTinitBasis ( ctx, FNV64basis );
} /* end FNV64init */ } /* end FNV64init */
/* initialize context with a provided 64-bit integer basis (64-bit) /* initialize context with a provided 64-bit integer basis (64-bit)
******************************************************************/ ******************************************************************/
skipping to change at page 43, line 4 skipping to change at line 1998
/* hash in a counted block (64-bit) /* hash in a counted block (64-bit)
******************************************************************/ ******************************************************************/
int FNV64blockin( FNV64context * const ctx, int FNV64blockin( FNV64context * const ctx,
const void *vin, const void *vin,
long int length ) { long int length ) {
const uint8_t *in = (const uint8_t*)vin; const uint8_t *in = (const uint8_t*)vin;
uint64_t temp; uint64_t temp;
if ( !ctx || !in ) if ( !ctx || !in )
return fnvNull; return fnvNull;
if ( length < 0 ) if ( length < 0 )
return fnvBadParam; return fnvBadParam;
switch ( ctx->Computed ) { switch ( ctx->Computed ) {
case FNVinited+FNV64state: case FNVinited+FNV64state:
ctx->Computed = FNVcomputed+FNV64state; ctx->Computed = FNVcomputed+FNV64state;
break; break;
case FNVcomputed+FNV64state: case FNVcomputed+FNV64state:
break; break;
default: default:
return fnvStateError; return fnvStateError;
} }
for ( temp = ctx->Hash; length > 0; length-- ) for ( temp = ctx->Hash; length > 0; length-- )
temp = FNV64prime * ( temp ^ *in++ ); temp = FNV64prime * ( temp ^ *in++ );
ctx->Hash = temp; ctx->Hash = temp;
return fnvSuccess; return fnvSuccess;
} /* end FNV64blockin */ } /* end FNV64blockin */
/* hash in a zero-terminated string not including the zero (64-bit) /* hash in a zero-terminated string not including the zero (64-bit)
******************************************************************/ ******************************************************************/
int FNV64stringin ( FNV64context * const ctx, const char *in ) { int FNV64stringin ( FNV64context * const ctx, const char *in ) {
uint64_t temp; uint64_t temp;
uint8_t ch; uint8_t ch;
if ( !ctx || !in ) if ( !ctx || !in )
return fnvNull; return fnvNull;
switch ( ctx->Computed ) { switch ( ctx->Computed ) {
case FNVinited+FNV64state: case FNVinited+FNV64state:
ctx->Computed = FNVcomputed+FNV64state; ctx->Computed = FNVcomputed+FNV64state;
skipping to change at page 43, line 46 skipping to change at line 2039
default: default:
return fnvStateError; return fnvStateError;
} }
temp = ctx->Hash; temp = ctx->Hash;
while ( (ch = (uint8_t)*in++) ) while ( (ch = (uint8_t)*in++) )
temp = FNV64prime * ( temp ^ ch ); temp = FNV64prime * ( temp ^ ch );
ctx->Hash = temp; ctx->Hash = temp;
return fnvSuccess; return fnvSuccess;
} /* end FNV64stringin */ } /* end FNV64stringin */
/* return hash as 64-bit int (64-bit) /* return hash as 64-bit int (64-bit)
******************************************************************/ ******************************************************************/
int FNV64INTresult ( FNV64context * const ctx, int FNV64INTresult ( FNV64context * const ctx,
uint64_t * const out ) { uint64_t * const out ) {
if ( !ctx || !out ) if ( !ctx || !out )
return fnvNull; return fnvNull;
if ( ctx->Computed != FNVcomputed+FNV64state ) if ( ctx->Computed != FNVcomputed+FNV64state )
return fnvStateError; return fnvStateError;
ctx->Computed = FNVemptied+FNV64state; ctx->Computed = FNVemptied+FNV64state;
*out = ctx->Hash; *out = ctx->Hash;
ctx->Hash = 0; ctx->Hash = 0;
return fnvSuccess; return fnvSuccess;
} /* end FNV64INTresult */ } /* end FNV64INTresult */
/* return hash as 8-byte vector (64-bit) /* return hash as 8-byte vector (64-bit)
******************************************************************/ ******************************************************************/
int FNV64result ( FNV64context * const ctx, int FNV64result ( FNV64context * const ctx,
uint8_t out[FNV64size] ) { uint8_t out[FNV64size] ) {
if ( !ctx || !out ) if ( !ctx || !out )
return fnvNull; return fnvNull;
if ( ctx->Computed != FNVcomputed+FNV64state ) if ( ctx->Computed != FNVcomputed+FNV64state )
return fnvStateError; return fnvStateError;
ctx->Computed = FNVemptied+FNV64state; ctx->Computed = FNVemptied+FNV64state;
for ( int i=0; i<FNV64size; ++i ) for ( int i=0; i<FNV64size; ++i )
out[i] = ((uint8_t *)&ctx->Hash)[i]; out[i] = ((uint8_t *)&ctx->Hash)[i];
skipping to change at page 45, line 29 skipping to change at line 2119
/* 64-bit FNV_prime = 2^40 + 2^8 + 0xb3 */ /* 64-bit FNV_prime = 2^40 + 2^8 + 0xb3 */
/* #define FNV64prime 0x00000100000001B3 */ /* #define FNV64prime 0x00000100000001B3 */
#define FNV64primeX 0x01B3 #define FNV64primeX 0x01B3
#define FNV64shift 8 #define FNV64shift 8
/* FNV64 hash a zero-terminated string not including the zero /* FNV64 hash a zero-terminated string not including the zero
******************************************************************/ ******************************************************************/
int FNV64string ( const char *in, uint8_t out[FNV64size] ) { int FNV64string ( const char *in, uint8_t out[FNV64size] ) {
FNV64context ctx; FNV64context ctx;
int error; int error;
if ( (error = FNV64init (&ctx)) ) if ( (error = FNV64init (&ctx)) )
return error; return error;
if ( (error = FNV64stringin (&ctx, in)) ) if ( (error = FNV64stringin (&ctx, in)) )
return error; return error;
return FNV64result (&ctx, out); return FNV64result (&ctx, out);
} /* end FNV64string */ } /* end FNV64string */
/* FNV64 hash a zero-terminated string not including the zero /* FNV64 hash a zero-terminated string not including the zero
* with a non-standard offset_basis * with a non-standard offset_basis
******************************************************************/ ******************************************************************/
int FNV64stringBasis ( const char *in, int FNV64stringBasis ( const char *in,
uint8_t out[FNV64size], uint8_t out[FNV64size],
const uint8_t basis[FNV64size] ) { const uint8_t basis[FNV64size] ) {
FNV64context ctx; FNV64context ctx;
int error; int error;
if ( (error = FNV64initBasis (&ctx, basis)) ) if ( (error = FNV64initBasis (&ctx, basis)) )
return error; return error;
if ( (error = FNV64stringin (&ctx, in)) ) if ( (error = FNV64stringin (&ctx, in)) )
return error; return error;
return FNV64result (&ctx, out); return FNV64result (&ctx, out);
} /* end FNV64stringBasis */ } /* end FNV64stringBasis */
/* FNV64 hash a counted block /* FNV64 hash a counted block
******************************************************************/ ******************************************************************/
int FNV64block ( const void *vin, int FNV64block ( const void *vin,
long int length, long int length,
uint8_t out[FNV64size] ) { uint8_t out[FNV64size] ) {
FNV64context ctx; FNV64context ctx;
int error; int error;
skipping to change at page 47, line 7 skipping to change at line 2193
if ( !ctx ) if ( !ctx )
return fnvNull; return fnvNull;
ctx->Hash[0] = 0xCBF2; ctx->Hash[0] = 0xCBF2;
ctx->Hash[1] = 0x9CE4; ctx->Hash[1] = 0x9CE4;
ctx->Hash[2] = 0x8422; ctx->Hash[2] = 0x8422;
ctx->Hash[3] = 0x2325; ctx->Hash[3] = 0x2325;
ctx->Computed = FNVinited+FNV64state; ctx->Computed = FNVinited+FNV64state;
return fnvSuccess; return fnvSuccess;
} /* end FNV64init */ } /* end FNV64init */
/* initialize context with a non-standard basis (32-bit) /* initialize context with a non-standard basis (32-bit)
******************************************************************/ ******************************************************************/
int FNV64initBasis ( FNV64context * const ctx, int FNV64initBasis ( FNV64context * const ctx,
const uint8_t basis[FNV64size] ) { const uint8_t basis[FNV64size] ) {
if ( !ctx || !basis ) if ( !ctx || !basis )
return fnvNull; return fnvNull;
for ( int i=0; i < FNV64size/2; ++i ) { for ( int i=0; i < FNV64size/2; ++i ) {
uint32_t temp = *basis++; uint32_t temp = *basis++;
ctx->Hash[i] = ( temp<<8 ) + *basis++; ctx->Hash[i] = ( temp<<8 ) + *basis++;
} }
ctx->Computed = FNVinited+FNV64state; ctx->Computed = FNVinited+FNV64state;
skipping to change at page 49, line 34 skipping to change at line 2316
} /* end FNV64result */ } /* end FNV64result */
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
//***************************************************************** //*****************************************************************
// END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//***************************************************************** //*****************************************************************
<CODE ENDS> <CODE ENDS>
8.2.3. FNV128 Code 8.2.3. FNV128 Code
The header and C source for 128-bit FNV-1a providing a byte vector The following code is the header and C source for 128-bit FNV-1a
hash. providing a byte vector hash.
<CODE BEGINS> file "FNV128.h" <CODE BEGINS> file "FNV128.h"
//************************** FNV128.h ************************// //************************** FNV128.h ************************//
//*************** See RFC NNNN for details. ******************// //*************** See RFC 9923 for details. ******************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
#ifndef _FNV128_H_ #ifndef _FNV128_H_
#define _FNV128_H_ #define _FNV128_H_
/* /*
* Description: * Description:
skipping to change at page 52, line 14 skipping to change at line 2439
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _FNV128_H_ */ #endif /* _FNV128_H_ */
<CODE ENDS> <CODE ENDS>
<CODE BEGINS> file "FNV128.c" <CODE BEGINS> file "FNV128.c"
//**************************** FNV128.c **************************// //**************************** FNV128.c **************************//
//******************* See RFC NNNN for details *******************// //******************* See RFC 9923 for details. ******************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
/* This file implements the FNV (Fowler, Noll, Vo) non-cryptographic /* This file implements the FNV (Fowler/Noll/Vo) non-cryptographic
* hash function FNV-1a for 128-bit hashes. * hash function FNV-1a for 128-bit hashes.
*/ */
#include <stdio.h> #include <stdio.h>
#include "FNVconfig.h" #include "FNVconfig.h"
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV128.h" #include "FNV128.h"
//***************************************************************** //*****************************************************************
// COMMON CODE FOR 64- AND 32-BIT INTEGER MODES // COMMON CODE FOR 64- AND 32-BIT INTEGER MODES
//***************************************************************** //*****************************************************************
/* FNV128 hash a zero-terminated string not including the zero /* FNV128 hash a zero-terminated string not including the zero
******************************************************************/ ******************************************************************/
int FNV128string ( const char *in, uint8_t out[FNV128size] ) { int FNV128string ( const char *in, uint8_t out[FNV128size] ) {
FNV128context ctx; FNV128context ctx;
int error; int error;
if ( (error = FNV128init ( &ctx )) ) if ( (error = FNV128init ( &ctx )) )
return error; return error;
skipping to change at page 53, line 18 skipping to change at line 2492
if ( (error = FNV128stringin ( &ctx, in )) ) if ( (error = FNV128stringin ( &ctx, in )) )
return error; return error;
return FNV128result ( &ctx, out ); return FNV128result ( &ctx, out );
} /* end FNV128stringBasis */ } /* end FNV128stringBasis */
/* FNV128 hash a counted block (64/32-bit) /* FNV128 hash a counted block (64/32-bit)
******************************************************************/ ******************************************************************/
int FNV128block ( const void *vin, int FNV128block ( const void *vin,
long int length, long int length,
uint8_t out[FNV128size] ) { uint8_t out[FNV128size] ) {
FNV128context ctx; FNV128context ctx;
int error; int error;
if ( (error = FNV128init ( &ctx )) ) if ( (error = FNV128init ( &ctx )) )
return error; return error;
if ( (error = FNV128blockin ( &ctx, vin, length )) ) if ( (error = FNV128blockin ( &ctx, vin, length )) )
return error; return error;
return FNV128result ( &ctx, out ); return FNV128result ( &ctx, out );
} /* end FNV128block */ } /* end FNV128block */
/* FNV128 hash a counted block (64/32-bit) /* FNV128 hash a counted block (64/32-bit)
skipping to change at page 55, line 19 skipping to change at line 2589
fclose(fp); fclose(fp);
return error; return error;
} }
error = ferror(fp); error = ferror(fp);
fclose(fp); fclose(fp);
if (error) return fnvBadParam; if (error) return fnvBadParam;
return fnvSuccess; return fnvSuccess;
} /* end FNV128filein */ } /* end FNV128filein */
//***************************************************************** //*****************************************************************
// START VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC // START VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC
//***************************************************************** //*****************************************************************
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
/* 128-bit FNV_prime = 2^88 + 2^8 + 0x3b */ /* 128-bit FNV_prime = 2^88 + 2^8 + 0x3b */
/* 0x00000000 01000000 00000000 0000013B */ /* 0x00000000 01000000 00000000 0000013B */
#define FNV128primeX 0x013B #define FNV128primeX 0x013B
#define FNV128shift 24 #define FNV128shift 24
//***************************************************************** //*****************************************************************
// Set of init, input, and output functions below // Set of init, input, and output functions below
skipping to change at page 57, line 52 skipping to change at line 2717
for ( i = 3; i > 0; --i ) { for ( i = 3; i > 0; --i ) {
temp[i-1] += temp[i] >> 32; temp[i-1] += temp[i] >> 32;
temp[i] &= 0xFFFFFFFF; temp[i] &= 0xFFFFFFFF;
} }
} }
for ( i=0; i<FNV128size/4; ++i ) for ( i=0; i<FNV128size/4; ++i )
ctx->Hash[i] = (uint32_t)temp[i]; ctx->Hash[i] = (uint32_t)temp[i];
return fnvSuccess; return fnvSuccess;
} /* end FNV128stringin */ } /* end FNV128stringin */
/* return hash as 16-byte vector (64-bit) /* return hash as 16-byte vector (64-bit)
******************************************************************/ ******************************************************************/
int FNV128result ( FNV128context * const ctx, int FNV128result ( FNV128context * const ctx,
uint8_t out[FNV128size] ) { uint8_t out[FNV128size] ) {
if ( !ctx || !out ) if ( !ctx || !out )
return fnvNull; return fnvNull;
if ( ctx->Computed != FNVcomputed+FNV128state ) if ( ctx->Computed != FNVcomputed+FNV128state )
return fnvStateError; return fnvStateError;
for ( int i=0; i<FNV128size/4; ++i ) { for ( int i=0; i<FNV128size/4; ++i ) {
out[4*i] = ctx->Hash[i] >> 24; out[4*i] = ctx->Hash[i] >> 24;
out[4*i+1] = ctx->Hash[i] >> 16; out[4*i+1] = ctx->Hash[i] >> 16;
skipping to change at page 61, line 28 skipping to change at line 2886
out[2*i] = ctx->Hash[i] >> 8; out[2*i] = ctx->Hash[i] >> 8;
out[2*i+1] = ctx->Hash[i]; out[2*i+1] = ctx->Hash[i];
ctx -> Hash[i] = 0; ctx -> Hash[i] = 0;
} }
ctx->Computed = FNVemptied+FNV128state; ctx->Computed = FNVemptied+FNV128state;
return fnvSuccess; return fnvSuccess;
} /* end FNV128result */ } /* end FNV128result */
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
//****************************************************************** //******************************************************************
// END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//****************************************************************** //******************************************************************
<CODE ENDS> <CODE ENDS>
8.2.4. FNV256 Code 8.2.4. FNV256 Code
The header and C source for 256-bit FNV-1a providing a byte vector The following code is the header and C source for 256-bit FNV-1a
hash. providing a byte vector hash.
<CODE BEGINS> file "FNV256.h" <CODE BEGINS> file "FNV256.h"
//************************* FNV256.h ***********************// //************************* FNV256.h ***********************//
//************** See RFC NNNN for details. *****************// //************** See RFC 9923 for details. *****************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
#ifndef _FNV256_H_ #ifndef _FNV256_H_
#define _FNV256_H_ #define _FNV256_H_
/* /*
* Description: * Description:
skipping to change at page 62, line 46 skipping to change at line 2951
int Computed; /* state */ int Computed; /* state */
uint16_t Hash[FNV256size/2]; uint16_t Hash[FNV256size/2];
} FNV256context; } FNV256context;
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
/* Function Prototypes: /* Function Prototypes:
* *
* FNV256string: hash a zero-terminated string not including * FNV256string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV246stgringBasis: also takes an offset_basis parameter * FNV256stringBasis: also takes an offset_basis parameter
* *
* FNV256block: hash a specified length byte vector * FNV256block: hash a specified length byte vector
* FNV256blockBasis: also takes an offset_basis parameter * FNV256blockBasis: also takes an offset_basis parameter
* *
* FNV256file: hash the contents of a file * FNV256file: hash the contents of a file
* FNV256fileBasis: also takes an offset_basis parameter * FNV256fileBasis: also takes an offset_basis parameter
* *
* FNV256init: initializes an FNV256 context * FNV256init: initializes an FNV256 context
* FNV256initBasis: initializes an FNV256 context with a * FNV256initBasis: initializes an FNV256 context with a
* provided 32-byte vector basis * provided 32-byte vector basis
* FNV256blockin: hash in a specified length byte vector * FNV256blockin: hash in a specified length byte vector
* FNV256stringin: hash in a zero-terminated string not * FNV256stringin: hash in a zero-terminated string not
* including the terminating zero * including the terminating zero
* FNV256filein: hash in the contents of a file * FNV256filein: hash in the contents of a file
* FNV256result: returns the hash value * FNV256result: returns the hash value
* *
* Hash is returned as an array of 8-bit unsigned integers * Hash is returned as an array of 8-bit unsigned integers
*/ */
skipping to change at page 64, line 14 skipping to change at line 3015
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _FNV256_H_ */ #endif /* _FNV256_H_ */
<CODE ENDS> <CODE ENDS>
<CODE BEGINS> file "FNV256.c" <CODE BEGINS> file "FNV256.c"
//**************************** FNV256.c **************************// //**************************** FNV256.c **************************//
//******************* See RFC NNNN for details *******************// //******************* See RFC 9923 for details. ******************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
/* This file implements the FNV (Fowler, Noll, Vo) non-cryptographic /* This file implements the FNV (Fowler/Noll/Vo) non-cryptographic
* hash function FNV-1a for 256-bit hashes. * hash function FNV-1a for 256-bit hashes.
*/ */
#include <stdio.h> #include <stdio.h>
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV256.h" #include "FNV256.h"
//***************************************************************** //*****************************************************************
// COMMON CODE FOR 64- AND 32-BIT INTEGER MODES // COMMON CODE FOR 64- AND 32-BIT INTEGER MODES
skipping to change at page 67, line 4 skipping to change at line 3150
case FNVinited+FNV256state: case FNVinited+FNV256state:
e256Context->Computed = FNVcomputed+FNV256state; e256Context->Computed = FNVcomputed+FNV256state;
break; break;
case FNVcomputed+FNV256state: case FNVcomputed+FNV256state:
break; break;
default: default:
return fnvStateError; return fnvStateError;
} }
if ( ( fp = fopen ( fname, "rb") ) == NULL ) if ( ( fp = fopen ( fname, "rb") ) == NULL )
return fnvBadParam; return fnvBadParam;
if ( (error = FNV256blockin ( e256Context, "", 0)) ) { if ( (error = FNV256blockin ( e256Context, "", 0)) ) {
fclose(fp); fclose(fp);
return error; return error;
} }
while ( ( i = fread ( buf, 1, sizeof(buf), fp ) ) > 0 ) while ( ( i = fread ( buf, 1, sizeof(buf), fp ) ) > 0 )
if ( (error = FNV256blockin ( e256Context, buf, i)) ) { if ( (error = FNV256blockin ( e256Context, buf, i)) ) {
fclose(fp); fclose(fp);
return error; return error;
} }
error = ferror(fp); error = ferror(fp);
fclose(fp); fclose(fp);
if (error) return fnvBadParam; if (error) return fnvBadParam;
return fnvSuccess; return fnvSuccess;
} /* end FNV256filein */ } /* end FNV256filein */
//***************************************************************** //*****************************************************************
// START VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC // START VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC
//***************************************************************** //*****************************************************************
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
/* 256-bit FNV_prime = 2^168 + 2^8 + 0x63 */ /* 256-bit FNV_prime = 2^168 + 2^8 + 0x63 */
/* 0x0000000000000000 0000010000000000 /* 0x0000000000000000 0000010000000000
0000000000000000 0000000000000163 */ 0000000000000000 0000000000000163 */
#define FNV256primeX 0x0163 #define FNV256primeX 0x0163
#define FNV256shift 8 #define FNV256shift 8
//***************************************************************** //*****************************************************************
skipping to change at page 70, line 28 skipping to change at line 3317
out[4*i+1] = ctx->Hash[i] >> 16; out[4*i+1] = ctx->Hash[i] >> 16;
out[4*i+2] = ctx->Hash[i] >> 8; out[4*i+2] = ctx->Hash[i] >> 8;
out[4*i+3] = ctx->Hash[i]; out[4*i+3] = ctx->Hash[i];
ctx -> Hash[i] = 0; ctx -> Hash[i] = 0;
} }
ctx->Computed = FNVemptied+FNV256state; ctx->Computed = FNVemptied+FNV256state;
return fnvSuccess; return fnvSuccess;
} /* end FNV256result */ } /* end FNV256result */
//**************************************************************** //****************************************************************
// END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC // END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC
//**************************************************************** //****************************************************************
#else /* FNV_64bitIntegers */ #else /* FNV_64bitIntegers */
//**************************************************************** //****************************************************************
// START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//**************************************************************** //****************************************************************
/* version for when you only have 32-bit arithmetic /* version for when you only have 32-bit arithmetic
*****************************************************************/ *****************************************************************/
/* 256-bit FNV_prime = 2^168 + 2^8 + 0x63 */ /* 256-bit FNV_prime = 2^168 + 2^8 + 0x63 */
/* 0x00000000 00000000 00000100 00000000 /* 0x00000000 00000000 00000100 00000000
00000000 00000000 00000000 00000163 */ 00000000 00000000 00000000 00000163 */
#define FNV256primeX 0x0163 #define FNV256primeX 0x0163
#define FNV256shift 8 #define FNV256shift 8
skipping to change at page 71, line 4 skipping to change at line 3342
//**************************************************************** //****************************************************************
// Set of init, input, and output functions below // Set of init, input, and output functions below
// to incrementally compute FNV256 // to incrementally compute FNV256
//**************************************************************** //****************************************************************
/* initialize context (32-bit) /* initialize context (32-bit)
*****************************************************************/ *****************************************************************/
int FNV256init ( FNV256context * const ctx ) { int FNV256init ( FNV256context * const ctx ) {
const uint16_t FNV256basis[FNV256size/2] = { const uint16_t FNV256basis[FNV256size/2] = {
0xDD26, 0x8DBC, 0xAAC5, 0x5036, 0x2D98, 0xC384, 0xC4E5, 0x76CC, 0xDD26, 0x8DBC, 0xAAC5, 0x5036, 0x2D98, 0xC384, 0xC4E5, 0x76CC,
0xC8B1, 0x5368, 0x47B6, 0xBBB3, 0x1023, 0xB4C8, 0xCAEE, 0x0535 }; 0xC8B1, 0x5368, 0x47B6, 0xBBB3, 0x1023, 0xB4C8, 0xCAEE, 0x0535 };
if ( !ctx ) if ( !ctx )
return fnvNull; return fnvNull;
for ( int i=0; i<FNV256size/2; ++i ) for ( int i=0; i<FNV256size/2; ++i )
ctx->Hash[i] = FNV256basis[i]; ctx->Hash[i] = FNV256basis[i];
ctx->Computed = FNVinited+FNV256state; ctx->Computed = FNVinited+FNV256state;
return fnvSuccess; return fnvSuccess;
} /* end FNV256init */ } /* end FNV256init */
/* initialize context with a provided 32-byte vector basis (32-bit) /* initialize context with a provided 32-byte vector basis (32-bit)
*****************************************************************/ ******************************************************************/
int FNV256initBasis ( FNV256context * const ctx, int FNV256initBasis ( FNV256context * const ctx,
const uint8_t basis[FNV256size] ) { const uint8_t basis[FNV256size] ) {
if ( !ctx || !basis ) if ( !ctx || !basis )
return fnvNull; return fnvNull;
for ( int i=0; i < FNV256size/2; ++i ) { for ( int i=0; i < FNV256size/2; ++i ) {
uint32_t temp = *basis++; uint32_t temp = *basis++;
ctx->Hash[i] = ( temp<<8 ) + (*basis++); ctx->Hash[i] = ( temp<<8 ) + (*basis++);
} }
ctx->Computed = FNVinited+FNV256state; ctx->Computed = FNVinited+FNV256state;
return fnvSuccess; return fnvSuccess;
skipping to change at page 72, line 26 skipping to change at line 3412
temp[i-1] += temp[i] >> 16; temp[i-1] += temp[i] >> 16;
temp[i] &= 0xFFFF; temp[i] &= 0xFFFF;
} }
} }
for ( i=0; i<FNV256size/2; ++i ) for ( i=0; i<FNV256size/2; ++i )
ctx->Hash[i] = temp[i]; ctx->Hash[i] = temp[i];
return fnvSuccess; return fnvSuccess;
} /* end FNV256blockin */ } /* end FNV256blockin */
/* hash in a zero-terminated string not including the zero (32-bit) /* hash in a zero-terminated string not including the zero (32-bit)
*****************************************************************/ ******************************************************************/
int FNV256stringin ( FNV256context * const ctx, const char *in ) { int FNV256stringin ( FNV256context * const ctx, const char *in ) {
uint32_t temp[FNV256size/2]; uint32_t temp[FNV256size/2];
uint32_t temp2[6]; uint32_t temp2[6];
int i; int i;
uint8_t ch; uint8_t ch;
if ( !ctx || !in ) if ( !ctx || !in )
return fnvNull; return fnvNull;
switch ( ctx->Computed ) { switch ( ctx->Computed ) {
case FNVinited+FNV256state: case FNVinited+FNV256state:
skipping to change at page 73, line 36 skipping to change at line 3470
out[2*i] = ctx->Hash[i] >> 8; out[2*i] = ctx->Hash[i] >> 8;
out[2*i+1] = ctx->Hash[i]; out[2*i+1] = ctx->Hash[i];
ctx->Hash[i] = 0; ctx->Hash[i] = 0;
} }
ctx->Computed = FNVemptied+FNV256state; ctx->Computed = FNVemptied+FNV256state;
return fnvSuccess; return fnvSuccess;
} /* end FNV256result */ } /* end FNV256result */
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
//**************************************************************** //****************************************************************
// END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//**************************************************************** //****************************************************************
<CODE ENDS> <CODE ENDS>
8.2.5. FNV512 Code 8.2.5. FNV512 Code
The header and C source for 512-bit FNV-1a providing a byte vector The following code is the header and C source for 512-bit FNV-1a
hash. providing a byte vector hash.
<CODE BEGINS> file "FNV512.h" <CODE BEGINS> file "FNV512.h"
//************************* FNV512.h ***********************// //************************* FNV512.h ***********************//
//************** See RFC NNNN for details. *****************// //************** See RFC 9923 for details. *****************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
#ifndef _FNV512_H_ #ifndef _FNV512_H_
#define _FNV512_H_ #define _FNV512_H_
/* /*
* Description: * Description:
skipping to change at page 74, line 52 skipping to change at line 3534
typedef struct FNV512context_s { typedef struct FNV512context_s {
int Computed; /* state */ int Computed; /* state */
uint16_t Hash[FNV512size/2]; uint16_t Hash[FNV512size/2];
} FNV512context; } FNV512context;
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
/* Function Prototypes: /* Function Prototypes:
* *
* FNV512string: hash a zero-terminated string not including * FNV512string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV512stringBasis: also takes an offset_basis parameter * FNV512stringBasis: also takes an offset_basis parameter
* *
* FNV512block: hash a specified length byte vector * FNV512block: hash a specified length byte vector
* FNV512blockBasis: also takes an offset_basis parameter * FNV512blockBasis: also takes an offset_basis parameter
* *
* FNV512file: hash the contents of a file * FNV512file: hash the contents of a file
* FNV512fileBasis: also takes an offset_basis parameter * FNV512fileBasis: also takes an offset_basis parameter
* *
* FNV512init: initializes an FNV1024 context * FNV512init: initializes an FNV1024 context
* FNV512initBasis: initializes an FNV1024 context with a * FNV512initBasis: initializes an FNV1024 context with a
* provided 128-byte vector basis * provided 128-byte vector basis
* FNV512blockin: hash in a specified length byte vector * FNV512blockin: hash in a specified length byte vector
* FNV512stringin: hash in a zero-terminated string not * FNV512stringin: hash in a zero-terminated string not
* including the terminating zero * including the terminating zero
* FMNV512filein: hash in the contents of a file * FNV512filein: hash in the contents of a file
* FNV512result: returns the hash value * FNV512result: returns the hash value
* *
* Hash is returned as an array of 8-bit unsigned integers * Hash is returned as an array of 8-bit unsigned integers
*/ */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* FNV512 */ /* FNV512 */
skipping to change at page 76, line 4 skipping to change at line 3583
uint8_t out[FNV512size] ); uint8_t out[FNV512size] );
extern int FNV512fileBasis ( const char *fname, extern int FNV512fileBasis ( const char *fname,
uint8_t out[FNV512size], uint8_t out[FNV512size],
const uint8_t basis[FNV512size] ); const uint8_t basis[FNV512size] );
extern int FNV512init ( FNV512context * const ); extern int FNV512init ( FNV512context * const );
extern int FNV512initBasis ( FNV512context * const, extern int FNV512initBasis ( FNV512context * const,
const uint8_t basis[FNV512size] ); const uint8_t basis[FNV512size] );
extern int FNV512blockin ( FNV512context * const, extern int FNV512blockin ( FNV512context * const,
const void *vin, const void *vin,
long int length ); long int length );
extern int FNV512stringin ( FNV512context * const, extern int FNV512stringin ( FNV512context * const,
const char *in ); const char *in );
extern int FNV512filein ( FNV512context * const, extern int FNV512filein ( FNV512context * const,
const char *fname ); const char *fname );
extern int FNV512result ( FNV512context * const, extern int FNV512result ( FNV512context * const,
uint8_t out[FNV512size] ); uint8_t out[FNV512size] );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _FNV512_H_ */ #endif /* _FNV512_H_ */
<CODE ENDS> <CODE ENDS>
<CODE BEGINS> file "FNV512.c" <CODE BEGINS> file "FNV512.c"
//**************************** FNV512.c **************************// //**************************** FNV512.c **************************//
//******************* See RFC NNNN for details *******************// //******************* See RFC 9923 for details. ******************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
/* This file implements the FNV (Fowler, Noll, Vo) non-cryptographic /* This file implements the FNV (Fowler/Noll/Vo) non-cryptographic
* hash function FNV-1a for 512-bit hashes. * hash function FNV-1a for 512-bit hashes.
*/ */
#include <stdio.h> #include <stdio.h>
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV512.h" #include "FNV512.h"
//***************************************************************** //*****************************************************************
// COMMON CODE FOR 64- AND 32-BIT INTEGER MODES // COMMON CODE FOR 64- AND 32-BIT INTEGER MODES
skipping to change at page 77, line 35 skipping to change at line 3662
FNV512context ctx; FNV512context ctx;
int error; int error;
if ( (error = FNV512init ( &ctx )) ) if ( (error = FNV512init ( &ctx )) )
return error; return error;
if ( (error = FNV512blockin ( &ctx, vin, length)) ) if ( (error = FNV512blockin ( &ctx, vin, length)) )
return error; return error;
return FNV512result ( &ctx, out ); return FNV512result ( &ctx, out );
} /* end FNV512block */ } /* end FNV512block */
/* FNV512 hash a counted block with a non-standard basis (64/32-bit) /* FNV512 hash a counted block (64/32-bit)
* with a non-standard basis
******************************************************************/ ******************************************************************/
int FNV512blockBasis ( const void *vin, int FNV512blockBasis ( const void *vin,
long int length, long int length,
uint8_t out[FNV512size], uint8_t out[FNV512size],
const uint8_t basis[FNV512size] ) { const uint8_t basis[FNV512size] ) {
FNV512context ctx; FNV512context ctx;
int error; int error;
if ( (error = FNV512initBasis ( &ctx, basis )) ) if ( (error = FNV512initBasis ( &ctx, basis )) )
return error; return error;
skipping to change at page 79, line 27 skipping to change at line 3750
fclose(fp); fclose(fp);
return error; return error;
} }
error = ferror(fp); error = ferror(fp);
fclose(fp); fclose(fp);
if (error) return fnvBadParam; if (error) return fnvBadParam;
return fnvSuccess; return fnvSuccess;
} /* end FNV512filein */ } /* end FNV512filein */
//***************************************************************** //*****************************************************************
// START VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC // START VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC
//***************************************************************** //*****************************************************************
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
/* 512-bit FNV_prime = 2^344 + 2^8 + 0x57 = /* 512-bit FNV_prime = 2^344 + 2^8 + 0x57 =
0x0000000000000000 0000000000000000 0x0000000000000000 0000000000000000
0000000001000000 0000000000000000 0000000001000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000157 */ 0000000000000000 0000000000000157 */
#define FNV512primeX 0x0157 #define FNV512primeX 0x0157
#define FNV512shift 24 #define FNV512shift 24
skipping to change at page 82, line 37 skipping to change at line 3904
out[4*i+1] = ctx->Hash[i] >> 16; out[4*i+1] = ctx->Hash[i] >> 16;
out[4*i+2] = ctx->Hash[i] >> 8; out[4*i+2] = ctx->Hash[i] >> 8;
out[4*i+3] = ctx->Hash[i]; out[4*i+3] = ctx->Hash[i];
ctx -> Hash[i] = 0; ctx -> Hash[i] = 0;
} }
ctx->Computed = FNVemptied+FNV512state; ctx->Computed = FNVemptied+FNV512state;
return fnvSuccess; return fnvSuccess;
} /* end FNV512result */ } /* end FNV512result */
//***************************************************************** //*****************************************************************
// END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC // END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC
//***************************************************************** //*****************************************************************
#else /* FNV_64bitIntegers */ #else /* FNV_64bitIntegers */
//***************************************************************** //*****************************************************************
// START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//***************************************************************** //*****************************************************************
/* 512-bit FNV_prime = 2^344 + 2^8 + 0x57 = /* 512-bit FNV_prime = 2^344 + 2^8 + 0x57 =
0x00000000 00000000 00000000 00000000 0x00000000 00000000 00000000 00000000
00000000 01000000 00000000 00000000 00000000 01000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000157 */ 00000000 00000000 00000000 00000157 */
#define FNV512primeX 0x0157 #define FNV512primeX 0x0157
#define FNV512shift 8 #define FNV512shift 8
skipping to change at page 85, line 47 skipping to change at line 4058
out[2*i] = ctx->Hash[i] >> 8; out[2*i] = ctx->Hash[i] >> 8;
out[2*i+1] = ctx->Hash[i]; out[2*i+1] = ctx->Hash[i];
ctx->Hash[i] = 0; ctx->Hash[i] = 0;
} }
ctx->Computed = FNVemptied+FNV512state; ctx->Computed = FNVemptied+FNV512state;
return fnvSuccess; return fnvSuccess;
} /* end FNV512result */ } /* end FNV512result */
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
//***************************************************************** //*****************************************************************
// END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//***************************************************************** //*****************************************************************
<CODE ENDS> <CODE ENDS>
8.2.6. FNV1024 Code 8.2.6. FNV1024 Code
The header and C source for 1024-bit FNV-1a providing a byte vector The following code is the header and C source for 1024-bit FNV-1a
hash. providing a byte vector hash.
<CODE BEGINS> file "FNV1024.h" <CODE BEGINS> file "FNV1024.h"
//*********************** FNV1024.h ***********************// //*********************** FNV1024.h ***********************//
//************* See RFC NNNN for details. *****************// //************* See RFC 9923 for details. *****************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
#ifndef _FNV1024_H_ #ifndef _FNV1024_H_
#define _FNV1024_H_ #define _FNV1024_H_
/* /*
* Description: * Description:
skipping to change at page 87, line 4 skipping to change at line 4109
/* /*
* This structure holds context information for an FNV1024 hash * This structure holds context information for an FNV1024 hash
*/ */
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
/* version if 64-bit integers supported */ /* version if 64-bit integers supported */
typedef struct FNV1024context_s { typedef struct FNV1024context_s {
int Computed; /* state */ int Computed; /* state */
uint32_t Hash[FNV1024size/4]; uint32_t Hash[FNV1024size/4];
} FNV1024context; } FNV1024context;
#else #else
/* version if 64-bit integers NOT supported */ /* version if 64-bit integers NOT supported */
typedef struct FNV1024context_s { typedef struct FNV1024context_s {
int Computed; /* state */ int Computed; /* state */
uint16_t Hash[FNV1024size/2]; uint16_t Hash[FNV1024size/2];
} FNV1024context; } FNV1024context;
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
/* Function Prototypes: /* Function Prototypes:
* *
* FNV1024string: hash a zero-terminated string not including * FNV1024string: hash a zero-terminated string not including
* the terminating zero * the terminating zero
* FNV1024stringBasis: also takes an offset_basis parameter * FNV1024stringBasis: also takes an offset_basis parameter
* *
* FNV1024block: hash a specified length byte vector * FNV1024block: hash a specified length byte vector
* FNV1024blockBasis: also takes an offset_basis parameter * FNV1024blockBasis: also takes an offset_basis parameter
* *
* FNV1024file: hash the contents of a file * FNV1024file: hash the contents of a file
* FNV1024fileBasis: also takes an offset_basis parameter * FNV1024fileBasis: also takes an offset_basis parameter
skipping to change at page 88, line 33 skipping to change at line 4187
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _FNV1024_H_ */ #endif /* _FNV1024_H_ */
<CODE ENDS> <CODE ENDS>
<CODE BEGINS> file "FNV1024.c" <CODE BEGINS> file "FNV1024.c"
//************************** FNV1024.c **************************// //************************** FNV1024.c **************************//
//****************** See RFC NNNN for details *******************// //****************** See RFC 9923 for details. ******************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
/* This file implements the FNV (Fowler, Noll, Vo) non-cryptographic /* This file implements the FNV (Fowler/Noll/Vo) non-cryptographic
* hash function FNV-1a for 1024-bit hashes. * hash function FNV-1a for 1024-bit hashes.
*/ */
#include <stdio.h> #include <stdio.h>
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV1024.h" #include "FNV1024.h"
//***************************************************************** //*****************************************************************
// COMMON CODE FOR 64- AND 32-BIT INTEGER MODES // COMMON CODE FOR 64- AND 32-BIT INTEGER MODES
skipping to change at page 90, line 48 skipping to change at line 4298
FNV1024context e1024Context; FNV1024context e1024Context;
int error; int error;
if ( !out ) if ( !out )
return fnvNull; return fnvNull;
if ( (error = FNV1024initBasis (&e1024Context, basis)) ) if ( (error = FNV1024initBasis (&e1024Context, basis)) )
return error; return error;
if ( (error = FNV1024filein (&e1024Context, fname)) ) if ( (error = FNV1024filein (&e1024Context, fname)) )
return error; return error;
return FNV1024result ( &e1024Context, out ); return FNV1024result ( &e1024Context, out );
} /* end FMV1024fileBasis */ } /* end FNV1024fileBasis */
/* hash in the contents of a file /* hash in the contents of a file
******************************************************************/ ******************************************************************/
int FNV1024filein ( FNV1024context * const e1024Context, int FNV1024filein ( FNV1024context * const e1024Context,
const char *fname ) { const char *fname ) {
FILE *fp; FILE *fp;
long int i; long int i;
char buf[1024]; char buf[1024];
int error; int error;
if ( !e1024Context || !fname ) if ( !e1024Context || !fname )
return fnvNull; return fnvNull;
switch ( e1024Context->Computed ) { switch ( e1024Context->Computed ) {
skipping to change at page 92, line 35 skipping to change at line 4381
if ( !ctx ) if ( !ctx )
return fnvNull; return fnvNull;
for ( int i=0; i<FNV1024size/4; ++i ) for ( int i=0; i<FNV1024size/4; ++i )
ctx->Hash[i] = FNV1024basis[i]; ctx->Hash[i] = FNV1024basis[i];
ctx->Computed = FNVinited+FNV1024state; ctx->Computed = FNVinited+FNV1024state;
return fnvSuccess; return fnvSuccess;
} /* end FNV1024init */ } /* end FNV1024init */
/* initialize context with a provided 128-byte vector basis (64-bit) /* initialize context with a provided 128-byte vector basis (64-bit)
******************************************************************/ *******************************************************************/
int FNV1024initBasis ( FNV1024context * const ctx, int FNV1024initBasis ( FNV1024context * const ctx,
const uint8_t basis[FNV1024size] ) { const uint8_t basis[FNV1024size] ) {
if ( !ctx || !basis ) if ( !ctx || !basis )
return fnvNull; return fnvNull;
for ( int i=0; i < FNV1024size/4; ++i ) { for ( int i=0; i < FNV1024size/4; ++i ) {
uint32_t temp = *basis++<<24; uint32_t temp = *basis++<<24;
temp += *basis++<<16; temp += *basis++<<16;
temp += *basis++<<8; temp += *basis++<<8;
ctx->Hash[i] = temp + *basis++; ctx->Hash[i] = temp + *basis++;
} }
skipping to change at page 95, line 4 skipping to change at line 4494
if ( !ctx || !out ) if ( !ctx || !out )
return fnvNull; return fnvNull;
if ( ctx->Computed != FNVcomputed+FNV1024state ) if ( ctx->Computed != FNVcomputed+FNV1024state )
return fnvStateError; return fnvStateError;
for ( int i=0; i<FNV1024size/4; ++i ) { for ( int i=0; i<FNV1024size/4; ++i ) {
out[4*i] = ctx->Hash[i] >> 24; out[4*i] = ctx->Hash[i] >> 24;
out[4*i+1] = ctx->Hash[i] >> 16; out[4*i+1] = ctx->Hash[i] >> 16;
out[4*i+2] = ctx->Hash[i] >> 8; out[4*i+2] = ctx->Hash[i] >> 8;
out[4*i+3] = ctx->Hash[i]; out[4*i+3] = ctx->Hash[i];
ctx -> Hash[i] = 0; ctx -> Hash[i] = 0;
} }
ctx->Computed = FNVemptied+FNV1024state; ctx->Computed = FNVemptied+FNV1024state;
return fnvSuccess; return fnvSuccess;
} /* end FNV1024result */ } /* end FNV1024result */
//****************************************************************// //****************************************************************//
// END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC // END VERSION FOR WHEN YOU HAVE 64-BIT ARITHMETIC
//***************************************************************// //****************************************************************//
#else /* FNV_64bitIntegers */ #else /* FNV_64bitIntegers */
//***************************************************************// //****************************************************************//
// START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // START VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//***************************************************************// //****************************************************************//
/* version for when you only have 32-bit arithmetic /* version for when you only have 32-bit arithmetic
******************************************************************/ ******************************************************************/
/* /*
1024-bit FNV_prime = 2^680 + 2^8 + 0x8d = 1024-bit FNV_prime = 2^680 + 2^8 + 0x8d =
0x00000000 00000000 00000000 00000000 0x00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000100 00000000 00000000 00000000 00000100 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
skipping to change at page 96, line 12 skipping to change at line 4550
if ( !ctx ) if ( !ctx )
return fnvNull; return fnvNull;
for ( int i=0; i<FNV1024size/2; ++i ) for ( int i=0; i<FNV1024size/2; ++i )
ctx->Hash[i] = FNV1024basis[i]; ctx->Hash[i] = FNV1024basis[i];
ctx->Computed = FNVinited+FNV1024state; ctx->Computed = FNVinited+FNV1024state;
return fnvSuccess; return fnvSuccess;
} /* end FNV1024init */ } /* end FNV1024init */
/* initialize context with a provided 128-byte vector basis (32-bit) /* initialize context with a provided 128-byte vector basis (32-bit)
******************************************************************/ *******************************************************************/
int FNV1024initBasis ( FNV1024context * const ctx, int FNV1024initBasis ( FNV1024context * const ctx,
const uint8_t basis[FNV1024size] ) { const uint8_t basis[FNV1024size] ) {
if ( !ctx || !basis ) if ( !ctx || !basis )
return fnvNull; return fnvNull;
for ( int i=0; i < FNV1024size/2; ++i ) { for ( int i=0; i < FNV1024size/2; ++i ) {
uint32_t temp = *basis++; uint32_t temp = *basis++;
ctx->Hash[i] = ( temp<<8 ) + *basis++; ctx->Hash[i] = ( temp<<8 ) + *basis++;
} }
ctx->Computed = FNVinited+FNV1024state; ctx->Computed = FNVinited+FNV1024state;
return fnvSuccess; return fnvSuccess;
skipping to change at page 98, line 32 skipping to change at line 4666
out[2*i] = ctx->Hash[i] >> 8; out[2*i] = ctx->Hash[i] >> 8;
out[2*i+1] = ctx->Hash[i]; out[2*i+1] = ctx->Hash[i];
ctx->Hash[i] = 0; ctx->Hash[i] = 0;
} }
ctx->Computed = FNVemptied+FNV1024state; ctx->Computed = FNVemptied+FNV1024state;
return fnvSuccess; return fnvSuccess;
} /* end FNV1024result */ } /* end FNV1024result */
#endif /* FNV_64bitIntegers */ #endif /* FNV_64bitIntegers */
//****************************************************************// //****************************************************************//
// END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC // END VERSION FOR WHEN YOU ONLY HAVE 32-BIT ARITHMETIC
//****************************************************************// //****************************************************************//
<CODE ENDS> <CODE ENDS>
8.3. FNV Test Code 8.3. FNV Test Code
Below is source code for a test driver with a command line interface Below is source code for a test driver with a command line interface
documented in Section 8.1.3. By default, with no command line as documented in Section 8.1.3. By default, with no command line
arguments, it runs tests of all FNV lengths. arguments, it runs tests of all FNV lengths.
<CODE BEGINS> file "main.c" <CODE BEGINS> file "main.c"
//************************* Main.c **************************// //************************* Main.c **************************//
//*************** See RFC NNNN for details. *****************// //*************** See RFC 9923 for details. *****************//
/* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons /* Copyright (c) 2016, 2024, 2025 IETF Trust and the persons
* identified as authors of the code. All rights reserved. * identified as authors of the code. All rights reserved.
* See fnv-private.h for terms of use and redistribution. * See fnv-private.h for terms of use and redistribution.
*/ */
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
/* To do a thorough test you need to run with /* To do a thorough test, you need to run with
* FNV_64bitIntegers defined and with it undefined * FNV_64bitIntegers defined and with it undefined
*/ */
#include "FNVconfig.h" #include "FNVconfig.h"
#include "fnv-private.h" #include "fnv-private.h"
#include "FNV32.h" #include "FNV32.h"
#include "FNV64.h" #include "FNV64.h"
#include "FNV128.h" #include "FNV128.h"
#include "FNV256.h" #include "FNV256.h"
#include "FNV512.h" #include "FNV512.h"
#include "FNV1024.h" #include "FNV1024.h"
skipping to change at page 99, line 33 skipping to change at line 4715
const char *errteststring = "foo"; const char *errteststring = "foo";
int Terr = -1; /* Total errors */ int Terr = -1; /* Total errors */
int verbose = 0; /* verbose flag */ int verbose = 0; /* verbose flag */
enum { FNV32selected = 0, FNV64selected, FNV128selected, enum { FNV32selected = 0, FNV64selected, FNV128selected,
FNV256selected, FNV512selected, FNV1024selected, FNV256selected, FNV512selected, FNV1024selected,
FNVnone = -1 } selected = FNVnone; FNVnone = -1 } selected = FNVnone;
#define NTestBytes 3 #define NTestBytes 3
const uint8_t errtestbytes[NTestBytes] = { (uint8_t)1, const uint8_t errtestbytes[NTestBytes] = { (uint8_t)1,
(uint8_t)2, (uint8_t)3 }; (uint8_t)2, (uint8_t)3 };
// initial teststring is null so initial result is offset_basis // initial teststring is null, so initial result is offset_basis
const char *teststring[] = { const char *teststring[] = {
"", "",
"a", "a",
"foobar", "foobar",
"Hello!\x01\xFF\xED" "Hello!\x01\xFF\xED"
}; };
#define NTstrings (sizeof(teststring)/sizeof(char *)) #define NTstrings (sizeof(teststring)/sizeof(char *))
// due to FNV-1 versus FNV1a, xor in final backslash separately // due to FNV-1 versus FNV1a, xor in final backslash separately
const char BasisString[] = "chongo <Landon Curt Noll> /\\../"; const char BasisString[] = "chongo <Landon Curt Noll> /\\../";
FNV32context e32Context; FNV32context e32Context;
uint32_t eUint32 = 42; uint32_t eUint32 = 42;
#ifdef FNV_64bitIntegers #ifdef FNV_64bitIntegers
uint64_t eUint64 = 42; uint64_t eUint64 = 42;
#endif #endif
FNV64context e64Context; FNV64context e64Context;
FNV128context e128Context; FNV128context e128Context;
FNV256context e256Context; FNV256context e256Context;
FNV512context e512Context; FNV512context e512Context;
FNV1024context e1024Context; FNV1024context e1024Context;
uint8_t hash[FNV1024size]; /* largest size needed */ uint8_t hash[FNV1024size]; /* largest size needed */
uint8_t FakeBasis[FNV1024size]; uint8_t FakeBasis[FNV1024size];
uint8_t ZeroBasis[FNV1024size]; uint8_t ZeroBasis[FNV1024size];
char tempFileNameTemplate[] = "tmp.XXXXXXXXXX"; char tempFileNameTemplate[] = "tmp.XXXXXXXXXX";
const char *tempFileName = 0; const char *tempFileName = 0;
//**************************************************************** //****************************************************************
// local prototypes in alphabetic order // local prototypes in alphabetical order
//**************************************************************** //****************************************************************
void CommonTest ( void ); void CommonTest ( void );
void ErrTestReport ( void ); void ErrTestReport ( void );
int find_selected(const char *optarg); int find_selected(const char *optarg);
void HexPrint ( int count, const uint8_t *ptr ); void HexPrint ( int count, const uint8_t *ptr );
void TestAll ( void ); void TestAll ( void );
void Test32 ( void ); void Test32 ( void );
void Test64 ( void ); void Test64 ( void );
void Test128 ( void ); void Test128 ( void );
void Test256 ( void ); void Test256 ( void );
skipping to change at page 101, line 51 skipping to change at line 4829
FakeBasis[i] = (uint8_t)i; FakeBasis[i] = (uint8_t)i;
} }
if ( argc == 1 ) { // if no arguments if ( argc == 1 ) { // if no arguments
TestAll(); TestAll();
if ( tempFileName ) if ( tempFileName )
unlink(tempFileName); unlink(tempFileName);
exit(0); exit(0);
} }
// process command line options // process command line options
// ***************************************************************** //*****************************************************************
while ((option = getopt(argc, (char *const *)argv, ":af:ht:u:v")) while ((option = getopt(argc, (char *const *)argv, ":af:ht:u:v"))
!= -1) { != -1) {
if ( verbose ) if ( verbose )
printf ( "Got option %c\n", option ); printf ( "Got option %c\n", option );
switch ( option ) { switch ( option ) {
case 'a': // run all tests case 'a': // run all tests
TestAll(); TestAll();
break; break;
case 'f': // followed by name of file to hash case 'f': // followed by name of file to hash
if ( selected == FNVnone ) { if ( selected == FNVnone ) {
printf ( "No hash size selected.\n" ); printf ( "No hash size selected.\n" );
break; break;
} }
printf ( "FNV-%i Hash of contents of file '%s':\n", printf ( "FNV-%i Hash of contents of file '%s':\n",
funcmap[selected].length, optarg ); funcmap[selected].length, optarg );
if ( funcmap[selected].Filefunc ( optarg, hash )) if ( funcmap[selected].Filefunc ( optarg, hash ))
skipping to change at page 103, line 27 skipping to change at line 4900
return 1; return 1;
} /* end switch */ } /* end switch */
} /* end while */ } /* end while */
if ( ( option == -1 ) && verbose ) if ( ( option == -1 ) && verbose )
printf ( "No more options.\n" ); printf ( "No more options.\n" );
// Through all the options, now, if a size is set, encrypt any // Through all the options, now, if a size is set, encrypt any
// other tokens on the command line // other tokens on the command line
//****************************************************** //******************************************************
for ( i = optind; i < argc; ++i ) { for ( i = optind; i < argc; ++i ) {
int rc; // return code int rc; // return code
if ( selected == FNVnone ) { if ( selected == FNVnone ) {
printf ( "No hash size selected.\n" ); printf ( "No hash size selected.\n" );
break; // out of for break; // out of for
} }
rc = funcmap[selected].Stringfunc(argv[i], hash); rc = funcmap[selected].Stringfunc(argv[i], hash);
if ( rc ) if ( rc )
printf ( "FNV-%i of '%s' returns error %i\n", printf ( "FNV-%i of '%s' returns error %i\n",
funcmap[selected].length, funcmap[selected].length,
argv[i], rc ); argv[i], rc );
skipping to change at page 104, line 36 skipping to change at line 4958
funcName, name, actual, expect ); funcName, name, actual, expect );
++Terr; /* increment error count */ ++Terr; /* increment error count */
} }
return actual; return actual;
} /* end TestR */ } /* end TestR */
//**************************************************************** //****************************************************************
// General byte vector return value test // General byte vector return value test
//**************************************************************** //****************************************************************
void TestNValue ( const char *subfunc, void TestNValue ( const char *subfunc,
const char *string, //usually what was hashed const char *string, // usually what was hashed
int N, int N,
const uint8_t was[N], const uint8_t was[N],
const uint8_t should[N] ) { const uint8_t should[N] ) {
if ( memcmp ( was, should, N) != 0 ) { if ( memcmp ( was, should, N ) != 0 ) {
++Terr; ++Terr;
printf ( "%s %s of '%s'", printf ( "%s %s of '%s'",
funcName, subfunc, string ); funcName, subfunc, string );
printf ( " computed " ); printf ( " computed " );
HexPrint ( N, was ); HexPrint ( N, was );
printf ( ", expected " ); printf ( ", expected " );
HexPrint ( N, should ); HexPrint ( N, should );
printf ( ".\n" ); printf ( ".\n" );
} }
else if ( verbose ) { else if ( verbose ) {
skipping to change at page 106, line 50 skipping to change at line 5068
funcmap[selected].Blockfunc ( errtestbytes, 1, funcmap[selected].Blockfunc ( errtestbytes, 1,
(uint8_t *)0 ) ); (uint8_t *)0 ) );
TestR ( "blk1b", fnvNull, TestR ( "blk1b", fnvNull,
funcmap[selected].BlockBasisfunc ( (uint8_t *)0, 1, funcmap[selected].BlockBasisfunc ( (uint8_t *)0, 1,
hash, FakeBasis ) ); hash, FakeBasis ) );
TestR ( "blk2b", fnvBadParam, TestR ( "blk2b", fnvBadParam,
funcmap[selected].BlockBasisfunc ( errtestbytes, -1, funcmap[selected].BlockBasisfunc ( errtestbytes, -1,
hash, FakeBasis ) ); hash, FakeBasis ) );
TestR ( "blk3b", fnvNull, TestR ( "blk3b", fnvNull,
funcmap[selected].BlockBasisfunc ( errtestbytes, 1, funcmap[selected].BlockBasisfunc ( errtestbytes, 1,
(uint8_t *)0 , FakeBasis ) ); (uint8_t *)0, FakeBasis ) );
TestR ( "blk4b", fnvNull, TestR ( "blk4b", fnvNull,
funcmap[selected].BlockBasisfunc ( errtestbytes, 1, funcmap[selected].BlockBasisfunc ( errtestbytes, 1,
hash, (uint8_t *)0 ) ); hash, (uint8_t *)0 ) );
TestR ( "file1", fnvNull, TestR ( "file1", fnvNull,
funcmap[selected].Filefunc ( (char *)0, hash )); funcmap[selected].Filefunc ( (char *)0, hash ));
TestR ( "file2", fnvNull, TestR ( "file2", fnvNull,
funcmap[selected].Filefunc ( "foo.txt", (uint8_t *)0 )); funcmap[selected].Filefunc ( "foo.txt", (uint8_t *)0 ));
TestR ( "file1b", fnvNull, TestR ( "file1b", fnvNull,
funcmap[selected].FileBasisfunc ( (char *)0, hash, funcmap[selected].FileBasisfunc ( (char *)0, hash,
FakeBasis )); FakeBasis ));
skipping to change at page 108, line 28 skipping to change at line 5142
STRIN ( &CTX, errteststring ) ); STRIN ( &CTX, errteststring ) );
#define TestFilein(FLIN,CTX,CTXT) \ #define TestFilein(FLIN,CTX,CTXT) \
TestR ( "file1", fnvNull, FLIN ( (CTXT *)0, errteststring ) );\ TestR ( "file1", fnvNull, FLIN ( (CTXT *)0, errteststring ) );\
TestR ( "file2", fnvNull, FLIN ( &CTX, (char *)0 ) ); \ TestR ( "file2", fnvNull, FLIN ( &CTX, (char *)0 ) ); \
TestR ( "file3", fnvStateError, \ TestR ( "file3", fnvStateError, \
FLIN ( &CTX, errteststring ) ); FLIN ( &CTX, errteststring ) );
#define TestResult(RSLT,CTX,CTXT) \ #define TestResult(RSLT,CTX,CTXT) \
TestR ( "result1", fnvNull, RSLT ( (CTXT *)0, hash ) ); \ TestR ( "result1", fnvNull, RSLT ( (CTXT *)0, hash ) ); \
TestR ( "result2", fnvNull, RSLT ( &CTX, (uint8_t *)0 ) ); \ TestR ( "result2", fnvNull, RSLT ( &CTX, (uint8_t *)0 ) ); \
TestR ( "result3", fnvStateError, \ TestR ( "result3", fnvStateError, \
FNV128result ( &e128Context, hash ) ); FNV128result ( &e128Context, hash ) );
// test return values for INT versions including non-std basis // test return values for INT versions including non-std basis
//************************************************************* //*************************************************************
#define TestINT(STRINT,STRINTB,BLKINT,BLKINTB,INITINTB, \ #define TestINT(STRINT,STRINTB,BLKINT,BLKINTB,INITINTB, \
INTV,INTVT,ctxT) \ INTV,INTVT,ctxT) \
TestR ( "string1i", fnvNull, STRINT ( (char *)0, &INTV ) ); \ TestR ( "string1i", fnvNull, STRINT ( (char *)0, &INTV ) ); \
TestR ( "string2i", fnvNull, \ TestR ( "string2i", fnvNull, \
STRINT ( errteststring, (INTVT *)0 ) ); \ STRINT ( errteststring, (INTVT *)0 ) ); \
TestR ("string3i", fnvNull, STRINTB ((char *)0, &INTV, INTV));\ TestR ("string3i", fnvNull, STRINTB ((char *)0, &INTV, INTV));\
TestR ( "string4i", fnvNull, \ TestR ( "string4i", fnvNull, \
skipping to change at page 109, line 10 skipping to change at line 5172
BLKINTB ( (uint8_t *)0, 1, &INTV, INTV ) ); \ BLKINTB ( (uint8_t *)0, 1, &INTV, INTV ) ); \
TestR ( "block5i", fnvBadParam, \ TestR ( "block5i", fnvBadParam, \
BLKINTB ( errtestbytes, -1, &INTV, INTV ) ); \ BLKINTB ( errtestbytes, -1, &INTV, INTV ) ); \
TestR ( "block6i", fnvNull, \ TestR ( "block6i", fnvNull, \
BLKINTB ( errtestbytes, 1, (INTVT *)0, INTV ) ); \ BLKINTB ( errtestbytes, 1, (INTVT *)0, INTV ) ); \
TestR ("initBasis1i", fnvNull, INITINTB ( (ctxT *)0, INTV )); TestR ("initBasis1i", fnvNull, INITINTB ( (ctxT *)0, INTV ));
#define TestINTrf(RSLTINT,FILEINT,FILEINTB, \ #define TestINTrf(RSLTINT,FILEINT,FILEINTB, \
ctx,ctxT,INTV,INTVT) \ ctx,ctxT,INTV,INTVT) \
TestR ( "result1i", fnvNull, RSLTINT ( (ctxT *)0, &INTV ) ); \ TestR ( "result1i", fnvNull, RSLTINT ( (ctxT *)0, &INTV ) ); \
TestR ( "result2i", fnvNull, RSLTINT ( &ctx, (INTVT *)0 ) ); \ TestR ( "result2i", fnvNull, RSLTINT ( &ctx, (INTVT *)0 ) ); \
TestR ( "result3i", fnvStateError, RSLTINT ( &ctx, &INTV ) );\ TestR ( "result3i", fnvStateError, RSLTINT ( &ctx, &INTV ) ); \
TestR ( "file1i", fnvNull, FILEINT ( (char *)0, &INTV )); \ TestR ( "file1i", fnvNull, FILEINT ( (char *)0, &INTV )); \
TestR ( "file2i", fnvNull, FILEINT ( "foo.txt", (INTVT *)0 ));\ TestR ( "file2i", fnvNull, FILEINT ( "foo.txt", (INTVT *)0 ));\
TestR ("file3i", fnvNull, FILEINTB ( (char *)0, &INTV, INTV));\ TestR ("file3i", fnvNull, FILEINTB ( (char *)0, &INTV, INTV));\
TestR ( "file4i", fnvNull, \ TestR ( "file4i", fnvNull, \
FILEINTB ( "foo.txt", (INTVT *)0, INTV )); FILEINTB ( "foo.txt", (INTVT *)0, INTV ));
// test to calculate standard basis from basis zero FNV-1 // test to calculate standard basis from basis zero FNV-1
// depends on zero basis making the initial multiply a no-op // depends on zero basis making the initial multiply a no-op
//***************************** //*****************************
#define BasisZero(STRING,SIZ,VALUE) \ #define BasisZero(STRING,SIZ,VALUE) \
skipping to change at page 125, line 5 skipping to change at line 5934
} }
ValueTestReport (); ValueTestReport ();
} /* end Test1024 */ } /* end Test1024 */
<CODE ENDS> <CODE ENDS>
8.4. Makefile 8.4. Makefile
Below is a simple makefile to produce and run the test program or to Below is a simple makefile to produce and run the test program or to
provide a library with all the FNV functions supplied in it. provide a library with all the FNV functions supplied in it.
WARNING: When actually using the following as a makefile, the five WARNING: When actually using the following as a makefile, the five-
character sequence "<TAB>" must be changed to a tab (0x09) character! character sequence "<TAB>" must be changed to a tab (0x09) character!
<CODE BEGINS> file "makefile" <CODE BEGINS> file "makefile"
# Makefile for fnv # Makefile for fnv
# If you extract this file from RFC NNNN, the five character sequence # If you extract this file from RFC 9923, the five-character sequence
# <TAB> below must be replace with a tab (0x09) character. # <TAB> below must be replaced with a tab (0x09) character.
explanation: explanation:
<TAB>@echo Choose one of the following make targets: <TAB>@echo Choose one of the following make targets:
<TAB>@echo make FNVhash -- test program <TAB>@echo make FNVhash -- test program
<TAB>@echo make libfnv.a -- library you can use <TAB>@echo make libfnv.a -- library you can use
<TAB>@echo make clean -- removes all of the built targets <TAB>@echo make clean -- removes all of the built targets
SRC=FNV1024.c FNV128.c FNV256.c FNV32.c FNV512.c FNV64.c SRC=FNV1024.c FNV128.c FNV256.c FNV32.c FNV512.c FNV64.c
HDR=FNV32.h FNV64.h FNV128.h FNV256.h FNV512.h FNV1024.h \ HDR=FNV32.h FNV64.h FNV128.h FNV256.h FNV512.h FNV1024.h \
<TAB>FNVErrorCodes.h FNVconfig.h fnv-private.h <TAB>FNVErrorCodes.h FNVconfig.h fnv-private.h
skipping to change at page 125, line 41 skipping to change at line 5970
<TAB>rm -f libfnv.a *.o <TAB>rm -f libfnv.a *.o
<TAB>$(CC) $(CFLAGS) -c $(SRC) <TAB>$(CC) $(CFLAGS) -c $(SRC)
<TAB>$(AR) $(ARFLAGS) libfnv.a $(OBJ) <TAB>$(AR) $(ARFLAGS) libfnv.a $(OBJ)
clean: clean:
<TAB>rm -rf libfnv.a FNVhash *.o <TAB>rm -rf libfnv.a FNVhash *.o
<CODE ENDS> <CODE ENDS>
9. IANA Considerations 9. IANA Considerations
This document requires no IANA Actions. This document has no IANA actions.
10. Normative References 10. References
[C] Kernighan, B. and D. Ritchie, "The C Programming Language, 10.1. Normative References
2nd Edition", ISBN-10 0-13-110362-8,
ISBN-13 978-0131103627, 1978. [C] Kernighan, B. W. and D. M. Ritchie, "The C Programming
Language, 2nd Edition", ISBN-10 0-13-110362-8,
ISBN-13 978-0131103627, 1988.
[RFC0020] Cerf, V., "ASCII format for network interchange", STD 80, [RFC0020] Cerf, V., "ASCII format for network interchange", STD 80,
RFC 20, DOI 10.17487/RFC0020, October 1969, RFC 20, DOI 10.17487/RFC0020, October 1969,
<https://www.rfc-editor.org/info/rfc20>. <https://www.rfc-editor.org/info/rfc20>.
11. Informative References [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[BASIC] Diamond, W., "FNV32 PowerBASIC in line x86 assembler", [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
10.2. Informative References
[BASIC] Diamond, W., "FNV32 PowerBASIC inline x86 assembler",
<http://www.isthe.com/chongo/tech/comp/fnv/ <http://www.isthe.com/chongo/tech/comp/fnv/
index.html#PowerBASIC>. index.html#PowerBASIC>.
[BFDseq] Jethanandani, M., Agarwal, S., Mishra, A., Saxena, A., and
A. DeKok, "Secure BFD Sequence Numbers", 22 March 2022,
<draft-ietf-bfd-secure-sequence-numbers-09.txt>.
[calc] Bell, D. and L. Noll, "Calc - C-style arbitrary precision [calc] Bell, D. and L. Noll, "Calc - C-style arbitrary precision
calculator", calculator",
<http://www.isthe.com/chongo/tech/comp/calc/index.html>. <http://www.isthe.com/chongo/tech/comp/calc/index.html>.
[Cohesia] Cohesia, "Cohesia website", <http://www.cohesia.com/>. [Cohesia] Cohesia, "Cohesia website", <http://www.cohesia.com/>.
[deliantra] [deliantra]
The Deliantra Team, "Deliantra MMORPG", 2016, The Deliantra Team, "Deliantra MMORPG", 2016,
<http://www.deliantra.net/>. <http://www.deliantra.net/>.
[fasmlab] Fasmlab, "Integrated Development Environment", [fasmlab] Fasmlab, "Integrated Development Environments",
<https://sourceforge.net/projects/fasmlab/>. <https://sourceforge.net/projects/fasmlab/>.
[FIPS202] National Institute of Standards and Technology, "SHA-3 [FIPS202] NIST, "SHA-3 Standard: Permutation-Based Hash and
Standard: Permutation-Based Hash and Extendable Output Extendable-Output Functions", FIPS PUB 202,
Functions", Federal Information Processing Standards DOI 10.6028/NIST.FIPS.202, August 2015,
Publicsation FIPS PUB 202,
DOI http://dx.doi.org/10.6028/NIST.FIPS.202, August 2015,
<https://nvlpubs.nist.gov/nistpubs/FIPS/ <https://nvlpubs.nist.gov/nistpubs/FIPS/
NIST.FIPS.202.pdf>. NIST.FIPS.202.pdf>.
[flatassembler] [flatassembler]
Grysztar, T., "flat assembler, Assembly language Grysztar, T., "flat assembler: Assembly language
resources", 2025, <https://flatassembler.net/>. resources", 2025, <https://flatassembler.net/>.
[FNV] Fowler-Noll-Vo, "FNV website", [FNV] Fowler-Noll-Vo, "FNV website",
<http://www.isthe.com/chongo/tech/comp/fnv/index.html>. <http://www.isthe.com/chongo/tech/comp/fnv/index.html>.
[Fortran] Fortran Standard Library, "A community driven standard [Fortran] Fortran Standard Library, "A community driven standard
library for (modern) Fortran", library for (modern) Fortran",
<https://stdlib.fortran-lang.org/>. <https://stdlib.fortran-lang.org/>.
[FragCache] [FragCache]
Weaver, E., "Improving Running Components at Twitter (see Weaver, E., "Improving Running Components at Twitter",
slide 31)", 2009, <https://www.slideshare.net/slideshow/ Slide 31, 2009, <https://www.slideshare.net/slideshow/
improving-running-components-at-twitter/1141786>. improving-running-components-at-twitter/1141786>.
[FreeBSD] The Free BSD Project, "FreeBSD 4.3 Release Notes", 2025, [FreeBSD] The Free BSD Project, "FreeBSD 4.3 Release Notes", 2025,
<http://www.freebsd.org/releases/4.3R/notes.html>. <https://www.freebsd.org/releases/4.3R/notes.html>.
[FRET] McCarthy, M., "FRET helps understand file formats", 19 [FRET] McCarthy, M., "FRET: helping understand file formats", 19
January 2006, <https://fret.sourceforge.net/>. January 2006, <https://fret.sourceforge.net/>.
[GolfHash] Gliim LLC, "Golf Language Hash Tables", 2025, [GolfHash] Gliim LLC, "Golf Language Hash Tables", 2025,
<https://golf-lang.com/new-hash.html>. <https://golf-lang.com/new-hash.html>.
[IEEE] Institute for Electrical and Electronics Engineers, "IEEE [IEEE] Institute for Electrical and Electronics Engineers, "IEEE
website", <http:www.ieee.org>. website", <https://www.ieee.org/>.
[IEEE8021Qbp] [IEEE8021Qbp]
"Media Access Control (MAC) Bridges and Virtual Bridged "Media Access Control (MAC) Bridges and Virtual Bridged
Local Area Networks - Equal Cost Multiple Path (ECMP)", Local Area Networks - Equal Cost Multiple Path (ECMP)",
IEEE Std 802.1Qbp-2014, 7 April 2014. IEEE Std 802.1Qbp-2014, 7 April 2014.
[IEN137] Cohen, D., "On Holy Wars and A Plea For Peace", IEN 137, 1 [IEN137] Cohen, D., "On Holy Wars and A Plea For Peace", IEN 137, 1
April 1980, <https://www.rfc-editor.org/ien/ien137.txt>. April 1980, <https://www.rfc-editor.org/ien/ien137.txt>.
[IPv6flow] Anderson, L., Brownlee, N., and B. Carpenter, "Comparing [IPv6flow] Anderson, L., Brownlee, N., and B. Carpenter, "Comparing
Hash Function Algorithms for the IPv6 Flow Label", Hash Function Algorithms for the IPv6 Flow Label",
University of Auckland Department of Computer Science University of Auckland Department of Computer Science
Technical Report 2012-002, ISSN 1173-3500, March 2012, Technical Report 2012-002, ISSN 1173-3500, March 2012,
<https://researchspace.auckland.ac.nz/bitstream/ <https://researchspace.auckland.ac.nz/bitstream/
handle/2292/13240/flowhashRep.pdf>. handle/2292/13240/flowhashRep.pdf>.
[LCN2] Noll, L. and C. Ferguson, "lcn2 / fnv", [ISAAC-Auth]
<https://github.com/lcn2/fnv>. DeKok, A., Jethanandani, M., Agarwal, S., Mishra, A., and
J. Haas, "Meticulous Keyed ISAAC for BFD Optimized
Authentication", Work in Progress, Internet-Draft, draft-
ietf-bfd-secure-sequence-numbers-27, 16 October 2025,
<https://datatracker.ietf.org/doc/html/draft-ietf-bfd-
secure-sequence-numbers-27>.
[LCN2] Noll, L. and C. Ferguson, "lcn2 / fnv", commit 953444c, 19
November 2025, <https://github.com/lcn2/fnv>.
[Leprechaun] [Leprechaun]
Sanmayce project, "Sanmayce project 'Underdog Way'", Sanmayce project, "Sanmayce project 'Underdog Way'",
<http://www.sanmayce.com/Downloads/>. <http://www.sanmayce.com/Downloads/>.
[libstr] Lederman, R. and J. Johnson, "libstr logging library", [libsir] Lederman, R. and J. Johnson, "libsir logging library",
commit 0ae0173, 3 December 2025,
<https://github.com/aremmell/libsir>. <https://github.com/aremmell/libsir>.
[memcache] Dovgal, A., Joye, P., Radtke, H., Johansson, M., and T. [memcache] Dovgal, A., Joye, P., Radtke, H., Johansson, M., and T.
Srnka, "PHP memcached extension", 30 April 2023, Srnka, "PHP memcached extension", 30 April 2023,
<http://pecl.php.net/package/memcache>. <https://pecl.php.net/package/memcache>.
[NCHF] Hayes, C. and D. Malone, "Questioning the Criteria for [NCHF] Hayes, C. and D. Malone, "Questioning the Criteria for
Evaluating Non-Cryptographic Hash Functions", Evaluating Non-Cryptographic Hash Functions",
DOI 10.1145/3704255, 15 January 2025, Communications of the ACM, Vol. 68 No. 2, pp. 46-51,
DOI 10.1145/3704255, February 2025,
<https://cacm.acm.org/practice/questioning-the-criteria- <https://cacm.acm.org/practice/questioning-the-criteria-
for-evaluating-non-cryptographic-hash-functions/>. for-evaluating-non-cryptographic-hash-functions/>.
Hayes, C. and D. Malone, "An Evaluation of FNV Non- Hayes, C. and D. Malone, "An Evaluation of FNV Non-
Cryptographic Hash Functions", Cryptographic Hash Functions", Proceedings of the 35th
Irish Signals and Systems Conference (ISSC),
DOI 10.1109/ISSC61953.2024.10603139, June 2024, DOI 10.1109/ISSC61953.2024.10603139, June 2024,
<https://ieeexplore.ieee.org/abstract/document/10603139>. <https://ieeexplore.ieee.org/abstract/document/10603139>.
[RFC3174] Eastlake 3rd, D. and P. Jones, "US Secure Hash Algorithm 1 [RFC3174] Eastlake 3rd, D. and P. Jones, "US Secure Hash Algorithm 1
(SHA1)", RFC 3174, DOI 10.17487/RFC3174, September 2001, (SHA1)", RFC 3174, DOI 10.17487/RFC3174, September 2001,
<https://www.rfc-editor.org/info/rfc3174>. <https://www.rfc-editor.org/info/rfc3174>.
[RFC6194] Polk, T., Chen, L., Turner, S., and P. Hoffman, "Security [RFC6194] Polk, T., Chen, L., Turner, S., and P. Hoffman, "Security
Considerations for the SHA-0 and SHA-1 Message-Digest Considerations for the SHA-0 and SHA-1 Message-Digest
Algorithms", RFC 6194, DOI 10.17487/RFC6194, March 2011, Algorithms", RFC 6194, DOI 10.17487/RFC6194, March 2011,
skipping to change at page 128, line 45 skipping to change at line 6132
[RFC7873] Eastlake 3rd, D. and M. Andrews, "Domain Name System (DNS) [RFC7873] Eastlake 3rd, D. and M. Andrews, "Domain Name System (DNS)
Cookies", RFC 7873, DOI 10.17487/RFC7873, May 2016, Cookies", RFC 7873, DOI 10.17487/RFC7873, May 2016,
<https://www.rfc-editor.org/info/rfc7873>. <https://www.rfc-editor.org/info/rfc7873>.
[RFC8200] Deering, S. and R. Hinden, "Internet Protocol, Version 6 [RFC8200] Deering, S. and R. Hinden, "Internet Protocol, Version 6
(IPv6) Specification", STD 86, RFC 8200, (IPv6) Specification", STD 86, RFC 8200,
DOI 10.17487/RFC8200, July 2017, DOI 10.17487/RFC8200, July 2017,
<https://www.rfc-editor.org/info/rfc8200>. <https://www.rfc-editor.org/info/rfc8200>.
[twistylists] [twistylists]
twistylists, "A no-sort namespace engine", 2012, Zethmayr, D., "twistylists: A no-sort namespace engine;
developers invited", 6 November 2012,
<https://twistylists.blogspot.com/>. <https://twistylists.blogspot.com/>.
[Vely] Mijatovic, S., "Vely - general purpose framework", [Vely] Mijatovic, S., "Vely - general purpose framework", 26
<https://www.linuxlinks.com/vely-general-purpose- October 2023, <https://www.linuxlinks.com/vely-general-
framework/>. purpose-framework/>.
[Vortetty] "Raytracing for the gba", [Vortetty] "Raytracing for the gba", commit f8bf009, 26 February
<https://github.com/Vortetty/gba-rtx>. 2025, <https://github.com/Vortetty/gba-rtx>.
Appendix A. Work Comparison with SHA-1 and SHA-256 Appendix A. Work Comparison with SHA-1 and SHA-256
This appendix provides a simplistic rough comparison of the level of This appendix provides a simplistic rough comparison of the level of
effort required to compute FNV-1a, SHA-1 [RFC3174], and SHA-256 effort required to compute FNV-1a, SHA-1 [RFC3174], and SHA-256
[RFC6234] for short messages, that is, those less than around 50 [RFC6234] for short messages -- that is, those less than around 50
bytes. Some CPUs may have special instructions or other hardware to bytes. Some CPUs may have special instructions or other hardware to
accelerate certain cryptographic operations so, if performance is accelerate certain cryptographic operations, so if performance is
particularly important for an application, benchmarking on the target particularly important for an application, benchmarking on the target
platform would be appropriate. platform would be appropriate.
Ignoring transfer of control and conditional tests and equating all Ignoring transfer of control and conditional tests, and equating all
logical and arithmetic operations, FNV requires 2 operations per logical and arithmetic operations, FNV requires two operations per
byte, an XOR and a multiply. byte: an XOR operation and a multiply operation.
SHA-1 and SHA-256 are actually designed to accept a bit vector input SHA-1 and SHA-256 are actually designed to accept a bit vector input,
although almost all computer uses apply them to an integer number of although almost all computer uses apply them to an integer number of
bytes. They both process blocks of 512 bits (64 bytes) and we bytes. They both process blocks of 512 bits (64 bytes), and we
estimate the effort involved in processing a full block. There is estimate the effort involved in processing a full block. There is
some overhead per message to indicate message termination and size. some overhead per message to indicate message termination and size.
Assuming the message is an even number of bytes, this overhead would Assuming that the message is an even number of bytes, this overhead
be 9 bytes for SHA-1 and 17 bytes for SHA-256. So, assuming the would be 9 bytes for SHA-1 and 17 bytes for SHA-256. So, assuming
message with that overhead fits into one block, the message would be that the message with that overhead fits into one block, the message
up to 55 bytes for SHA-1 or up to 47 bytes for SHA-256. would be up to 55 bytes for SHA-1 or up to 47 bytes for SHA-256.
SHA-1 is a relatively weak cryptographic hash function producing a SHA-1 is a relatively weak cryptographic hash function producing a
160-bit hash. It has been partially broken [RFC6194]. Ignoring SHA- 160-bit hash. It has been partially broken [RFC6194]. Ignoring SHA-
1's initial set up, transfer of control, and conditional tests, but 1's initial setup, transfer of control, and conditional tests, but
counting all logical and arithmetic operations, including counting counting all logical and arithmetic operations, including counting
indexing as an addition, SHA-1 requires 1,744 operations per 64 bytes indexing as an addition, SHA-1 requires 1,744 operations per 64-byte
block or 31.07 operations per byte for a message of 55 bytes. By block or 31.07 operations per byte for a message of 55 bytes. By
this rough measure, it is a little over 15.5 times the effort of FNV. this rough measure, it is a little over 15.5 times the effort of FNV.
SHA-256 is, at the time of publication, considered to be a stronger SHA-256 is, at the time of publication, considered to be a stronger
cryptographic hash function than SHA-1. Ignoring SHA-256's initial cryptographic hash function than SHA-1. Ignoring SHA-256's initial
set up, transfer of control, and conditional tests, but counting all setup, transfer of control, and conditional tests, but counting all
logical and arithmetic operations, SHA-1 requires 2,058 operations logical and arithmetic operations, SHA-1 requires 2,058 operations
per 64 bytes block or 48.79 operations per byte for a message of 47 per 64-byte block or 48.79 operations per byte for a message of 47
byte. By this rough measure, it is over 24 times the effort of FNV. bytes. By this rough measure, it is over 24 times the effort of FNV.
However, FNV is commonly used for short inputs so a comparison for However, FNV is commonly used for short inputs, so doing a comparison
such inputs is relevant. Using the above comparison method, for of such inputs is relevant. Using the above comparison method, for
inputs of N bytes, where N is <= 55 so SHA-1 will take one block, the inputs of N bytes, where N is <= 55 so SHA-1 will take one block, the
ratio of the effort for SHA-1 to the effort for FNV will be 872/N. ratio of the effort for SHA-1 to the effort for FNV will be 872/N.
For inputs of N bytes, where N is <= 47 so SHA-256 will take one For inputs of N bytes, where N is <= 47 so SHA-256 will take one
block, the ratio of the effort for SHA-256 to the effort for FNV will block, the ratio of the effort for SHA-256 to the effort for FNV will
be 1029/N. Some examples are given below. be 1029/N. Some examples are given below.
+---------+----------+-----------------------+----------------+ +=========+==========+=======================+================+
| Example | Length | SHA-1 Effort Relative | SHA-256 Effort | | Example | Length | SHA-1 Effort Relative | SHA-256 Effort |
| | in Bytes | to FNV Effort | Relative to | | | in Bytes | to FNV Effort | Relative to |
| | | | FNV Effort | | | | | FNV Effort |
+---------+----------+-----------------------+----------------+ +=========+==========+=======================+================+
| IPv4 | 4 | 218 | 514 | | IPv4 | 4 | 218 | 514 |
| address | | | | | address | | | |
+---------+----------+-----------------------+----------------+ +---------+----------+-----------------------+----------------+
| MAC | 6 | 145 | 171 | | MAC | 6 | 145 | 171 |
| address | | | | | address | | | |
+---------+----------+-----------------------+----------------+ +---------+----------+-----------------------+----------------+
| IPv6 | 16 | 54 | 64 | | IPv6 | 16 | 54 | 64 |
| address | | | | | address | | | |
+---------+----------+-----------------------+----------------+ +---------+----------+-----------------------+----------------+
Table 3 Table 3
Appendix B. Previous IETF FNV Code Appendix B. Previous IETF FNV Code
FNV-1a was referenced in draft-ietf-tls-cached-info-08.txt that has FNV-1a was referenced in draft-ietf-tls-cached-info-08 (which was
since expired. Below is the Java code for FNV64 from that TLS draft ultimately published as RFC 7924, but RFC 7924 no longer contains the
included with the kind permission of the author: code below). Herein, we provide the Java code for FNV64 from that
earlier draft, included with the kind permission of the author:
<CODE BEGINS> <CODE BEGINS>
/* /*
* Java code sample, implementing 64 bit FNV-1a * Java code sample, implementing 64 bit FNV-1a
* By Stefan Santesson * By Stefan Santesson
*/ */
import java.math.BigInteger; import java.math.BigInteger;
public class FNV { public class FNV {
skipping to change at page 131, line 34 skipping to change at line 6243
for (byte b : inp) { for (byte b : inp) {
digest = digest.xor(BigInteger.valueOf((int) b & 255)); digest = digest.xor(BigInteger.valueOf((int) b & 255));
digest = digest.multiply(fnvPrime).mod(m); digest = digest.multiply(fnvPrime).mod(m);
} }
return digest; return digest;
} }
} }
<CODE ENDS> <CODE ENDS>
Appendix C. Change History
RFC Editor Note: Please delete this appendix on publication.
C.1. 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.
C.2. 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.
C.3. From -02 to -05
1. Minor addition to Section 6, point 3.
2. Add Twitter as a use example and IPv6 flow hash study reference.
3. Minor editorial changes.
C.4. From -05 to -08
1. Add code subsections.
2. Update Author info.
3. Minor edits.
C.5. From -08 to -09
1. Change reference for ASCII to [RFC0020].
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.
C.6. From -09 to -10
1. Inclusion of initial partial version of code and some
documentation about the code, Section 9.
2. Insertion of new Section 4 on hashing values.
C.7. From -10 to -12
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.
C.8. 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 Endian-
ness consistency is not required.
C.9. From -13 to -17
1. Update an author address
2. Update an author affiliation.
C.10. From -17 to -19
1. Add reference to draft-ietf-bfd-secure-sequence-numbers.
2. Add references to the following, each of which uses FNV: RFC
7357, RFC 7873, and IEEE Std. 802.1Qbp-2014
3. Update author information
4. Minor editorial changes.
C.11. From -19 to -20
Convert to XML v3. Fix code for longer FNV hashes.
C.12. From -20 to -21
Update Twitter to X. Minor Editorial changes.
C.13. From -21 to -22
Update Landon's email. Minor Editorial changes. Update to
substantially improved code.
C.14. From -22 to -23
1. Author info update.
2. Make byte vector returning versions of functions available for
all sizes.
3. Remove BigEndian code due to difficulty in finding someone to
test it. This only affects multi-byte integer returns and
correct results can always be obtained by using the byte vector
return versions of functions.
C.15. From -23 to -25
1. Correct some errors in comments in the code, fix some omissions
and add testing for the file hashing code, and other code
polishing
2. Minor editorial changes.
C.16. From -25 to -28
1. Add autodetect in FNVconfig.h of target support for 64-bit
integers.
2. Add discussion of what source files are needed for particular
uses.
3. Fix code so it compiles properly if all .c files are concatenated
as well as when they are compiled separately.
4. Add makefile section.
5. Fix some problems with &gt; and >.
6. Minor editorial improvements.
C.17. From -28 to -29
Responding to some IETF Last Call Comments: minor re-organization of
Introduction and addition to the Introduction of a some non-
applicability considerations. Minor editorial improvements.
C.18. From -29 to -30
1. Reorganize Section 1 and add to it a subsection on the
applicability of non-cryptographic hash functions.
2. Rewrite and expand Section 6.1 on inducing collisions.
3. Add material on parallelization to the section on hashing
multiple values.
4. Add a reference to IEN 137 on Endian-ness.
5. Minor editorial improvements.
6. Minor coding changes including adding function calls supporting
variant offset_basis values and reducing the size of main.c
through the use of C pre-processor macros.
C.19. From -30 to -31
1. Add more uses of FNV to Section 1.2.
2. Fix instructions for reporting uses of FNV.
3. Minor editing changes.
C.20. From -31 to -32
1. Move purpose sentence for this draft from the beginning of
Section 6 to the Introduction.
2. Minor editing changes.
C.21. From -32 to -33
1. Edit based on Independent Submissions Editor review. Includes
moving around some material, creation of the Historical Notes
Appendix, add additional uses including references for some uses,
etc.
2. Add [C], [LCN2], and [Vely] to References.
3. Minor editing changes.
C.22. From -33 to -34
Add "This work is not an Internet standard and is not the result of
consensus of the IETF community." to the Introduction.
C.23. From -34 to -35
Update based on reviews as follows:
1. Add references to SHA3 [FIPS202].
2. Slightly simplify the wording of Section 1.1.
3. Add [NCHF] reference group.
4. Make it clear that the Section 2 pseudocode uses modulus
arithmetic mod 2**HashSize.
5. Mention in Section 8 that some other source code might be more
optimized.
6. Mention in Appendix A that some CPUs may have hardware that
accelerates some cryptographic operations and, if performance is
important for a particular application, benchmarking on the
target platform would be appropriate.
7. Augment Appendix A with rough computational effort estimates for
SHA-256 as well as SHA-1 and reformat examples as a table.
8. Minor editing changes.
Acknowledgements Acknowledgements
The contributions of the following, listed is alphabetic order, are The contributions of the following, listed in alphabetical order, are
gratefully acknowledged: gratefully acknowledged:
Roman Donchenko, Frank Ellermann, Stephen Farrell, Tony Finch, Roman Donchenko, Frank Ellermann, Stephen Farrell, Tony Finch, Paul
Charlie Kaufman, Eliot Lear, Bob Moskowitz, Gayle Noble, Stefan Hoffman, Charlie Kaufman, Eliot Lear, Bob Moskowitz, Gayle Noble,
Santesson, Mukund Sivaraman, Paul Hoffman, and Paul Wouters. Stefan Santesson, Mukund Sivaraman, and Paul Wouters.
Authors' Addresses Authors' Addresses
Glenn S. Fowler Glenn S. Fowler
Google Google
Email: glenn.s.fowler@gmail.com Email: glenn.s.fowler@gmail.com
Landon Curt Noll Landon Curt Noll
Cisco Systems Cisco Systems
170 West Tasman Drive 170 West Tasman Drive
San Jose, California 95134 San Jose, California 95134
United States of America United States of America
Phone: +1-408-424-1102 Phone: +1-408-424-1102
Email: fnv-ietf7-mail@asthe.com Email: fnv-ietf8-mail@asthe.com
URI: http://www.isthe.com/chongo/index.html URI: http://www.isthe.com/chongo/index.html
Kiem-Phong Vo Kiem-Phong Vo
Google Google
Email: phongvo@gmail.com Email: phongvo@gmail.com
Donald E. Eastlake 3rd Donald E. Eastlake 3rd
Independent Independent
2386 Panoramic Circle 2386 Panoramic Circle
Apopka, Florida 32703 Apopka, Florida 32703
United States of America United States of America
Phone: +1-508-333-2270 Phone: +1-508-333-2270
Email: d3e3e3@gmail.com Email: d3e3e3@gmail.com
Tony Hansen Tony Hansen
AT&T AT&T
 End of changes. 247 change blocks. 
677 lines changed or deleted 456 lines changed or added

This html diff was produced by rfcdiff 1.48.