fix checksum/sha1

This commit is contained in:
bolero-MURAKAMI 2012-08-06 22:29:17 +09:00
parent 48adf49ef3
commit 30241d3be6
2 changed files with 141 additions and 70 deletions

View file

@ -12,6 +12,7 @@
#include <sprout/container/functions.hpp> #include <sprout/container/functions.hpp>
#include <sprout/iterator/operation.hpp> #include <sprout/iterator/operation.hpp>
#include <sprout/iterator/bytes_iterator.hpp> #include <sprout/iterator/bytes_iterator.hpp>
#include <sprout/algorithm/fixed/fill.hpp>
#include <sprout/range/algorithm/fixed/copy.hpp> #include <sprout/range/algorithm/fixed/copy.hpp>
#include <sprout/operation/fixed/set.hpp> #include <sprout/operation/fixed/set.hpp>
@ -19,7 +20,8 @@ namespace sprout {
static_assert(CHAR_BIT == 8, "CHAR_BIT == 8"); static_assert(CHAR_BIT == 8, "CHAR_BIT == 8");
namespace detail { namespace detail {
inline SPROUT_CONSTEXPR std::uint32_t sha1_left_rotate(std::uint32_t x, std::size_t n) { inline SPROUT_CONSTEXPR std::uint32_t
sha1_left_rotate(std::uint32_t x, std::size_t n) {
return (x << n) ^ (x >> (32 - n)); return (x << n) ^ (x >> (32 - n));
} }
} // namespace detail } // namespace detail
@ -34,18 +36,18 @@ namespace sprout {
sprout::array<std::uint32_t, 5> h_; sprout::array<std::uint32_t, 5> h_;
sprout::array<std::uint8_t, 64> block_; sprout::array<std::uint8_t, 64> block_;
std::size_t block_byte_index_; std::size_t block_byte_index_;
std::size_t byte_count_; std::uint64_t bit_count_;
private: private:
SPROUT_CONSTEXPR sha1( SPROUT_CONSTEXPR sha1(
sprout::array<std::uint32_t, 5> const& h, sprout::array<std::uint32_t, 5> const& h,
sprout::array<std::uint8_t, 64> const& block, sprout::array<std::uint8_t, 64> const& block,
std::size_t block_byte_index, std::size_t block_byte_index,
std::size_t byte_count std::uint64_t bit_count
) )
: h_(h) : h_(h)
, block_(block) , block_(block)
, block_byte_index_(block_byte_index) , block_byte_index_(block_byte_index)
, byte_count_(byte_count) , bit_count_(bit_count)
{} {}
SPROUT_CONSTEXPR std::uint32_t calc_w(std::size_t i) const { SPROUT_CONSTEXPR std::uint32_t calc_w(std::size_t i) const {
return i < 16 return i < 16
@ -59,11 +61,11 @@ namespace sprout {
) )
; ;
} }
SPROUT_CONSTEXPR sha1 process( SPROUT_CONSTEXPR sha1 const process(
sprout::array<std::uint32_t, 5> const& h, sprout::array<std::uint32_t, 5> const& h,
sprout::array<std::uint8_t, 64> const& block, sprout::array<std::uint8_t, 64> const& block,
std::size_t block_byte_index, std::size_t block_byte_index,
std::size_t byte_count std::uint64_t bit_count
) const ) const
{ {
return block_byte_index != 64 return block_byte_index != 64
@ -71,17 +73,17 @@ namespace sprout {
h, h,
block, block,
block_byte_index, block_byte_index,
byte_count bit_count
) )
: sha1( : sha1(
h, h,
block, block,
0, 0,
byte_count bit_count
).process_block() ).process_block_0()
; ;
} }
SPROUT_CONSTEXPR sha1 process_block_2( SPROUT_CONSTEXPR sha1 const process_block_2(
std::uint32_t a, std::uint32_t a,
std::uint32_t b, std::uint32_t b,
std::uint32_t c, std::uint32_t c,
@ -101,7 +103,7 @@ namespace sprout {
i + 1 i + 1
); );
} }
SPROUT_CONSTEXPR sha1 process_block_1( SPROUT_CONSTEXPR sha1 const process_block_1(
std::uint32_t a, std::uint32_t a,
std::uint32_t b, std::uint32_t b,
std::uint32_t c, std::uint32_t c,
@ -132,17 +134,17 @@ namespace sprout {
sprout::array<std::uint32_t, 5>{{h_[0] + a, h_[1] + b, h_[2] + c, h_[3] + d, h_[4] + e}}, sprout::array<std::uint32_t, 5>{{h_[0] + a, h_[1] + b, h_[2] + c, h_[3] + d, h_[4] + e}},
block_, block_,
block_byte_index_, block_byte_index_,
byte_count_ bit_count_
) )
; ;
} }
SPROUT_CONSTEXPR sha1 process_block() const { SPROUT_CONSTEXPR sha1 const process_block_0() const {
return process_block_1(h_[0], h_[1], h_[2], h_[3], h_[4]); return process_block_1(h_[0], h_[1], h_[2], h_[3], h_[4]);
} }
template<typename Iterator, typename... Args> template<typename Iterator, typename... Args>
SPROUT_CONSTEXPR typename std::enable_if< SPROUT_CONSTEXPR typename std::enable_if<
sizeof...(Args) == 64, sizeof...(Args) == 64,
sha1 sha1 const
>::type process_block_impl( >::type process_block_impl(
Iterator first, Iterator first,
Iterator last, Iterator last,
@ -153,20 +155,20 @@ namespace sprout {
h_, h_,
sprout::make_array<std::uint8_t>(args...), sprout::make_array<std::uint8_t>(args...),
64, 64,
byte_count_ + 64 bit_count_ + 64 * 8
) )
: process( : process(
h_, h_,
sprout::make_array<std::uint8_t>(args...), sprout::make_array<std::uint8_t>(args...),
64, 64,
byte_count_ + 64 bit_count_ + 64 * 8
).process_block_impl(first, last) ).process_block_impl(first, last)
; ;
} }
template<typename Iterator, typename... Args> template<typename Iterator, typename... Args>
SPROUT_CONSTEXPR typename std::enable_if< SPROUT_CONSTEXPR typename std::enable_if<
sizeof...(Args) != 64, sizeof...(Args) != 64,
sha1 sha1 const
>::type process_block_impl( >::type process_block_impl(
Iterator first, Iterator first,
Iterator last, Iterator last,
@ -177,74 +179,69 @@ namespace sprout {
h_, h_,
sprout::get_internal(sprout::range::fixed::copy(sprout::make_array<std::uint8_t>(args...), sprout::sub(block_, block_byte_index_))), sprout::get_internal(sprout::range::fixed::copy(sprout::make_array<std::uint8_t>(args...), sprout::sub(block_, block_byte_index_))),
block_byte_index_ + sizeof...(Args), block_byte_index_ + sizeof...(Args),
byte_count_ + sizeof...(Args) bit_count_ + sizeof...(Args) * 8
) )
: block_byte_index_ + sizeof...(Args) == 64 ? process( : block_byte_index_ + sizeof...(Args) == 64 ? process(
h_, h_,
sprout::get_internal(sprout::range::fixed::copy(sprout::make_array<std::uint8_t>(args...), sprout::sub(block_, block_byte_index_))), sprout::get_internal(sprout::range::fixed::copy(sprout::make_array<std::uint8_t>(args...), sprout::sub(block_, block_byte_index_))),
block_byte_index_ + sizeof...(Args), block_byte_index_ + sizeof...(Args),
byte_count_ + sizeof...(Args) bit_count_ + sizeof...(Args) * 8
).process_block_impl(first, last) ).process_block_impl(first, last)
: process_block_impl(sprout::next(first), last, args..., *first) : process_block_impl(sprout::next(first), last, args..., *first)
; ;
} }
template<typename... Args> SPROUT_CONSTEXPR sha1 const process_one() const {
SPROUT_CONSTEXPR typename std::enable_if<
sizeof...(Args) == 64,
sha1
>::type process_padding(
Args... args
) const
{
return process( return process(
h_, h_,
sprout::make_array<std::uint8_t>(args...), sprout::fixed::set(block_, block_.begin() + block_byte_index_, static_cast<std::uint8_t>(0x80)),
64, block_byte_index_ + 1,
byte_count_ + 64 bit_count_
).process_padding() );
;
} }
template<typename... Args> template<typename... Args>
SPROUT_CONSTEXPR typename std::enable_if< SPROUT_CONSTEXPR sha1 const process_padding_after() const {
sizeof...(Args) != 64, return process(
sha1 h_,
>::type process_padding( sprout::array<std::uint8_t, 64>{{}},
Args... args 56,
) const bit_count_
{ );
return block_byte_index_ + sizeof...(Args) == 56 ? process( }
template<typename... Args>
SPROUT_CONSTEXPR sha1 const process_padding() const {
return block_byte_index_ == 56 ? *this
: block_byte_index_ > 56 ? process(
h_, h_,
sprout::get_internal(sprout::range::fixed::copy(sprout::make_array<std::uint8_t>(args...), sprout::sub(block_, block_byte_index_))), sprout::get_internal(sprout::fixed::fill(sprout::sub(block_, block_byte_index_), static_cast<std::uint8_t>(0))),
block_byte_index_ + sizeof...(Args), 64,
byte_count_ + sizeof...(Args) bit_count_
).process_padding_after()
: process(
h_,
sprout::get_internal(sprout::fixed::fill(sprout::sub(block_, block_byte_index_, 56), static_cast<std::uint8_t>(0))),
56,
bit_count_
) )
: block_byte_index_ + sizeof...(Args) == 64 ? process(
h_,
sprout::get_internal(sprout::range::fixed::copy(sprout::make_array<std::uint8_t>(args...), sprout::sub(block_, block_byte_index_))),
block_byte_index_ + sizeof...(Args),
byte_count_ + sizeof...(Args)
).process_padding()
: process_padding(args..., static_cast<std::uint8_t>(0))
; ;
} }
SPROUT_CONSTEXPR sha1 process_append() const { SPROUT_CONSTEXPR sha1 const process_append() const {
return process( return process(
h_, h_,
sprout::get_internal(sprout::range::fixed::copy( sprout::get_internal(sprout::range::fixed::copy(
sprout::array<std::uint8_t, 8>{{ sprout::array<std::uint8_t, 8>{{
static_cast<std::uint8_t>(0), static_cast<std::uint8_t>((bit_count_ >> 56) & 0xFF),
static_cast<std::uint8_t>(0), static_cast<std::uint8_t>((bit_count_ >> 48) & 0xFF),
static_cast<std::uint8_t>(0), static_cast<std::uint8_t>((bit_count_ >> 40) & 0xFF),
static_cast<std::uint8_t>(0), static_cast<std::uint8_t>((bit_count_ >> 32) & 0xFF),
static_cast<std::uint8_t>((byte_count_ * 8 >> 24) & 0xFF), static_cast<std::uint8_t>((bit_count_ >> 24) & 0xFF),
static_cast<std::uint8_t>((byte_count_ * 8 >> 16) & 0xFF), static_cast<std::uint8_t>((bit_count_ >> 16) & 0xFF),
static_cast<std::uint8_t>((byte_count_ * 8 >> 8) & 0xFF), static_cast<std::uint8_t>((bit_count_ >> 8) & 0xFF),
static_cast<std::uint8_t>((byte_count_ * 8) & 0xFF) static_cast<std::uint8_t>(bit_count_ & 0xFF)
}}, }},
sprout::sub(block_, block_byte_index_) sprout::sub(block_, block_byte_index_)
)), )),
block_byte_index_ + 8, block_byte_index_ + 8,
byte_count_ + 8 bit_count_
); );
} }
SPROUT_CONSTEXPR value_type make_value() const { SPROUT_CONSTEXPR value_type make_value() const {
@ -271,38 +268,111 @@ namespace sprout {
static_cast<std::uint8_t>((h_[4]) & 0xFF) static_cast<std::uint8_t>((h_[4]) & 0xFF)
}}; }};
} }
void process_block() {
std::uint32_t 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] = sprout::detail::sha1_left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
}
std::uint32_t a = h_[0];
std::uint32_t b = h_[1];
std::uint32_t c = h_[2];
std::uint32_t d = h_[3];
std::uint32_t e = h_[4];
for (std::size_t i = 0; i < 80; ++i) {
std::uint32_t f;
std::uint32_t 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 = sprout::detail::sha1_left_rotate(a, 5) + f + e + k + w[i];
e = d;
d = c;
c = sprout::detail::sha1_left_rotate(b, 30);
b = a;
a = temp;
}
h_[0] += a;
h_[1] += b;
h_[2] += c;
h_[3] += d;
h_[4] += e;
}
void process_byte_impl(unsigned char byte) {
block_[block_byte_index_++] = byte;
if (block_byte_index_ == 64) {
block_byte_index_ = 0;
process_block();
}
}
public: public:
SPROUT_CONSTEXPR sha1() SPROUT_CONSTEXPR sha1()
: h_{{0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}} : h_{{0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}}
, block_{{}} , block_{{}}
, block_byte_index_() , block_byte_index_()
, byte_count_() , bit_count_()
{} {}
SPROUT_CONSTEXPR sha1 process_byte(std::uint8_t byte) const {
SPROUT_CONSTEXPR sha1 const process_byte(std::uint8_t byte) const {
return process( return process(
h_, h_,
sprout::fixed::set(block_, block_.begin() + block_byte_index_, byte), sprout::fixed::set(block_, block_.begin() + block_byte_index_, byte),
block_byte_index_ + 1, block_byte_index_ + 1,
byte_count_ + 1 bit_count_ + 8
); );
} }
template<typename Iterator> template<typename Iterator>
SPROUT_CONSTEXPR sha1 process_block(Iterator bytes_begin, Iterator bytes_end) const { SPROUT_CONSTEXPR sha1 const process_block(Iterator bytes_begin, Iterator bytes_end) const {
return process_block_impl( return process_block_impl(
sprout::make_bytes_iterator(bytes_begin), sprout::make_bytes_iterator(bytes_begin),
sprout::make_bytes_iterator(bytes_end) sprout::make_bytes_iterator(bytes_end)
); );
} }
template<typename Iterator> template<typename Iterator>
SPROUT_CONSTEXPR sha1 process_bytes(Iterator buffer, std::size_t byte_count) const { SPROUT_CONSTEXPR sha1 const process_bytes(Iterator buffer, std::size_t byte_count) const {
return process_block(buffer, sprout::next(buffer, byte_count)); return process_block(buffer, sprout::next(buffer, byte_count));
} }
template<typename Range> template<typename Range>
SPROUT_CONSTEXPR sha1 process_range(Range const& bytes_range) const { SPROUT_CONSTEXPR sha1 const process_range(Range const& bytes_range) const {
return process_block(sprout::begin(bytes_range), sprout::end(bytes_range)); return process_block(sprout::begin(bytes_range), sprout::end(bytes_range));
} }
void process_byte(std::uint8_t byte) {
process_byte_impl(byte);
bit_count_ += 8;
}
template<typename Iterator>
void process_block(Iterator bytes_begin, Iterator bytes_end) {
for(; bytes_begin != bytes_end; ++bytes_begin) {
process_byte(*bytes_begin);
}
}
template<typename Iterator>
void process_bytes(Iterator buffer, std::size_t byte_count) {
process_block(buffer, sprout::next(buffer, byte_count));
}
template<typename Range>
void process_range(Range const& bytes_range) {
process_block(sprout::begin(bytes_range), sprout::end(bytes_range));
}
SPROUT_CONSTEXPR value_type checksum() const { SPROUT_CONSTEXPR value_type checksum() const {
return process_byte(0x80).process_padding().process_append().make_value(); return process_one().process_padding().process_append().make_value();
} }
SPROUT_CONSTEXPR value_type operator()() const { SPROUT_CONSTEXPR value_type operator()() const {
return checksum(); return checksum();

View file

@ -15,6 +15,7 @@ namespace sprout {
public: public:
typedef sprout::uuids::uuid result_type; typedef sprout::uuids::uuid result_type;
private: private:
typedef sprout::sha1 const sha1_const_type;
typedef typename result_type::value_type value_type; typedef typename result_type::value_type value_type;
private: private:
sprout::sha1 sha_; sprout::sha1 sha_;
@ -44,10 +45,10 @@ namespace sprout {
} }
public: public:
SPROUT_CONSTEXPR name_generator() SPROUT_CONSTEXPR name_generator()
: sha_(sprout::sha1().process_range(sprout::uuids::uuid{{0}})) : sha_(sha1_const_type().process_range(sprout::uuids::uuid{{0}}))
{} {}
explicit SPROUT_CONSTEXPR name_generator(sprout::uuids::uuid const& namespace_uuid) explicit SPROUT_CONSTEXPR name_generator(sprout::uuids::uuid const& namespace_uuid)
: sha_(sprout::sha1().process_range(namespace_uuid)) : sha_(sha1_const_type().process_range(namespace_uuid))
{} {}
template<typename Elem, std::size_t N, typename Traits> template<typename Elem, std::size_t N, typename Traits>
SPROUT_CONSTEXPR result_type operator()(sprout::basic_string<Elem, N, Traits> const& name) const { SPROUT_CONSTEXPR result_type operator()(sprout::basic_string<Elem, N, Traits> const& name) const {