| 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 | |||
| 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 > 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 | |||
| 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 | |||
| 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. | ||||