273 lines
12 KiB
Plaintext
273 lines
12 KiB
Plaintext
VERSION:
|
|
|
|
This is version 1.0 RELEASE
|
|
|
|
While this is my "release" version, due to lack of additional
|
|
official test vectors against which to verify this implementation's
|
|
correctness, beware that there may be implementation bugs. Also,
|
|
it has not yet been tested on very many other architectures,
|
|
big-endian machines in particular.
|
|
|
|
|
|
LICENSE:
|
|
|
|
This implementation is released freely under an open-source BSD
|
|
license which appears at the top of each source code file.
|
|
|
|
|
|
WHAT IT IS:
|
|
|
|
The files sha2.h and sha2.c implement the SHA-256, SHA-384, and SHA-512
|
|
hash algorithms as described in the PDF document found at the following
|
|
web address:
|
|
|
|
http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
|
|
|
|
The interface is similar to the interface to SHA-1 found in the OpenSSL
|
|
library.
|
|
|
|
The file sha2prog.c is a simple program that accepts input from either
|
|
STDIN or reads one or more files specified on the command line, and then
|
|
generates the specified hash (either SHA-256, SHA-384, SHA-512, or any
|
|
combination thereof, including all three at once).
|
|
|
|
|
|
LIMITATIONS:
|
|
|
|
This implementation has several limitations:
|
|
|
|
* Input data is only accepted in octet-length increments. No sub-byte
|
|
data is handled. The NIST document describes how to handle sub-byte
|
|
input data, but for ease of implementation this version will only
|
|
accept message data in multiples of bytes.
|
|
* This implementation utilizes 64-bit integer data types. If your
|
|
system and compiler does not have a 64-bit integer data type, this
|
|
implementation will not work.
|
|
* Because of the use of 64-bit operations, many 32-bit architectures
|
|
that do have 64-bit data types but do operations most efficiently
|
|
on 32-bit words, this implementation may be slower than an
|
|
implementation designed to use only 32-bit words (emulating the
|
|
64-bit operations).
|
|
* On platforms with 128-bit integer data types, the SHA-384 and SHA-512
|
|
bit counters used by this implementation might be better off using
|
|
the 128-bit type instead of simulating it with two 64-bit integers.
|
|
* This implementation was written in C in hopes of portability and for
|
|
the fun of it during my spare time. It is probably not the most
|
|
efficient or fastest C implementation. I welcome suggestions,
|
|
however, that suggest ways to speed things up without breaking
|
|
portability. I also welcome suggestions to improve portability.
|
|
* As mentioned above, this code has NOT been thoroughly tested.
|
|
This is perhaps the most severe limitation.
|
|
|
|
|
|
BEFORE YOU COMPILE (OPTIONS):
|
|
|
|
Each of the options described below may either be defined in the sha2.h
|
|
header file (or in the sha2.c file in some cases), or on the command
|
|
line at compile time if your compiler supports such things. For
|
|
example:
|
|
|
|
#define SHA2_USE_INTTYPES_H
|
|
#define SHA2_UNROLL_TRANSFORM
|
|
|
|
Or:
|
|
|
|
cc -c -DSHA2_UNROLL_TRANSFORM sha2.c
|
|
cc -c -DBYTE_ORDER=4321 -DBIG_ENDIAN=4321 sha2.c
|
|
|
|
Here are the available options. Read on below for a description of
|
|
each one:
|
|
|
|
SHA2_USE_INTTYPES_H
|
|
SHA2_USE_MEMSET_MEMCPY/SHA2_USE_BZERO_BCOPY
|
|
SHA2_UNROLL_TRANSFORM
|
|
BYTE_ORDER (LITTLE_ENDIAN/BIG_ENDIAN)
|
|
|
|
* SHA2_USE_INTTYPES_H option:
|
|
By default, this code uses u_intXX_t data types for 8 bit, 32 bit, and
|
|
64 bit unsigned integer type definitions. Most BSD systems define these,
|
|
as does Linux. However, some (like Compaq's Tru64 Unix) may instead
|
|
use uintXX_t data types as defined by recent ANSI C standards and as
|
|
included in the inttypes.h header file. Those wanting to use inttypes.h
|
|
need to define this either in sha.h or at compile time.
|
|
|
|
On those systems where NEITHER definitions are available, you will need
|
|
to edit both sha2.h and sha2.c and define things by hand in the appropriate
|
|
sections.
|
|
|
|
* BYTE_ORDER definitions:
|
|
This code assumes that BYTE_ORDER will be defined by the system during
|
|
compile to either equal LITTLE_ENDIAN or BIG_ENDIAN. If your system
|
|
does not define these, you may need to define them by hand in the sha.c
|
|
file according to the byte ordering conventions of your system.
|
|
|
|
* SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY
|
|
The code in sha2.c can use either memset()/memcpy() for memory block
|
|
operations, or bzero()/mcopy(). If you define neither of these, the
|
|
code will default to memset()/memcpy(). You can define either at the
|
|
command line or in sha2.h or in sha2.c.
|
|
|
|
* SHA2_UNROLL_TRANSFORM
|
|
By defining this either on the command line or in sha2.h or sha2.c,
|
|
the code will use macros to partially "unroll" the SHA transform
|
|
function. This usually generates bigger executables. It CAN (but
|
|
not necessarily WILL) generate faster code when you tell your compiler
|
|
to optimize things. For example, on the FreeBSD and Linux x86 systems
|
|
I tested things on (using gcc), when I optimized with just -O2 and
|
|
unrolled the transform, the hash transform was faster by 15-30%. On
|
|
these same systems, if I did NO optimization, the unrolled transform
|
|
was SLOWER, much slower (I'm guessing because the code was breaking
|
|
the cache, but I'm not sure). Your mileage may vary.
|
|
|
|
|
|
PORTABILITY:
|
|
|
|
The code in sha2.c and sha2.h is intended to be portable. It may
|
|
require that you do a few #definitions in the .h file. I've successfully
|
|
compiled and tested the sha2.c and sha2.h code on Apple's OS X (on
|
|
a PPC), FreeBSD 4.1.1 on Intel, Linux on Intel, FreeBSD on the Alpha,
|
|
and even under Windows98SE using Metrowerks C. The utility/example
|
|
programs (sha2prog.c, sha2test.c, and sha2speed.c) will very likely
|
|
have more trouble in portability since they do I/O.
|
|
|
|
To get sha2.c/sha2.h working under Windows, I had to define
|
|
SHA2_USE_INTTYPES_H, BYTE_ORDER, LITTLE_ENDIAN, and had to comment
|
|
out the include of <sys/types.h> in sha2.h. With a bit more work
|
|
I got the test program to run and verified that all the test
|
|
cases passed.
|
|
|
|
|
|
SUGGESTIONS/BUG FIXES:
|
|
|
|
If you make changes to get it working on other architectures, if you fix
|
|
any bugs, or if you make changes that improve this implementation's
|
|
efficiency that would be relatively portable and you're willing to release
|
|
your changes under the same license, please send them to me for possible
|
|
inclusion in future versions.
|
|
|
|
If you know where I can find some additional test vectors, please let me
|
|
know.
|
|
|
|
|
|
CHANGE HISTORY:
|
|
|
|
0.8 to 0.9 - Fixed spelling errors, changed to u_intXX_t type usage,
|
|
removed names from prototypes, added prototypes to sha2.c,
|
|
and a few things I can't recall.
|
|
|
|
0.9 to 0.9.5 - Add a new define in sha2.c that permits one to compile
|
|
it to either use memcpy()/memset() or bcopy()/bzero()
|
|
for memory block copying and zeroing. Added support
|
|
for unrolled SHA-256/384/512 transform loops. Just
|
|
compile with SHA2_UNROLL_TRANSFORM to enable. It takes
|
|
longer to compile, but I hope it is a bit faster. I
|
|
need to do some test to see whether or not it is. Oh,
|
|
in sha2.c, you either need to define SHA2_USE_BZERO_BCOPY
|
|
or SHA2_USE_MEMSET_MEMCPY to choose which way you want
|
|
to compile. *Whew* It's amazing how quickly something
|
|
simple starts to grow more complex even in the span of
|
|
just a few hours. I didn't really intend to do this much.
|
|
0.9.5 to 0.9.6 - Added a test program (sha2test) which tests against several
|
|
known test vectors. WARNING: Some of the test output
|
|
hashes are NOT from NIST's documentation and are the
|
|
output of this implementation and so may be incorrect.
|
|
0.9.6 to 0.9.7 - Fixed a bug that could cause invalid output in certain
|
|
cases and added an assumed scenario where zero-length
|
|
data is hashed. Also changed the rotation macros to use
|
|
a temporary variable as this reduces the number of operations.
|
|
When data is fed in blocks of the right length, copying of
|
|
data is reduced in this version. Added SHAYXZ_Data()
|
|
functions for ease of hashing a set of data. Added another
|
|
file sha2speed.c for doing speed testing. Added another test
|
|
vector with a larger data size (16KB). Fixed u_intXX_t and
|
|
uintXX_t handling by adding a define for SHA2_USE_INTTYPES_H
|
|
as well as made a few other minor changes to get rid of
|
|
warnings when compiling on Compaq's Tru64 Unix.
|
|
0.9.7 to 0.9.8 - The bug fix in 0.9.7 was incomplete and in some cases made
|
|
things worse. I believe that 0.9.8 fixes the bug completely
|
|
so that output is correct. I cannot verify this, however,
|
|
because of the lack of test vectors against which to do such
|
|
verification. All versions correctly matched the very few
|
|
NIST-provided vectors, but unfortunately the bug only
|
|
appeared in longer message data sets.
|
|
0.9.8 to 0.9.9 - Fixed some really bad typos and mistakes on my part that
|
|
only affected big-endian systems. I didn't have direct
|
|
access for testing before this version. Thanks to
|
|
Lucas Marshall for giving me access to his OS X system.
|
|
0.9.9 to 1.0.0b1 Added a few more test samples and made a few changes to
|
|
make things easier compiling on several other platforms.
|
|
Also I experimented with alternate macro definitions
|
|
in the SHA2_UNROLL_TRANSFORM version (see sha2.slower.c)
|
|
and eliminated the T1 temporary variable (the compiler
|
|
would of course still use internal temporary storage
|
|
during expression evaluation, but I'd hoped the compiler
|
|
would be more efficient), but unfortunately under FreeBSD
|
|
4.1.1-STABLE on an x86 platform, the change slowed things
|
|
down.
|
|
1.0.0b1 to 1.0 RELEASE Fixed an off-by-one implementation bug that affected
|
|
SHA-256 when hashed data length L = 55 + 64 * X where X is
|
|
either zero or a positive integer, and another (basically
|
|
the same bug) bug in SHA-384 and SHA-512 that showed up when
|
|
hashed data lengths L = 111 + 128 * X. Thanks to Rogier
|
|
van de Pol for sending me test data that revealed the bug.
|
|
The fix was very simple (just two tiny changes). Also,
|
|
I finally put the files into RCS so future changes will be
|
|
easier to manage. The sha2prog.c file was rewritten to
|
|
be more useful to me, and I got rid of the old C testing
|
|
program and now use a perl script with a subdirectory full
|
|
of test data. It's a more flexible test system.
|
|
|
|
|
|
LATEST VERSION:
|
|
|
|
The latest version and documentation (if any ;) should always be available
|
|
on the web at:
|
|
|
|
http://www.aarongifford.com/computers/sha.html
|
|
|
|
|
|
CONTACT ME:
|
|
|
|
I can be reached via email at:
|
|
|
|
Aaron Gifford <m e @ a a r o n g i f f o r d . c o m>
|
|
|
|
Please don't send support questions. I don't have the time to answer and
|
|
they'll probably be ignored. Bug fixes, or patches that add something useful
|
|
will be gratefully accepted, however.
|
|
|
|
If you use this implementation, I would enjoy getting a brief email message
|
|
letting me know who you are and what use to which it is being put. There
|
|
is no requirement to do so. I just think it would be fun.
|
|
|
|
|
|
EXAMPLES:
|
|
|
|
Here's an example of compiling and using the sha2 program (in this example
|
|
I build it using the unrolled transform version with -O2 optimizations),
|
|
and then running the perl testing script:
|
|
|
|
cc -O2 -DSHA2_UNROLL_TRANSFORM -Wall -o sha2 sha2prog.c sha2.c
|
|
% ./sha2test.pl
|
|
|
|
[most of the perl script output deleted for brevity]
|
|
|
|
===== RESULTS (18 VECTOR DATA FILES HASHED) =====
|
|
|
|
HASH TYPE NO. OF TESTS PASSED FAILED
|
|
--------- ------------ ------ ------
|
|
SHA-256 18 18 0
|
|
SHA-384 18 18 0
|
|
SHA-512 18 18 0
|
|
----------------------------------------------
|
|
TOTAL: 54 54 0
|
|
|
|
NO ERRORS! ALL TESTS WERE SUCCESSFUL!
|
|
|
|
ALL TEST VECTORS PASSED!
|
|
|
|
That's all folks! Have fun!
|
|
|
|
Aaron out.
|
|
|