232 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			232 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								// boost/uuid/sha1.hpp header file  ----------------------------------------------//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Copyright 2007 Andy Tompkins.
							 | 
						||
| 
								 | 
							
								// Distributed under the Boost Software License, Version 1.0. (See
							 | 
						||
| 
								 | 
							
								// accompanying file LICENSE_1_0.txt or copy at
							 | 
						||
| 
								 | 
							
								// http://www.boost.org/LICENSE_1_0.txt)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Revision History
							 | 
						||
| 
								 | 
							
								//  29 May 2007 - Initial Revision
							 | 
						||
| 
								 | 
							
								//  25 Feb 2008 - moved to namespace boost::uuids::detail
							 | 
						||
| 
								 | 
							
								//  10 Jan 2012 - can now handle the full size of messages (2^64 - 1 bits)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// This is a byte oriented implementation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_UUID_SHA1_H
							 | 
						||
| 
								 | 
							
								#define BOOST_UUID_SHA1_H
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/static_assert.hpp>
							 | 
						||
| 
								 | 
							
								#include <stdexcept>
							 | 
						||
| 
								 | 
							
								#include <boost/throw_exception.hpp>
							 | 
						||
| 
								 | 
							
								#include <cstddef>
							 | 
						||
| 
								 | 
							
								#include <string>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_NO_STDC_NAMESPACE
							 | 
						||
| 
								 | 
							
								namespace std {
							 | 
						||
| 
								 | 
							
								    using ::size_t;
							 | 
						||
| 
								 | 
							
								} // namespace std
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost {
							 | 
						||
| 
								 | 
							
								namespace uuids {
							 | 
						||
| 
								 | 
							
								namespace detail {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOST_STATIC_ASSERT(sizeof(unsigned char)*8 == 8);
							 | 
						||
| 
								 | 
							
								BOOST_STATIC_ASSERT(sizeof(unsigned int)*8 == 32);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline unsigned int left_rotate(unsigned int x, std::size_t n)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return (x<<n) ^ (x>> (32-n));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class sha1
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    typedef unsigned int(&digest_type)[5];
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    sha1();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void reset();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void process_byte(unsigned char byte);
							 | 
						||
| 
								 | 
							
								    void process_block(void const* bytes_begin, void const* bytes_end);
							 | 
						||
| 
								 | 
							
								    void process_bytes(void const* buffer, std::size_t byte_count);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void get_digest(digest_type digest);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    void process_block();
							 | 
						||
| 
								 | 
							
								    void process_byte_impl(unsigned char byte);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    unsigned int h_[5];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    unsigned char block_[64];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    std::size_t block_byte_index_;
							 | 
						||
| 
								 | 
							
								    std::size_t bit_count_low;
							 | 
						||
| 
								 | 
							
								    std::size_t bit_count_high;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline sha1::sha1()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    reset();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline void sha1::reset()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    h_[0] = 0x67452301;
							 | 
						||
| 
								 | 
							
								    h_[1] = 0xEFCDAB89;
							 | 
						||
| 
								 | 
							
								    h_[2] = 0x98BADCFE;
							 | 
						||
| 
								 | 
							
								    h_[3] = 0x10325476;
							 | 
						||
| 
								 | 
							
								    h_[4] = 0xC3D2E1F0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    block_byte_index_ = 0;
							 | 
						||
| 
								 | 
							
								    bit_count_low = 0;
							 | 
						||
| 
								 | 
							
								    bit_count_high = 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline void sha1::process_byte(unsigned char byte)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    process_byte_impl(byte);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // size_t max value = 0xFFFFFFFF
							 | 
						||
| 
								 | 
							
								    //if (bit_count_low + 8 >= 0x100000000) { // would overflow
							 | 
						||
| 
								 | 
							
								    //if (bit_count_low >= 0x100000000-8) {
							 | 
						||
| 
								 | 
							
								    if (bit_count_low < 0xFFFFFFF8) {
							 | 
						||
| 
								 | 
							
								        bit_count_low += 8;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        bit_count_low = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (bit_count_high <= 0xFFFFFFFE) {
							 | 
						||
| 
								 | 
							
								            ++bit_count_high;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            BOOST_THROW_EXCEPTION(std::runtime_error("sha1 too many bytes"));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline void sha1::process_byte_impl(unsigned char byte)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    block_[block_byte_index_++] = byte;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (block_byte_index_ == 64) {
							 | 
						||
| 
								 | 
							
								        block_byte_index_ = 0;
							 | 
						||
| 
								 | 
							
								        process_block();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline void sha1::process_block(void const* bytes_begin, void const* bytes_end)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    unsigned char const* begin = static_cast<unsigned char const*>(bytes_begin);
							 | 
						||
| 
								 | 
							
								    unsigned char const* end = static_cast<unsigned char const*>(bytes_end);
							 | 
						||
| 
								 | 
							
								    for(; begin != end; ++begin) {
							 | 
						||
| 
								 | 
							
								        process_byte(*begin);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline void sha1::process_bytes(void const* buffer, std::size_t byte_count)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    unsigned char const* b = static_cast<unsigned char const*>(buffer);
							 | 
						||
| 
								 | 
							
								    process_block(b, b+byte_count);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline void sha1::process_block()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    unsigned int w[80];
							 | 
						||
| 
								 | 
							
								    for (std::size_t i=0; i<16; ++i) {
							 | 
						||
| 
								 | 
							
								        w[i]  = (block_[i*4 + 0] << 24);
							 | 
						||
| 
								 | 
							
								        w[i] |= (block_[i*4 + 1] << 16);
							 | 
						||
| 
								 | 
							
								        w[i] |= (block_[i*4 + 2] << 8);
							 | 
						||
| 
								 | 
							
								        w[i] |= (block_[i*4 + 3]);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    for (std::size_t i=16; i<80; ++i) {
							 | 
						||
| 
								 | 
							
								        w[i] = left_rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    unsigned int a = h_[0];
							 | 
						||
| 
								 | 
							
								    unsigned int b = h_[1];
							 | 
						||
| 
								 | 
							
								    unsigned int c = h_[2];
							 | 
						||
| 
								 | 
							
								    unsigned int d = h_[3];
							 | 
						||
| 
								 | 
							
								    unsigned int e = h_[4];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (std::size_t i=0; i<80; ++i) {
							 | 
						||
| 
								 | 
							
								        unsigned int f;
							 | 
						||
| 
								 | 
							
								        unsigned int k;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (i<20) {
							 | 
						||
| 
								 | 
							
								            f = (b & c) | (~b & d);
							 | 
						||
| 
								 | 
							
								            k = 0x5A827999;
							 | 
						||
| 
								 | 
							
								        } else if (i<40) {
							 | 
						||
| 
								 | 
							
								            f = b ^ c ^ d;
							 | 
						||
| 
								 | 
							
								            k = 0x6ED9EBA1;
							 | 
						||
| 
								 | 
							
								        } else if (i<60) {
							 | 
						||
| 
								 | 
							
								            f = (b & c) | (b & d) | (c & d);
							 | 
						||
| 
								 | 
							
								            k = 0x8F1BBCDC;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            f = b ^ c ^ d;
							 | 
						||
| 
								 | 
							
								            k = 0xCA62C1D6;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        unsigned temp = left_rotate(a, 5) + f + e + k + w[i];
							 | 
						||
| 
								 | 
							
								        e = d;
							 | 
						||
| 
								 | 
							
								        d = c;
							 | 
						||
| 
								 | 
							
								        c = left_rotate(b, 30);
							 | 
						||
| 
								 | 
							
								        b = a;
							 | 
						||
| 
								 | 
							
								        a = temp;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    h_[0] += a;
							 | 
						||
| 
								 | 
							
								    h_[1] += b;
							 | 
						||
| 
								 | 
							
								    h_[2] += c;
							 | 
						||
| 
								 | 
							
								    h_[3] += d;
							 | 
						||
| 
								 | 
							
								    h_[4] += e;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline void sha1::get_digest(digest_type digest)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // append the bit '1' to the message
							 | 
						||
| 
								 | 
							
								    process_byte_impl(0x80);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // append k bits '0', where k is the minimum number >= 0
							 | 
						||
| 
								 | 
							
								    // such that the resulting message length is congruent to 56 (mod 64)
							 | 
						||
| 
								 | 
							
								    // check if there is enough space for padding and bit_count
							 | 
						||
| 
								 | 
							
								    if (block_byte_index_ > 56) {
							 | 
						||
| 
								 | 
							
								        // finish this block
							 | 
						||
| 
								 | 
							
								        while (block_byte_index_ != 0) {
							 | 
						||
| 
								 | 
							
								            process_byte_impl(0);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // one more block
							 | 
						||
| 
								 | 
							
								        while (block_byte_index_ < 56) {
							 | 
						||
| 
								 | 
							
								            process_byte_impl(0);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        while (block_byte_index_ < 56) {
							 | 
						||
| 
								 | 
							
								            process_byte_impl(0);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // append length of message (before pre-processing) 
							 | 
						||
| 
								 | 
							
								    // as a 64-bit big-endian integer
							 | 
						||
| 
								 | 
							
								    process_byte_impl( static_cast<unsigned char>((bit_count_high>>24) & 0xFF) );
							 | 
						||
| 
								 | 
							
								    process_byte_impl( static_cast<unsigned char>((bit_count_high>>16) & 0xFF) );
							 | 
						||
| 
								 | 
							
								    process_byte_impl( static_cast<unsigned char>((bit_count_high>>8 ) & 0xFF) );
							 | 
						||
| 
								 | 
							
								    process_byte_impl( static_cast<unsigned char>((bit_count_high)     & 0xFF) );
							 | 
						||
| 
								 | 
							
								    process_byte_impl( static_cast<unsigned char>((bit_count_low>>24) & 0xFF) );
							 | 
						||
| 
								 | 
							
								    process_byte_impl( static_cast<unsigned char>((bit_count_low>>16) & 0xFF) );
							 | 
						||
| 
								 | 
							
								    process_byte_impl( static_cast<unsigned char>((bit_count_low>>8 ) & 0xFF) );
							 | 
						||
| 
								 | 
							
								    process_byte_impl( static_cast<unsigned char>((bit_count_low)     & 0xFF) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // get final digest
							 | 
						||
| 
								 | 
							
								    digest[0] = h_[0];
							 | 
						||
| 
								 | 
							
								    digest[1] = h_[1];
							 | 
						||
| 
								 | 
							
								    digest[2] = h_[2];
							 | 
						||
| 
								 | 
							
								    digest[3] = h_[3];
							 | 
						||
| 
								 | 
							
								    digest[4] = h_[4];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}}} // namespace boost::uuids::detail
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 |