mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
replaces sha1 library with a more clearly licensed project references #294
This commit is contained in:
@@ -37,48 +37,45 @@
|
||||
BOOST_AUTO_TEST_SUITE ( sha1 )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( sha1_test_a ) {
|
||||
websocketpp::sha1 sha;
|
||||
uint32_t digest[5];
|
||||
unsigned char hash[20];
|
||||
unsigned char reference[20] = {0xa9, 0x99, 0x3e, 0x36, 0x47,
|
||||
0x06, 0x81, 0x6a, 0xba, 0x3e,
|
||||
0x25, 0x71, 0x78, 0x50, 0xc2,
|
||||
0x6c, 0x9c, 0xd0, 0xd8, 0x9d};
|
||||
|
||||
sha << "abc";
|
||||
BOOST_CHECK(sha.get_raw_digest(digest));
|
||||
websocketpp::sha1::calc("abc",3,hash);
|
||||
|
||||
BOOST_CHECK_EQUAL( digest[0], 0xa9993e36 );
|
||||
BOOST_CHECK_EQUAL( digest[1], 0x4706816a );
|
||||
BOOST_CHECK_EQUAL( digest[2], 0xba3e2571 );
|
||||
BOOST_CHECK_EQUAL( digest[3], 0x7850c26c );
|
||||
BOOST_CHECK_EQUAL( digest[4], 0x9cd0d89d );
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(hash, hash+20, reference, reference+20);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( sha1_test_b ) {
|
||||
websocketpp::sha1 sha;
|
||||
uint32_t digest[5];
|
||||
unsigned char hash[20];
|
||||
unsigned char reference[20] = {0x84, 0x98, 0x3e, 0x44, 0x1c,
|
||||
0x3b, 0xd2, 0x6e, 0xba, 0xae,
|
||||
0x4a, 0xa1, 0xf9, 0x51, 0x29,
|
||||
0xe5, 0xe5, 0x46, 0x70, 0xf1};
|
||||
|
||||
sha << "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
||||
BOOST_CHECK(sha.get_raw_digest(digest));
|
||||
websocketpp::sha1::calc(
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",56,hash);
|
||||
|
||||
BOOST_CHECK_EQUAL( digest[0], 0x84983e44 );
|
||||
BOOST_CHECK_EQUAL( digest[1], 0x1c3bd26e );
|
||||
BOOST_CHECK_EQUAL( digest[2], 0xbaae4aa1 );
|
||||
BOOST_CHECK_EQUAL( digest[3], 0xf95129e5 );
|
||||
BOOST_CHECK_EQUAL( digest[4], 0xe54670f1 );
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(hash, hash+20, reference, reference+20);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( sha1_test_c ) {
|
||||
websocketpp::sha1 sha;
|
||||
uint32_t digest[5];
|
||||
std::string input;
|
||||
unsigned char hash[20];
|
||||
unsigned char reference[20] = {0x34, 0xaa, 0x97, 0x3c, 0xd4,
|
||||
0xc4, 0xda, 0xa4, 0xf6, 0x1e,
|
||||
0xeb, 0x2b, 0xdb, 0xad, 0x27,
|
||||
0x31, 0x65, 0x34, 0x01, 0x6f};
|
||||
|
||||
for (int i = 1; i <= 1000000; i++) {
|
||||
sha.input('a');
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
input += 'a';
|
||||
}
|
||||
|
||||
BOOST_CHECK(sha.get_raw_digest(digest));
|
||||
websocketpp::sha1::calc(input.c_str(),input.size(),hash);
|
||||
|
||||
BOOST_CHECK_EQUAL( digest[0], 0x34aa973c );
|
||||
BOOST_CHECK_EQUAL( digest[1], 0xd4c4daa4 );
|
||||
BOOST_CHECK_EQUAL( digest[2], 0xf61eeb2b );
|
||||
BOOST_CHECK_EQUAL( digest[3], 0xdbad2731 );
|
||||
BOOST_CHECK_EQUAL( digest[4], 0x6534016f );
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(hash, hash+20, reference, reference+20);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -614,27 +614,11 @@ protected:
|
||||
lib::error_code process_handshake_key(std::string & key) const {
|
||||
key.append(constants::handshake_guid);
|
||||
|
||||
sha1 sha;
|
||||
uint32_t message_digest[5];
|
||||
unsigned char message_digest[20];
|
||||
sha1::calc(key.c_str(),key.length(),message_digest);
|
||||
key = base64_encode(message_digest,20);
|
||||
|
||||
sha << key.c_str();
|
||||
|
||||
if (sha.get_raw_digest(message_digest)){
|
||||
// convert sha1 hash bytes to network byte order because this sha1
|
||||
// library works on ints rather than bytes
|
||||
for (int i = 0; i < 5; i++) {
|
||||
message_digest[i] = htonl(message_digest[i]);
|
||||
}
|
||||
|
||||
key = base64_encode(
|
||||
reinterpret_cast<unsigned char const *>(message_digest),
|
||||
20
|
||||
);
|
||||
|
||||
return lib::error_code();
|
||||
} else {
|
||||
return error::make_error_code(error::sha1_library);
|
||||
}
|
||||
return lib::error_code();
|
||||
}
|
||||
|
||||
/// Reads bytes from buf into m_basic_header
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
Copyright (C) 1998, 2009
|
||||
Paul E. Jones <paulej@packetizer.com>
|
||||
|
||||
Freeware Public License (FPL)
|
||||
|
||||
This software is licensed as "freeware." Permission to distribute
|
||||
this software in source and binary forms, including incorporation
|
||||
into other products, is hereby granted without a fee. THIS SOFTWARE
|
||||
IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR SHALL NOT BE HELD
|
||||
LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE, EITHER
|
||||
DIRECTLY OR INDIRECTLY, INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA
|
||||
OR DATA BEING RENDERED INACCURATE.
|
||||
185
websocketpp/sha1/sha1.cpp
Executable file
185
websocketpp/sha1/sha1.cpp
Executable file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
Copyright (c) 2011, Micael Hildenborg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Micael Hildenborg nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Contributors:
|
||||
Gustav
|
||||
Several members in the gamedev.se forum.
|
||||
Gregory Petrosyan
|
||||
*/
|
||||
|
||||
#include "sha1.h"
|
||||
|
||||
namespace sha1
|
||||
{
|
||||
namespace // local
|
||||
{
|
||||
// Rotate an integer value to left.
|
||||
inline const unsigned int rol(const unsigned int value,
|
||||
const unsigned int steps)
|
||||
{
|
||||
return ((value << steps) | (value >> (32 - steps)));
|
||||
}
|
||||
|
||||
// Sets the first 16 integers in the buffert to zero.
|
||||
// Used for clearing the W buffert.
|
||||
inline void clearWBuffert(unsigned int* buffert)
|
||||
{
|
||||
for (int pos = 16; --pos >= 0;)
|
||||
{
|
||||
buffert[pos] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void innerHash(unsigned int* result, unsigned int* w)
|
||||
{
|
||||
unsigned int a = result[0];
|
||||
unsigned int b = result[1];
|
||||
unsigned int c = result[2];
|
||||
unsigned int d = result[3];
|
||||
unsigned int e = result[4];
|
||||
|
||||
int round = 0;
|
||||
|
||||
#define sha1macro(func,val) \
|
||||
{ \
|
||||
const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
|
||||
e = d; \
|
||||
d = c; \
|
||||
c = rol(b, 30); \
|
||||
b = a; \
|
||||
a = t; \
|
||||
}
|
||||
|
||||
while (round < 16)
|
||||
{
|
||||
sha1macro((b & c) | (~b & d), 0x5a827999)
|
||||
++round;
|
||||
}
|
||||
while (round < 20)
|
||||
{
|
||||
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
|
||||
sha1macro((b & c) | (~b & d), 0x5a827999)
|
||||
++round;
|
||||
}
|
||||
while (round < 40)
|
||||
{
|
||||
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
|
||||
sha1macro(b ^ c ^ d, 0x6ed9eba1)
|
||||
++round;
|
||||
}
|
||||
while (round < 60)
|
||||
{
|
||||
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
|
||||
sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
|
||||
++round;
|
||||
}
|
||||
while (round < 80)
|
||||
{
|
||||
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
|
||||
sha1macro(b ^ c ^ d, 0xca62c1d6)
|
||||
++round;
|
||||
}
|
||||
|
||||
#undef sha1macro
|
||||
|
||||
result[0] += a;
|
||||
result[1] += b;
|
||||
result[2] += c;
|
||||
result[3] += d;
|
||||
result[4] += e;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void calc(const void* src, const int bytelength, unsigned char* hash)
|
||||
{
|
||||
// Init the result array.
|
||||
unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
|
||||
|
||||
// Cast the void src pointer to be the byte array we can work with.
|
||||
const unsigned char* sarray = (const unsigned char*) src;
|
||||
|
||||
// The reusable round buffer
|
||||
unsigned int w[80];
|
||||
|
||||
// Loop through all complete 64byte blocks.
|
||||
const int endOfFullBlocks = bytelength - 64;
|
||||
int endCurrentBlock;
|
||||
int currentBlock = 0;
|
||||
|
||||
while (currentBlock <= endOfFullBlocks)
|
||||
{
|
||||
endCurrentBlock = currentBlock + 64;
|
||||
|
||||
// Init the round buffer with the 64 byte block data.
|
||||
for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
|
||||
{
|
||||
// This line will swap endian on big endian and keep endian on little endian.
|
||||
w[roundPos++] = (unsigned int) sarray[currentBlock + 3]
|
||||
| (((unsigned int) sarray[currentBlock + 2]) << 8)
|
||||
| (((unsigned int) sarray[currentBlock + 1]) << 16)
|
||||
| (((unsigned int) sarray[currentBlock]) << 24);
|
||||
}
|
||||
innerHash(result, w);
|
||||
}
|
||||
|
||||
// Handle the last and not full 64 byte block if existing.
|
||||
endCurrentBlock = bytelength - currentBlock;
|
||||
clearWBuffert(w);
|
||||
int lastBlockBytes = 0;
|
||||
for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes)
|
||||
{
|
||||
w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3);
|
||||
}
|
||||
w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
|
||||
if (endCurrentBlock >= 56)
|
||||
{
|
||||
innerHash(result, w);
|
||||
clearWBuffert(w);
|
||||
}
|
||||
w[15] = bytelength << 3;
|
||||
innerHash(result, w);
|
||||
|
||||
// Store hash in result pointer, and make sure we get in in the correct order on both endian models.
|
||||
for (int hashByte = 20; --hashByte >= 0;)
|
||||
{
|
||||
hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void toHexString(const unsigned char* hash, char* hexstring)
|
||||
{
|
||||
const char hexDigits[] = { "0123456789abcdef" };
|
||||
|
||||
for (int hashByte = 20; --hashByte >= 0;)
|
||||
{
|
||||
hexstring[hashByte << 1] = hexDigits[(hash[hashByte] >> 4) & 0xf];
|
||||
hexstring[(hashByte << 1) + 1] = hexDigits[hash[hashByte] & 0xf];
|
||||
}
|
||||
hexstring[40] = 0;
|
||||
}
|
||||
} // namespace sha1
|
||||
49
websocketpp/sha1/sha1.h
Executable file
49
websocketpp/sha1/sha1.h
Executable file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright (c) 2011, Micael Hildenborg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Micael Hildenborg nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SHA1_DEFINED
|
||||
#define SHA1_DEFINED
|
||||
|
||||
namespace sha1
|
||||
{
|
||||
|
||||
/**
|
||||
@param src points to any kind of data to be hashed.
|
||||
@param bytelength the number of bytes to hash from the src pointer.
|
||||
@param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in.
|
||||
*/
|
||||
void calc(const void* src, const int bytelength, unsigned char* hash);
|
||||
|
||||
/**
|
||||
@param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function.
|
||||
@param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string.
|
||||
*/
|
||||
void toHexString(const unsigned char* hash, char* hexstring);
|
||||
|
||||
} // namespace sha1
|
||||
|
||||
#endif // SHA1_DEFINED
|
||||
@@ -1,406 +1,184 @@
|
||||
/*
|
||||
* sha1.hpp
|
||||
*
|
||||
* Copyright (C) 1998, 2009
|
||||
* Paul E. Jones <paulej@packetizer.com>
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Modifications were done in 2012-13 by Peter Thorson (webmaster@zaphoyd.com)
|
||||
* to allow header only usage of the library and use C++ features to better
|
||||
* support C++ usage. These changes are distributed under the original freeware
|
||||
* license included below
|
||||
*
|
||||
* Freeware Public License (FPL)
|
||||
*
|
||||
* This software is licensed as "freeware." Permission to distribute
|
||||
* this software in source and binary forms, including incorporation
|
||||
* into other products, is hereby granted without a fee. THIS SOFTWARE
|
||||
* IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR SHALL NOT BE HELD
|
||||
* LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE, EITHER
|
||||
* DIRECTLY OR INDIRECTLY, INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA
|
||||
* OR DATA BEING RENDERED INACCURATE.
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* Description:
|
||||
* This class implements the Secure Hashing Standard as defined
|
||||
* in FIPS PUB 180-1 published April 17, 1995.
|
||||
*
|
||||
* Many of the variable names in this class, especially the single
|
||||
* character names, were used because those were the names used
|
||||
* in the publication.
|
||||
*
|
||||
* The Secure Hashing Standard, which uses the Secure Hashing
|
||||
* Algorithm (SHA), produces a 160-bit message digest for a
|
||||
* given data stream. In theory, it is highly improbable that
|
||||
* two messages will produce the same message digest. Therefore,
|
||||
* this algorithm can serve as a means of providing a "fingerprint"
|
||||
* for a message.
|
||||
*
|
||||
* Portability Issues:
|
||||
* SHA-1 is defined in terms of 32-bit "words". This code was
|
||||
* written with the expectation that the processor has at least
|
||||
* a 32-bit machine word size. If the machine word size is larger,
|
||||
* the code should still function properly. One caveat to that
|
||||
* is that the input functions taking characters and character arrays
|
||||
* assume that only 8 bits of information are stored in each character.
|
||||
*
|
||||
* Caveats:
|
||||
* SHA-1 is designed to work with messages less than 2^64 bits long.
|
||||
* Although SHA-1 allows a message digest to be generated for
|
||||
* messages of any number of bits less than 2^64, this implementation
|
||||
* only works with messages with a length that is a multiple of 8
|
||||
* bits.
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _SHA1_H_
|
||||
#define _SHA1_H_
|
||||
|
||||
#include <websocketpp/common/stdint.hpp>
|
||||
|
||||
namespace websocketpp {
|
||||
|
||||
/// Provides SHA1 hashing functionality
|
||||
class sha1 {
|
||||
public:
|
||||
sha1() {
|
||||
reset();
|
||||
}
|
||||
|
||||
virtual ~sha1() {}
|
||||
|
||||
/// Re-initialize the class
|
||||
void reset() {
|
||||
length_low = 0;
|
||||
length_high = 0;
|
||||
message_block_index = 0;
|
||||
|
||||
H[0] = 0x67452301;
|
||||
H[1] = 0xEFCDAB89;
|
||||
H[2] = 0x98BADCFE;
|
||||
H[3] = 0x10325476;
|
||||
H[4] = 0xC3D2E1F0;
|
||||
|
||||
computed = false;
|
||||
corrupted = false;
|
||||
}
|
||||
|
||||
/// Extract the message digest as a raw integer array
|
||||
/**
|
||||
* @param [out] message_digest_array Integer array to store the message in
|
||||
* @return Whether or not the extraction was sucessful
|
||||
*/
|
||||
bool get_raw_digest(uint32_t * message_digest_array) {
|
||||
if (corrupted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!computed) {
|
||||
pad_message();
|
||||
computed = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
message_digest_array[i] = H[i];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Provide input to SHA1
|
||||
/**
|
||||
* @param [in] message_array The input bytes
|
||||
* @param [in] length Length of the message array
|
||||
*/
|
||||
void input(unsigned char const * message_array, uint32_t length) {
|
||||
if (!length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (computed || corrupted) {
|
||||
corrupted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
while (length-- && !corrupted) {
|
||||
// Suppresses Visual Studio code analysis for write overrun. It doesn't know the
|
||||
// index into Message_Block is protected by checking length.
|
||||
//
|
||||
// TODO: is there a more compatible way to write the original code to avoid
|
||||
// this sort of warning?
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(suppress: 6386)
|
||||
#endif
|
||||
message_block[message_block_index++] = (*message_array & 0xFF);
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
length_low += 8;
|
||||
length_low &= 0xFFFFFFFF; // Force it to 32 bits
|
||||
if (length_low == 0) {
|
||||
length_high++;
|
||||
length_high &= 0xFFFFFFFF; // Force it to 32 bits
|
||||
if (length_high == 0) {
|
||||
corrupted = true; // Message is too long
|
||||
}
|
||||
}
|
||||
|
||||
if (message_block_index == 64) {
|
||||
process_message_block();
|
||||
}
|
||||
|
||||
message_array++;
|
||||
}
|
||||
}
|
||||
|
||||
/// Provide input to SHA1
|
||||
/**
|
||||
* Overload with signed message array
|
||||
*
|
||||
* @param [in] message_array The input bytes
|
||||
* @param [in] length Length of the message array
|
||||
*/
|
||||
void input(char const * message_array, uint32_t length) {
|
||||
input(reinterpret_cast<const unsigned char *>(message_array), length);
|
||||
}
|
||||
|
||||
/// Provide input to SHA1
|
||||
/**
|
||||
* Overload with a single unsigned char
|
||||
*
|
||||
* @param [in] message_element The character to input
|
||||
*/
|
||||
void input(unsigned char message_element) {
|
||||
input(&message_element, 1);
|
||||
}
|
||||
|
||||
/// Provide input to SHA1
|
||||
/**
|
||||
* Overload with a single signed char
|
||||
*
|
||||
* @param [in] message_element The character to input
|
||||
*/
|
||||
void input(char message_element) {
|
||||
input(reinterpret_cast<unsigned char *>(&message_element), 1);
|
||||
}
|
||||
|
||||
/// Provide input to SHA1
|
||||
/**
|
||||
* Overload via signed char array stream input
|
||||
*
|
||||
* @param [in] message_array The character array to input
|
||||
*/
|
||||
sha1& operator<<(char const * message_array) {
|
||||
char const * p = message_array;
|
||||
|
||||
while(*p) {
|
||||
input(*p);
|
||||
p++;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Provide input to SHA1
|
||||
/**
|
||||
* Overload via unsigned char array stream input
|
||||
*
|
||||
* @param [in] message_array The character array to input
|
||||
*/
|
||||
sha1& operator<<(unsigned char const * message_array) {
|
||||
unsigned char const * p = message_array;
|
||||
|
||||
while(*p) {
|
||||
input(*p);
|
||||
p++;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Provide input to SHA1
|
||||
/**
|
||||
* Overload via signed char stream input
|
||||
*
|
||||
* @param [in] message_element The character to input
|
||||
*/
|
||||
sha1& operator<<(char message_element) {
|
||||
input((unsigned char *) &message_element, 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Provide input to SHA1
|
||||
/**
|
||||
* Overload via unsigned char stream input
|
||||
*
|
||||
* @param [in] message_element The character to input
|
||||
*/
|
||||
sha1& operator<<(unsigned char message_element) {
|
||||
input(&message_element, 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
/// Process the next 512 bits of the message
|
||||
/**
|
||||
* Many of the variable names in this function, especially the single
|
||||
* character names, were used because those were the names used
|
||||
* in the publication.
|
||||
*/
|
||||
void process_message_block() {
|
||||
// Constants defined for SHA-1
|
||||
uint32_t const K[] = { 0x5A827999,
|
||||
0x6ED9EBA1,
|
||||
0x8F1BBCDC,
|
||||
0xCA62C1D6 };
|
||||
uint32_t temp; // Temporary word value
|
||||
uint32_t W[80]; // Word sequence
|
||||
uint32_t A, B, C, D, E; // Word buffers
|
||||
|
||||
// Initialize the first 16 words in the array W
|
||||
for (int t = 0; t < 16; t++) {
|
||||
W[t] = ((uint32_t) message_block[t * 4]) << 24;
|
||||
W[t] |= ((uint32_t) message_block[t * 4 + 1]) << 16;
|
||||
W[t] |= ((uint32_t) message_block[t * 4 + 2]) << 8;
|
||||
W[t] |= ((uint32_t) message_block[t * 4 + 3]);
|
||||
}
|
||||
|
||||
for (int t = 16; t < 80; t++) {
|
||||
W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
|
||||
}
|
||||
|
||||
A = H[0];
|
||||
B = H[1];
|
||||
C = H[2];
|
||||
D = H[3];
|
||||
E = H[4];
|
||||
|
||||
for (int t = 0; t < 20; t++) {
|
||||
temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
|
||||
temp &= 0xFFFFFFFF;
|
||||
E = D;
|
||||
D = C;
|
||||
C = CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for (int t = 20; t < 40; t++) {
|
||||
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
|
||||
temp &= 0xFFFFFFFF;
|
||||
E = D;
|
||||
D = C;
|
||||
C = CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for (int t = 40; t < 60; t++) {
|
||||
temp = CircularShift(5,A) +
|
||||
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
|
||||
temp &= 0xFFFFFFFF;
|
||||
E = D;
|
||||
D = C;
|
||||
C = CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
for (int t = 60; t < 80; t++) {
|
||||
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
|
||||
temp &= 0xFFFFFFFF;
|
||||
E = D;
|
||||
D = C;
|
||||
C = CircularShift(30,B);
|
||||
B = A;
|
||||
A = temp;
|
||||
}
|
||||
|
||||
H[0] = (H[0] + A) & 0xFFFFFFFF;
|
||||
H[1] = (H[1] + B) & 0xFFFFFFFF;
|
||||
H[2] = (H[2] + C) & 0xFFFFFFFF;
|
||||
H[3] = (H[3] + D) & 0xFFFFFFFF;
|
||||
H[4] = (H[4] + E) & 0xFFFFFFFF;
|
||||
|
||||
message_block_index = 0;
|
||||
}
|
||||
|
||||
/// Pads the current message block to 512 bits
|
||||
/**
|
||||
* According to the standard, the message must be padded to an even
|
||||
* 512 bits. The first padding bit must be a '1'. The last 64 bits
|
||||
* represent the length of the original message. All bits in between
|
||||
* should be 0. This function will pad the message according to those
|
||||
* rules by filling the message_block array accordingly. It will also
|
||||
* call ProcessMessageBlock() appropriately. When it returns, it
|
||||
* can be assumed that the message digest has been computed.
|
||||
*/
|
||||
void pad_message() {
|
||||
// Check to see if the current message block is too small to hold
|
||||
// the initial padding bits and length. If so, we will pad the
|
||||
// block, process it, and then continue padding into a second block.
|
||||
if (message_block_index > 55) {
|
||||
message_block[message_block_index++] = 0x80;
|
||||
while(message_block_index < 64) {
|
||||
message_block[message_block_index++] = 0;
|
||||
}
|
||||
|
||||
process_message_block();
|
||||
|
||||
while(message_block_index < 56) {
|
||||
message_block[message_block_index++] = 0;
|
||||
}
|
||||
} else {
|
||||
message_block[message_block_index++] = 0x80;
|
||||
while(message_block_index < 56) {
|
||||
message_block[message_block_index++] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Store the message length as the last 8 octets
|
||||
message_block[56] = (length_high >> 24) & 0xFF;
|
||||
message_block[57] = (length_high >> 16) & 0xFF;
|
||||
message_block[58] = (length_high >> 8) & 0xFF;
|
||||
message_block[59] = (length_high) & 0xFF;
|
||||
message_block[60] = (length_low >> 24) & 0xFF;
|
||||
message_block[61] = (length_low >> 16) & 0xFF;
|
||||
message_block[62] = (length_low >> 8) & 0xFF;
|
||||
message_block[63] = (length_low) & 0xFF;
|
||||
|
||||
process_message_block();
|
||||
}
|
||||
|
||||
/// Performs a circular left shift operation
|
||||
/**
|
||||
* @param [in] bits How many bits to shift
|
||||
* @param [in] word The word to shift
|
||||
* @return The shifted word
|
||||
*/
|
||||
inline uint32_t CircularShift(int bits, uint32_t word) {
|
||||
return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
|
||||
}
|
||||
|
||||
uint32_t H[5]; // Message digest buffers
|
||||
|
||||
uint32_t length_low; // Message length in bits
|
||||
uint32_t length_high; // Message length in bits
|
||||
|
||||
unsigned char message_block[64]; // 512-bit message blocks
|
||||
int message_block_index; // Index into message block array
|
||||
|
||||
bool computed; // Is the digest computed?
|
||||
bool corrupted; // Is the message digest corruped?
|
||||
|
||||
};
|
||||
|
||||
} // namespace websocketpp
|
||||
|
||||
#endif // _SHA1_H_
|
||||
/*
|
||||
*****
|
||||
sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the shallsha1
|
||||
library (http://code.google.com/p/smallsha1/) into a single header suitable for
|
||||
use as a header only library. This conversion was done by Peter Thorson
|
||||
(webmaster@zaphoyd.com) in 2013. All modifications to the code are redistributed
|
||||
under the same license as the original, which is listed below.
|
||||
*****
|
||||
|
||||
Copyright (c) 2011, Micael Hildenborg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Micael Hildenborg nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SHA1_DEFINED
|
||||
#define SHA1_DEFINED
|
||||
|
||||
namespace websocketpp {
|
||||
namespace sha1 {
|
||||
|
||||
namespace // local
|
||||
{
|
||||
// Rotate an integer value to left.
|
||||
inline const unsigned int rol(const unsigned int value,
|
||||
const unsigned int steps)
|
||||
{
|
||||
return ((value << steps) | (value >> (32 - steps)));
|
||||
}
|
||||
|
||||
// Sets the first 16 integers in the buffert to zero.
|
||||
// Used for clearing the W buffert.
|
||||
inline void clearWBuffert(unsigned int* buffert)
|
||||
{
|
||||
for (int pos = 16; --pos >= 0;)
|
||||
{
|
||||
buffert[pos] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void innerHash(unsigned int* result, unsigned int* w)
|
||||
{
|
||||
unsigned int a = result[0];
|
||||
unsigned int b = result[1];
|
||||
unsigned int c = result[2];
|
||||
unsigned int d = result[3];
|
||||
unsigned int e = result[4];
|
||||
|
||||
int round = 0;
|
||||
|
||||
#define sha1macro(func,val) \
|
||||
{ \
|
||||
const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
|
||||
e = d; \
|
||||
d = c; \
|
||||
c = rol(b, 30); \
|
||||
b = a; \
|
||||
a = t; \
|
||||
}
|
||||
|
||||
while (round < 16)
|
||||
{
|
||||
sha1macro((b & c) | (~b & d), 0x5a827999)
|
||||
++round;
|
||||
}
|
||||
while (round < 20)
|
||||
{
|
||||
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
|
||||
sha1macro((b & c) | (~b & d), 0x5a827999)
|
||||
++round;
|
||||
}
|
||||
while (round < 40)
|
||||
{
|
||||
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
|
||||
sha1macro(b ^ c ^ d, 0x6ed9eba1)
|
||||
++round;
|
||||
}
|
||||
while (round < 60)
|
||||
{
|
||||
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
|
||||
sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
|
||||
++round;
|
||||
}
|
||||
while (round < 80)
|
||||
{
|
||||
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
|
||||
sha1macro(b ^ c ^ d, 0xca62c1d6)
|
||||
++round;
|
||||
}
|
||||
|
||||
#undef sha1macro
|
||||
|
||||
result[0] += a;
|
||||
result[1] += b;
|
||||
result[2] += c;
|
||||
result[3] += d;
|
||||
result[4] += e;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
@param src points to any kind of data to be hashed.
|
||||
@param bytelength the number of bytes to hash from the src pointer.
|
||||
@param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in.
|
||||
*/
|
||||
inline void calc(const void* src, const int bytelength, unsigned char* hash) {
|
||||
// Init the result array.
|
||||
unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
|
||||
|
||||
// Cast the void src pointer to be the byte array we can work with.
|
||||
const unsigned char* sarray = (const unsigned char*) src;
|
||||
|
||||
// The reusable round buffer
|
||||
unsigned int w[80];
|
||||
|
||||
// Loop through all complete 64byte blocks.
|
||||
const int endOfFullBlocks = bytelength - 64;
|
||||
int endCurrentBlock;
|
||||
int currentBlock = 0;
|
||||
|
||||
while (currentBlock <= endOfFullBlocks)
|
||||
{
|
||||
endCurrentBlock = currentBlock + 64;
|
||||
|
||||
// Init the round buffer with the 64 byte block data.
|
||||
for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
|
||||
{
|
||||
// This line will swap endian on big endian and keep endian on little endian.
|
||||
w[roundPos++] = (unsigned int) sarray[currentBlock + 3]
|
||||
| (((unsigned int) sarray[currentBlock + 2]) << 8)
|
||||
| (((unsigned int) sarray[currentBlock + 1]) << 16)
|
||||
| (((unsigned int) sarray[currentBlock]) << 24);
|
||||
}
|
||||
innerHash(result, w);
|
||||
}
|
||||
|
||||
// Handle the last and not full 64 byte block if existing.
|
||||
endCurrentBlock = bytelength - currentBlock;
|
||||
clearWBuffert(w);
|
||||
int lastBlockBytes = 0;
|
||||
for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes)
|
||||
{
|
||||
w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3);
|
||||
}
|
||||
w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
|
||||
if (endCurrentBlock >= 56)
|
||||
{
|
||||
innerHash(result, w);
|
||||
clearWBuffert(w);
|
||||
}
|
||||
w[15] = bytelength << 3;
|
||||
innerHash(result, w);
|
||||
|
||||
// Store hash in result pointer, and make sure we get in in the correct order on both endian models.
|
||||
for (int hashByte = 20; --hashByte >= 0;)
|
||||
{
|
||||
hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sha1
|
||||
} // namespace websocketpp
|
||||
|
||||
#endif // SHA1_DEFINED
|
||||
|
||||
Reference in New Issue
Block a user