mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-06 06:56:23 +08:00
Co-authored-by: Andrew Le Bihan <andy@mcneel.com> Co-authored-by: Dale Fugier <dale@mcneel.com> Co-authored-by: Dale Lear <dalelear@mcneel.com> Co-authored-by: Greg Arden <greg@mcneel.com> Co-authored-by: Jussi <jussi@mcneel.com> Co-authored-by: Lowell <lowell@mcneel.com> Co-authored-by: Rajaa Issa <rajaa@mcneel.com> Co-authored-by: Steve Baer <steve@mcneel.com> Co-authored-by: alain <alain@mcneel.com> Co-authored-by: chuck <chuck@mcneel.com> Co-authored-by: piac <giulio@mcneel.com>
659 lines
16 KiB
C++
659 lines
16 KiB
C++
/*
|
|
//
|
|
// Copyright (c) 1993-2015 Robert McNeel & Associates. All rights reserved.
|
|
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
|
|
// McNeel & Associates.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
|
|
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
|
|
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
|
|
//
|
|
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
#if !defined(OPENNURBS_SHA1_INC_)
|
|
#define OPENNURBS_SHA1_INC_
|
|
|
|
class ON_CLASS ON_SHA1_Hash
|
|
{
|
|
public:
|
|
static const ON_SHA1_Hash ZeroDigest; // all digest bytes are zero
|
|
static const ON_SHA1_Hash EmptyContentHash; // SHA-1 hash of zero bytes
|
|
|
|
// The default constructor creates a zero digest sha1 hash
|
|
ON_SHA1_Hash();
|
|
|
|
~ON_SHA1_Hash() = default;
|
|
ON_SHA1_Hash(const ON_SHA1_Hash&) = default;
|
|
ON_SHA1_Hash& operator=(const ON_SHA1_Hash&) = default;
|
|
|
|
static int Compare(
|
|
const ON_SHA1_Hash& a,
|
|
const ON_SHA1_Hash& b
|
|
);
|
|
|
|
/*
|
|
Parameters:
|
|
buffer - [in]
|
|
sizeof_buffer - [in]
|
|
number of bytes in buffer
|
|
Returns:
|
|
SHA1-1 hash of the buffer.
|
|
*/
|
|
static ON_SHA1_Hash BufferContentHash(
|
|
const void* buffer,
|
|
size_t sizeof_buffer
|
|
);
|
|
|
|
/*
|
|
Parameters:
|
|
file_name - [in]
|
|
Name of file
|
|
sizeof_file - [out]
|
|
number of bytes in file
|
|
Returns:
|
|
SHA1-1 hash of the buffer.
|
|
*/
|
|
static ON_SHA1_Hash FileContentHash(
|
|
const wchar_t* file_name,
|
|
ON__UINT64& sizeof_file
|
|
);
|
|
|
|
static ON_SHA1_Hash FileContentHash(
|
|
const char* file_name,
|
|
ON__UINT64& sizeof_file
|
|
);
|
|
|
|
/*
|
|
Description:
|
|
Return a hash of the file system path that is independent
|
|
of the size of wchar_t, constant across platforms, and
|
|
constant across varations in the way the path is formatted.
|
|
|
|
Parameters:
|
|
path - [in]
|
|
File system path to a directory or file.
|
|
|
|
Returns:
|
|
SHA1-1 hash of the buffer.
|
|
|
|
Example:
|
|
These file system paths have identical values of FileSystemPathHash().
|
|
/x/y/z/name.ext
|
|
\x\y\z\name.ext
|
|
/x//y//z/name.ext
|
|
/x/y/a/b/c/../../../z/name.ext
|
|
/X/Y/Z/NAME.EXT (When ON_ComparePathIgnoreCase() is true)
|
|
|
|
Remarks:
|
|
This function uses the value of ON_FileSystemPath::PlatformPathIgnoreCase()
|
|
to determine if case should be ignored. Use the version with a bIgnoreCase
|
|
parameter if you want to explicitly control this decision.
|
|
*/
|
|
static ON_SHA1_Hash FileSystemPathHash(
|
|
const wchar_t* path
|
|
);
|
|
|
|
static ON_SHA1_Hash FileSystemPathHash(
|
|
const char* path
|
|
);
|
|
|
|
static ON_SHA1_Hash FileSystemPathHash(
|
|
const wchar_t* path,
|
|
bool bIgnoreCase
|
|
);
|
|
|
|
static ON_SHA1_Hash FileSystemPathHash(
|
|
const char* path,
|
|
bool bIgnoreCase
|
|
);
|
|
|
|
/*
|
|
Parameters:
|
|
file - [in]
|
|
File stream from ON_FileStream::Open(...,L"rb");
|
|
sizeof_file - [out]
|
|
number of bytes in file
|
|
Returns:
|
|
SHA1-1 hash of the file stream from the current
|
|
offset to the end of the file.
|
|
*/
|
|
static ON_SHA1_Hash FileContentHash(
|
|
FILE* file,
|
|
ON__UINT64& sizeof_file
|
|
);
|
|
|
|
/*
|
|
Parameters:
|
|
str - [in]
|
|
string
|
|
byte_count - [out]
|
|
number of bytes in UTF-8 encoding of the string.
|
|
Returns:
|
|
SHA1-1 hash of the UTF-8 encoding of the string. (Platforms and endian independent.)
|
|
*/
|
|
static ON_SHA1_Hash StringHash(
|
|
const ON_wString& str,
|
|
ON__UINT64& byte_count
|
|
);
|
|
|
|
static ON_SHA1_Hash StringHash(
|
|
const wchar_t* str,
|
|
size_t str_length,
|
|
ON__UINT64& byte_count
|
|
);
|
|
|
|
static ON_SHA1_Hash StringHash(
|
|
const wchar_t* null_terminated_string
|
|
);
|
|
|
|
/*
|
|
Parameters:
|
|
str - [in]
|
|
byte_count - [out]
|
|
number of bytes in the string.
|
|
Returns:
|
|
SHA1-1 hash of the UTF-8 encoding of the string. (Platforms and endian independent.)
|
|
*/
|
|
static ON_SHA1_Hash StringHash(
|
|
const ON_String& str,
|
|
ON__UINT64& byte_count
|
|
);
|
|
|
|
static ON_SHA1_Hash StringHash(
|
|
const char* str,
|
|
size_t str_length,
|
|
ON__UINT64& byte_count
|
|
);
|
|
|
|
|
|
static ON_SHA1_Hash StringHash(
|
|
const char* null_terminated_string
|
|
);
|
|
|
|
/*
|
|
Parameters:
|
|
bUpperCaseHexadecimalDigits - [in]
|
|
false - use 0-9, a-f
|
|
true - use 0-9, A-F
|
|
Returns:
|
|
The SHA-1 hash value as a 40 hexadecimal digits.
|
|
The first digit in the string is the hexadecimal value of m_digest[0].
|
|
*/
|
|
const ON_String ToUTF8String(
|
|
bool bUpperCaseHexadecimalDigits
|
|
) const;
|
|
|
|
/*
|
|
Parameters:
|
|
bUpperCaseHexadecimalDigits - [in]
|
|
false - use 0-9, a-f
|
|
true - use 0-9, A-F
|
|
Returns:
|
|
The SHA-1 hash value as a 40 hexadecimal digits.
|
|
The first digit in the string is the hexadecimal value of m_digest[0].
|
|
*/
|
|
const ON_wString ToString(
|
|
bool bUpperCaseHexadecimalDigits
|
|
) const;
|
|
|
|
/*
|
|
Description:
|
|
Same as ToString but prints EmptyContentSHA1 or ZeroSHA1 for those two special cases.
|
|
*/
|
|
const ON_wString ToStringEx(
|
|
bool bUpperCaseHexadecimalDigits
|
|
) const;
|
|
|
|
/*
|
|
Description:
|
|
Parse a string of 40 hexadecimal digits to create a SHA-1 hash.
|
|
Parameters:
|
|
string_to_parse - [in]
|
|
bParseLeadinglSpaces - [in]
|
|
If true, leading space characters are parsed.
|
|
Otherwise leading space characters cause parsing to fail.
|
|
bParseInteriorSpace - [in]
|
|
If true, interior space characters are parsed.
|
|
Otherwise interior space characters cause parsing to fail.
|
|
bParseInteriorHyphen - [in]
|
|
If true, interior hyphen characters are parsed.
|
|
Otherwise interior hyphen characters cause parsing to fail.
|
|
bIgnoreInternalSpaces - [in]
|
|
If true, isolated hyphens are ingored until 40 hex digits are read.
|
|
bIgnoreInternalHyphens - [in]
|
|
If true, leading spaces and isolated interior spacess are ingored until 40 hex digits are read.
|
|
failure_return_value - [in]
|
|
Value to return if string_to_parse cannot be parsed as 40 hex digits.
|
|
Returns:
|
|
If parsing is successful, the value of the SHA-1 hash is returned.
|
|
Otherwise failure_return_value is returned.
|
|
*/
|
|
static const ON_SHA1_Hash FromString(
|
|
const ON_wString string_to_parse,
|
|
bool bParseLeasingSpaces,
|
|
bool bParseInteriorSpace,
|
|
bool bParseInteriorHyphen,
|
|
ON_SHA1_Hash failure_return_value
|
|
);
|
|
|
|
bool Read(
|
|
class ON_BinaryArchive& archive
|
|
);
|
|
|
|
bool Write(
|
|
class ON_BinaryArchive& archive
|
|
) const;
|
|
|
|
void Dump(
|
|
class ON_TextLog& text_log
|
|
) const;
|
|
|
|
/*
|
|
Returns:
|
|
True if this and ON_SHA1_Hash::ZeroDigest have identical digest values.
|
|
*/
|
|
bool IsZeroDigest() const;
|
|
|
|
/*
|
|
Returns:
|
|
True if this and ON_SHA1_Hash::EmptyContentHash have identical digest values.
|
|
*/
|
|
bool IsEmptyContentHash() const;
|
|
|
|
bool IsZeroDigestOrEmptyContentHash() const;
|
|
|
|
ON_DEPRECATED_MSG("Use IsZeroDigestOrEmptyContentHash() instead. (Spelling error in this one's name.")
|
|
bool IsZeroDigentOrEmptyContentHash() const;
|
|
|
|
/*
|
|
Returns:
|
|
True if this hash is not equal to ON_SHA1_Hash::EmptyContentHash or ON_SHA1_Hash::ZeroDigest.
|
|
Remarks:
|
|
ON_SHA1_Hash::EmptyContentHash is the SHA1 of hasing zero bytes and has a non zero digest.
|
|
ON_SHA1_Hash::ZeroDigest is 20 bytes of zeros. Opennurbs uses ON_SHA1_Hash::ZeroDigest to
|
|
indicate a SHA1 has is not initialized.
|
|
*/
|
|
bool IsSet() const;
|
|
|
|
ON__UINT8 m_digest[20];
|
|
};
|
|
|
|
|
|
|
|
ON_DECL
|
|
bool operator==(const ON_SHA1_Hash& a, const ON_SHA1_Hash& b);
|
|
|
|
ON_DECL
|
|
bool operator!=(const ON_SHA1_Hash& a, const ON_SHA1_Hash& b);
|
|
|
|
/*
|
|
Description:
|
|
ON_SHA1 is a small class for calculating the SHA-1 hash of a sequence of bytes.
|
|
It may be use incrementally (the bytes do not have to be in a contiguous
|
|
array in memory at one time).
|
|
|
|
Remarks:
|
|
The ON_SHA1 class cannot be used for cryptographic or security applications.
|
|
The SHA-1 hash algorithm is not suitable for cryptographic or security applications.
|
|
The ON_SHA1 class does not "wipe" intermediate results.
|
|
|
|
If you have two different seqences of N bytes storing information (lower entropy
|
|
than a random sequence) are you are not intentionally calculating the information
|
|
to create a SHA-1 hash collision, then the probability that the sequences have
|
|
the same SHA-1 hash is approximately 2^-80 ~ 10^-24.
|
|
*/
|
|
class ON_CLASS ON_SHA1
|
|
{
|
|
public:
|
|
|
|
ON_SHA1() = default;
|
|
~ON_SHA1() = default;
|
|
ON_SHA1(const ON_SHA1&) = default;
|
|
ON_SHA1& operator=(const ON_SHA1&) = default;
|
|
|
|
/*
|
|
Description:
|
|
Make one or more calls to AccumulateBytes() as the sequenence of bytes is available.
|
|
|
|
Parameters:
|
|
buffer - [in]
|
|
sizeof_buffer - [in]
|
|
number of bytes in buffer
|
|
*/
|
|
#if defined(ON_COMPILER_MSC) && defined(NDEBUG)
|
|
// Reduces release build link time optimization by several hours for
|
|
// large programs that make lots of calls to ON_SHA1.Accumulate*() functions.
|
|
__declspec(noinline)
|
|
#endif
|
|
void AccumulateBytes(
|
|
const void* buffer,
|
|
ON__UINT64 sizeof_buffer
|
|
);
|
|
|
|
/*
|
|
Description:
|
|
Add the double value to the SHA1 in a manner that
|
|
-0.0 and +0.0 will generate identical SHA-1 values
|
|
and the result is independent of endian byte order.
|
|
*/
|
|
void AccumulateDouble(
|
|
double x
|
|
);
|
|
|
|
/*
|
|
Description:
|
|
Add the double value to the SHA1 in a manner that
|
|
-0.0 and +0.0 will generate identical SHA-1 values
|
|
and the result is independent of endian byte order.
|
|
*/
|
|
void AccumulateDoubleArray(
|
|
size_t count,
|
|
const double* a
|
|
);
|
|
|
|
/*
|
|
Description:
|
|
Add the double value to the SHA1 in a manner that
|
|
-0.0 and +0.0 will generate identical SHA-1 values
|
|
and the result is independent of endian byte order.
|
|
*/
|
|
void AccumulateFloat(
|
|
float x
|
|
);
|
|
|
|
/*
|
|
Description:
|
|
Add the double value to the SHA1 in a manner that
|
|
-0.0 and +0.0 will generate identical SHA-1 values
|
|
and the result is independent of endian byte order.
|
|
*/
|
|
void AccumulateFloatArray(
|
|
size_t count,
|
|
const float* a
|
|
);
|
|
|
|
void Accumulate2fPoint(
|
|
const class ON_2fPoint& point
|
|
);
|
|
|
|
void Accumulate3fPoint(
|
|
const class ON_3fPoint& point
|
|
);
|
|
|
|
void Accumulate4fPoint(
|
|
const class ON_4fPoint& point
|
|
);
|
|
|
|
void Accumulate2fVector(
|
|
const class ON_2fVector& vector
|
|
);
|
|
|
|
void Accumulate3fVector(
|
|
const class ON_3fVector& vector
|
|
);
|
|
|
|
void Accumulate2dPoint(
|
|
const class ON_2dPoint& point
|
|
);
|
|
|
|
void Accumulate3dPoint(
|
|
const class ON_3dPoint& point
|
|
);
|
|
|
|
void Accumulate4dPoint(
|
|
const class ON_4dPoint& point
|
|
);
|
|
|
|
void Accumulate2dVector(
|
|
const class ON_2dVector& vector
|
|
);
|
|
|
|
void Accumulate3dVector(
|
|
const class ON_3dVector& vector
|
|
);
|
|
|
|
void AccumulateBoundingBox(
|
|
const class ON_BoundingBox& bbox
|
|
);
|
|
|
|
void AccumulateUnitSystem(
|
|
const class ON_UnitSystem& unit_system
|
|
);
|
|
|
|
void AccumulateLengthUnitSystem(
|
|
const ON::LengthUnitSystem length_unit_system
|
|
);
|
|
|
|
/*
|
|
Description:
|
|
Accumuates the full and relative path names.
|
|
*/
|
|
void AccumulateFileReference(
|
|
const class ON_FileReference& file_reference
|
|
);
|
|
|
|
void AccumulateTransformation(
|
|
const class ON_Xform& xform
|
|
);
|
|
|
|
void AccumulateInteger8(
|
|
ON__INT8 i
|
|
);
|
|
|
|
void AccumulateUnsigned8(
|
|
ON__UINT8 u
|
|
);
|
|
|
|
void AccumulateInteger16(
|
|
ON__INT16 i
|
|
);
|
|
|
|
void AccumulateUnsigned16(
|
|
ON__UINT16 u
|
|
);
|
|
|
|
void AccumulateInteger32(
|
|
ON__INT32 i
|
|
);
|
|
|
|
void AccumulateInteger32Array(
|
|
size_t count,
|
|
const ON__INT32* a
|
|
);
|
|
|
|
void AccumulateUnsigned32(
|
|
ON__UINT32 u
|
|
);
|
|
|
|
void AccumulateInteger64(
|
|
ON__INT64 i
|
|
);
|
|
|
|
void AccumulateUnsigned64(
|
|
ON__UINT64 u
|
|
);
|
|
|
|
|
|
void AccumulateBool(
|
|
bool b
|
|
);
|
|
|
|
|
|
void AccumulateString(
|
|
const class ON_String& str
|
|
);
|
|
|
|
void AccumulateString(
|
|
const class ON_wString& str
|
|
);
|
|
|
|
void AccumulateId(
|
|
const ON_UUID& id
|
|
);
|
|
|
|
void AccumulateString(
|
|
const char* sUTF8,
|
|
int element_count,
|
|
ON_StringMapOrdinalType mapping
|
|
);
|
|
|
|
void AccumulateString(
|
|
const wchar_t* sUTF8,
|
|
int element_count,
|
|
ON_StringMapOrdinalType mapping
|
|
);
|
|
|
|
void AccumulateString(
|
|
const class ON_String& str,
|
|
ON_StringMapOrdinalType mapping
|
|
);
|
|
|
|
void AccumulateString(
|
|
const class ON_wString& str,
|
|
ON_StringMapOrdinalType mapping
|
|
);
|
|
|
|
|
|
void AccumulateSubHash(
|
|
const class ON_SHA1_Hash& sub_hash
|
|
);
|
|
|
|
private:
|
|
void Internal_SwapBigEndianUpdate(
|
|
const void* buffer,
|
|
ON__UINT64 sizeof_buffer
|
|
);
|
|
|
|
public:
|
|
/*
|
|
Returns:
|
|
Total number of bytes passed to Update().
|
|
*/
|
|
ON__UINT64 ByteCount() const;
|
|
|
|
/*
|
|
Returns:
|
|
SHA-1 hash value of the sequenence of ByteCount() bytes that have been
|
|
passed to this ON_SHA1 classe's Update() function since construction
|
|
or the last call to Reset().
|
|
Remarks:
|
|
You may use Hash() to compute intermediate SHA-1 hash values.
|
|
|
|
Put another way, you may call Update() zero or more times passing in N1 bytes,
|
|
call Digest() to get the SHA-1 hash of those N1 bytes, make zero or more additional
|
|
calls to Update() passing in N2 additional bytes, call digest to get the SHA-1 hash
|
|
of the seqence of (N1 + N2) bytes, and so on.
|
|
*/
|
|
ON_SHA1_Hash Hash() const;
|
|
|
|
/*
|
|
Description:
|
|
Reset this ON_SHA1 class so it can be reused.
|
|
*/
|
|
void Reset();
|
|
|
|
/*
|
|
Description:
|
|
This is a static function that uses ON_SHA1 to compute SHA-1 hash values
|
|
of sequences of bytes with known SHA-1 hash values and compares the
|
|
results from ON_SHA1 with the known SHA-1 hash values.
|
|
|
|
This function can be used to validate the ON_SHA1 class compiled correctly.
|
|
|
|
Returns:
|
|
true
|
|
All validation tests passed.
|
|
false
|
|
At least one validation test failed.
|
|
*/
|
|
static bool Validate();
|
|
|
|
private:
|
|
void Internal_Accumulate(const ON__UINT8* input, ON__UINT32 length);
|
|
void set_final_hash();
|
|
|
|
ON__UINT64 m_byte_count = 0; // number of bytes that have passed through calls to update().
|
|
// if 1 == m_status_bits & 1, then update has been called at least once (perhaps with 0 bytes).
|
|
// if 2 == m_status_bits & 2, then m_sha1_hash is current.
|
|
mutable ON__UINT32 m_status_bits = 0;
|
|
ON__UINT32 m_reserved = 0;
|
|
|
|
// current "remainder"
|
|
ON__UINT8 m_buffer[64]; // bytes that didn't fit in last 64 byte chunk
|
|
ON__UINT32 m_bit_count[2]; // number of bits (lo, hi)
|
|
ON__UINT32 m_state[5]; // current state
|
|
|
|
// chached SHA1 hash - valid if 2 = (2 & m_status_bits)
|
|
mutable ON_SHA1_Hash m_sha1_hash;
|
|
};
|
|
|
|
/*
|
|
Description:
|
|
Test speeds of various hash algoritmhs.
|
|
Parameters:
|
|
byte_count - [in]
|
|
Number of bytes to hash. This number is rounded up to the nearest multiple of 1024.
|
|
crc16 - [in/out]
|
|
If crc16 is not nullptr, then 16 bit CRC hashing is tested using function ON_CRC16().
|
|
crc32 - [in/out]
|
|
If crc32 is not nullptr, then 32 bit CRC hashing is tested using function ON_CRC32().
|
|
md5_hash - [in/out]
|
|
If md5_hash is not nullptr, then MD5 hashing is tested using class ON_MD5.
|
|
sha1_hash - [in/out]
|
|
If sha1_hash is not nullptr, then SHA-1 hashing is tested class ON_SHA1.
|
|
elapsed_time_in_seconds - [out]
|
|
elapsed_time_in_seconds[0] = 16 bit CRC hash time in seconds.
|
|
elapsed_time_in_seconds[1] = 32 bit CRC hash time in seconds.
|
|
elapsed_time_in_seconds[2] = MD5 hash time in seconds.
|
|
elapsed_time_in_seconds[3] = SHA-1 hash time in seconds.
|
|
If a hash was tested, then number of seconds it took to compute the hash is returned.
|
|
Otherwise ON_DBL_QNAN is returned.
|
|
*/
|
|
ON_DECL
|
|
void ON_TestHashSpeed(
|
|
size_t byte_count,
|
|
ON__UINT16* crc16,
|
|
ON__UINT32* crc32,
|
|
ON_MD5_Hash* md5_hash,
|
|
ON_SHA1_Hash* sha1_hash,
|
|
double elapsed_time_in_seconds[4]
|
|
);
|
|
|
|
/*
|
|
Description:
|
|
Test speeds of various hash algoritmhs and use text_log to print the results.
|
|
Parameters:
|
|
byte_count - [in]
|
|
Number of bytes to hash. This number is rounded up to the nearest multiple of 1024.
|
|
bCRC16 - [in]
|
|
True to test 16 bit CRC hashing speed.
|
|
bCRC32 - [in]
|
|
True to test 32 bit CRC hashing speed.
|
|
bMD5 - [in]
|
|
True to test MD5 hashing speed.
|
|
bSHA1 - [in]
|
|
True to test SHA-1 hashing speed.
|
|
text_log - [in]
|
|
Test results are printed using text_log.
|
|
*/
|
|
ON_DECL
|
|
void ON_TestHashSpeed(
|
|
size_t byte_count,
|
|
bool bTestCRC16,
|
|
bool bTestCRC32,
|
|
bool bTestMD5,
|
|
bool bTestSHA1,
|
|
ON_TextLog& text_log
|
|
);
|
|
|
|
ON_DECL
|
|
void ON_TestHashSpeed(
|
|
size_t byte_count,
|
|
ON_TextLog& text_log
|
|
);
|
|
|
|
#endif
|