mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
minor refactoring of sha1 code
Update code style to better match project. Add more documentation. Add some C++ specific features to improve compatibility and reduce warnings with C++ applications. Add original project unit tests to WebSocket++ test suite.
This commit is contained in:
@@ -15,18 +15,22 @@ BOOST_LIBS = boostlibs(['unit_test_framework','system'],env) + [platform_libs]
|
||||
objs = env.Object('uri_boost.o', ["uri.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('utilities_boost.o', ["utilities.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('close_boost.o', ["close.cpp"], LIBS = BOOST_LIBS)
|
||||
objs += env.Object('sha1_boost.o', ["sha1.cpp"], LIBS = BOOST_LIBS)
|
||||
prgs = env.Program('test_uri_boost', ["uri_boost.o"], LIBS = BOOST_LIBS)
|
||||
prgs += env.Program('test_utility_boost', ["utilities_boost.o"], LIBS = BOOST_LIBS)
|
||||
prgs += env.Program('test_frame', ["frame.cpp"], LIBS = BOOST_LIBS)
|
||||
prgs += env.Program('test_close_boost', ["close_boost.o"], LIBS = BOOST_LIBS)
|
||||
prgs += env.Program('test_sha1_boost', ["sha1_boost.o"], LIBS = BOOST_LIBS)
|
||||
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
objs += env_cpp11.Object('utilities_stl.o', ["utilities.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
objs += env_cpp11.Object('uri_stl.o', ["uri.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
objs += env_cpp11.Object('close_stl.o', ["close.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
objs += env_cpp11.Object('sha1_stl.o', ["sha1.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_utility_stl', ["utilities_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_uri_stl', ["uri_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_close_stl', ["close_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
prgs += env_cpp11.Program('test_sha1_stl', ["sha1_stl.o"], LIBS = BOOST_LIBS_CPP11)
|
||||
|
||||
Return('prgs')
|
||||
|
||||
84
test/utility/sha1.cpp
Normal file
84
test/utility/sha1.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Peter Thorson. 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 the WebSocket++ Project 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 PETER THORSON 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.
|
||||
*
|
||||
*/
|
||||
//#define BOOST_TEST_DYN_LINK
|
||||
#define BOOST_TEST_MODULE sha1
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <websocketpp/sha1/sha1.hpp>
|
||||
#include <websocketpp/utilities.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE ( sha1 )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( sha1_test_a ) {
|
||||
websocketpp::sha1 sha;
|
||||
uint32_t digest[5];
|
||||
|
||||
sha << "abc";
|
||||
BOOST_CHECK(sha.get_raw_digest(digest));
|
||||
|
||||
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_AUTO_TEST_CASE( sha1_test_b ) {
|
||||
websocketpp::sha1 sha;
|
||||
uint32_t digest[5];
|
||||
|
||||
sha << "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
||||
BOOST_CHECK(sha.get_raw_digest(digest));
|
||||
|
||||
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_AUTO_TEST_CASE( sha1_test_c ) {
|
||||
websocketpp::sha1 sha;
|
||||
uint32_t digest[5];
|
||||
|
||||
for (int i = 1; i <= 1000000; i++) {
|
||||
sha.input('a');
|
||||
}
|
||||
|
||||
BOOST_CHECK(sha.get_raw_digest(digest));
|
||||
|
||||
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_AUTO_TEST_SUITE_END()
|
||||
@@ -614,12 +614,12 @@ protected:
|
||||
lib::error_code process_handshake_key(std::string & key) const {
|
||||
key.append(constants::handshake_guid);
|
||||
|
||||
SHA1 sha;
|
||||
uint32_t message_digest[5];
|
||||
sha1 sha;
|
||||
uint32_t message_digest[5];
|
||||
|
||||
sha << key.c_str();
|
||||
|
||||
if (sha.Result(message_digest)){
|
||||
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++) {
|
||||
|
||||
@@ -28,80 +28,73 @@
|
||||
#ifndef _SHA1_H_
|
||||
#define _SHA1_H_
|
||||
|
||||
#include <websocketpp/common/stdint.hpp>
|
||||
|
||||
namespace websocketpp {
|
||||
|
||||
/// Provides SHA1 hashing functionality
|
||||
class SHA1
|
||||
{
|
||||
public:
|
||||
class sha1 {
|
||||
public:
|
||||
sha1() {
|
||||
reset();
|
||||
}
|
||||
|
||||
SHA1() {
|
||||
Reset();
|
||||
}
|
||||
virtual ~SHA1() {}
|
||||
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;
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the message digest
|
||||
*/
|
||||
bool Result(unsigned *message_digest_array) {
|
||||
int i; // Counter
|
||||
|
||||
if (Corrupted)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Computed)
|
||||
{
|
||||
PadMessage();
|
||||
Computed = true;
|
||||
}
|
||||
|
||||
for(i = 0; i < 5; i++)
|
||||
{
|
||||
message_digest_array[i] = H[i];
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!computed) {
|
||||
pad_message();
|
||||
computed = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide input to SHA1
|
||||
*/
|
||||
void Input( const unsigned char *message_array,
|
||||
unsigned length)
|
||||
{
|
||||
if (!length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Computed || Corrupted)
|
||||
{
|
||||
Corrupted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
while(length-- && !Corrupted)
|
||||
{
|
||||
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.
|
||||
//
|
||||
@@ -111,246 +104,257 @@ class SHA1
|
||||
#pragma warning(push)
|
||||
#pragma warning(suppress: 6386)
|
||||
#endif
|
||||
Message_Block[Message_Block_Index++] = (*message_array & 0xFF);
|
||||
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)
|
||||
{
|
||||
ProcessMessageBlock();
|
||||
}
|
||||
|
||||
message_array++;
|
||||
}
|
||||
}
|
||||
void Input( const char *message_array,
|
||||
unsigned length)
|
||||
{
|
||||
Input((unsigned char *) message_array, length);
|
||||
}
|
||||
void Input(unsigned char message_element)
|
||||
{
|
||||
Input(&message_element, 1);
|
||||
}
|
||||
void Input(char message_element)
|
||||
{
|
||||
Input((unsigned char *) &message_element, 1);
|
||||
}
|
||||
SHA1& operator<<(const char *message_array)
|
||||
{
|
||||
const char *p = message_array;
|
||||
|
||||
while(*p)
|
||||
{
|
||||
Input(*p);
|
||||
p++;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
SHA1& operator<<(const unsigned char *message_array)
|
||||
{
|
||||
const unsigned char *p = message_array;
|
||||
|
||||
while(*p)
|
||||
{
|
||||
Input(*p);
|
||||
p++;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
SHA1& operator<<(const char message_element)
|
||||
{
|
||||
Input((unsigned char *) &message_element, 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
SHA1& operator<<(const unsigned char message_element)
|
||||
{
|
||||
Input(&message_element, 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
* Process the next 512 bits of the message
|
||||
*/
|
||||
void ProcessMessageBlock()
|
||||
{
|
||||
const unsigned K[] = { // Constants defined for SHA-1
|
||||
0x5A827999,
|
||||
0x6ED9EBA1,
|
||||
0x8F1BBCDC,
|
||||
0xCA62C1D6
|
||||
};
|
||||
int t; // Loop counter
|
||||
unsigned temp; // Temporary word value
|
||||
unsigned W[80]; // Word sequence
|
||||
unsigned A, B, C, D, E; // Word buffers
|
||||
|
||||
/*
|
||||
* Initialize the first 16 words in the array W
|
||||
*/
|
||||
for(t = 0; t < 16; t++)
|
||||
{
|
||||
W[t] = ((unsigned) Message_Block[t * 4]) << 24;
|
||||
W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
|
||||
W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
|
||||
W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
|
||||
}
|
||||
|
||||
for(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(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(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(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(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
|
||||
*/
|
||||
void PadMessage()
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
ProcessMessageBlock();
|
||||
|
||||
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;
|
||||
|
||||
ProcessMessageBlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a circular left shift operation
|
||||
*/
|
||||
inline unsigned CircularShift(int bits, unsigned word)
|
||||
{
|
||||
return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
|
||||
}
|
||||
|
||||
unsigned H[5]; // Message digest buffers
|
||||
|
||||
unsigned Length_Low; // Message length in bits
|
||||
unsigned 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?
|
||||
|
||||
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
|
||||
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
|
||||
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_
|
||||
|
||||
Reference in New Issue
Block a user