├── README.md ├── example ├── CMakeLists.txt ├── autoproxy.cpp └── multi_proxychain.cpp └── include └── boost ├── acceptor_server.hpp ├── async_coro_queue.hpp ├── async_dir_walk.hpp ├── async_foreach.hpp ├── avloop.hpp ├── avproxy.hpp ├── avproxy ├── auto_proxychain.hpp ├── avproxy.hpp ├── detail │ ├── error.hpp │ ├── proxy_chain.hpp │ ├── proxy_error_mapper.hpp │ ├── proxy_http.hpp │ ├── proxy_socks5.hpp │ ├── proxy_ssl.hpp │ └── proxy_tcp.hpp ├── proxies.hpp └── proxy_connect.hpp ├── base64.hpp ├── cfunction.hpp ├── hash.hpp ├── hash ├── adler.hpp ├── block_cyphers │ ├── basic_shacal.hpp │ ├── detail │ │ ├── basic_functions.hpp │ │ ├── md4_policy.hpp │ │ ├── md5_policy.hpp │ │ ├── shacal1_policy.hpp │ │ ├── shacal2_policy.hpp │ │ ├── shacal_functions.hpp │ │ ├── shacal_policy.hpp │ │ └── threefish_policy.hpp │ ├── md4.hpp │ ├── md5.hpp │ ├── shacal.hpp │ ├── shacal1.hpp │ ├── shacal2.hpp │ └── threefish.hpp ├── compute_digest.hpp ├── crc.hpp ├── cubehash.hpp ├── davies_meyer_compressor.hpp ├── detail │ ├── basic_functions.hpp │ ├── cubehash_policy.hpp │ ├── exploder.hpp │ ├── imploder.hpp │ ├── md4_policy.hpp │ ├── md5_policy.hpp │ ├── primes.hpp │ ├── sha1_policy.hpp │ ├── sha2_policy.hpp │ ├── sha_policy.hpp │ ├── state_adder.hpp │ └── unbounded_shift.hpp ├── digest.hpp ├── digest_io.hpp ├── md4.hpp ├── md5.hpp ├── merkle_damgard_block_hash.hpp ├── pack.hpp ├── sha.hpp ├── sha1.hpp ├── sha2.hpp ├── stream_endian.hpp └── stream_preprocessor.hpp ├── ietf └── README.md ├── interthread_stream.hpp ├── json_create_escapes_utf8.hpp ├── json_parser_read.hpp ├── json_parser_write.hpp ├── multihandler.hpp ├── splice_stream.hpp ├── stringencodings.hpp ├── timedcall.hpp └── urlencode.hpp /README.md: -------------------------------------------------------------------------------- 1 | avboost 2 | ======= 3 | 4 | some templates that's very very useful during development. 5 | 6 | avboost 是一些在开发 avplayer 的项目过程中编写的极其有用的方便的小模板工具库的集合. 是对 Boost 库的一个补充. 7 | 8 | 包括但不限于 9 | 10 | 11 | * base64 编解码 12 | * cfunction 封装 boost::funcion 为 C 接口的回调. 13 | * async\_coro\_queue 协程使用的异步列队. 14 | * async\_foreach 协程并发的 for\_each 版本 15 | * async\_dir\_walk 利用协程并发的 for\_each 版本实现的异步文件夹遍历. 16 | * acceptor\_server 一个简单的 accepter 用于接受TCP连接. 17 | * avloop 为 asio 添加 idle 回调. 当 io\_service 没事情干的时候调用回调. 18 | * timedcall 简单的 asio deadline\_timer 封装. 用于延时执行一个任务. 19 | * hash 来自 boost.sandbox 的 哈希编码, 支持 SHA1 MD5 20 | * multihandler 一个回调封装, 用于 指定的回调发生N次后调用真正的回调. 21 | * json\_create\_escapes\_utf8.hpp 在使用 boost 的 json 编码器的时候, 包含这个头文件, 可以让 boost 的 json 编码器输出未经过转码的utf8文本 22 | * urlencode.hpp 用于 url 的编码, 将非允许字符使用 % 编码. 23 | * consolestr.hpp 用于将UTF-8字符串转码为本地控制台的字体编码以输出不乱码. 因 linux 和 windows 的控制台编码不一样而引入 24 | * avproxy.hpp asio 的helper, 用于一行代码完成 dns 解析+主机连接+代理协商 25 | 26 | 27 | avproxy 28 | ======= 29 | 30 | asio based async proxy connector 31 | 32 | avproxy is used to make async connections with or without proxyes in one single line of code. 33 | 34 | avproxy 用于在一行代码之内异步发起通过代理和不通过代理的TCP链接 35 | 36 | avproxy support nested proxy aka proxy behind proxy. 37 | 38 | avproxy 支持代理嵌套,能以“代理套代理”的方式发起链接。 39 | 40 | avproxy is as simple as one line call to avproxy::async\_proxy\_connect. 41 | 42 | avproxy 的使用非常简单,调用 avproxy::async\_proxy\_connect 即可。 43 | 44 | async\_proxyconnect 需要的 proxychain 参数可以使用 avproxy::autoproxychain 自动从环境变量构建 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | find_package(Threads) 3 | 4 | add_executable( test1 autoproxy.cpp) 5 | add_executable( test2 multi_proxychain.cpp) 6 | 7 | target_link_libraries( test1 ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) 8 | target_link_libraries( test2 ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) -------------------------------------------------------------------------------- /example/autoproxy.cpp: -------------------------------------------------------------------------------- 1 | 2 | /*** 3 | * 4 | * autoproxy.cpp 5 | * 6 | * avproxy 示例 - 使用 avproxy::autoproxychain 自动从 环境变了构建 proxychain 7 | * 8 | */ 9 | 10 | #include "avproxy.hpp" 11 | 12 | 13 | 14 | static void connected(const boost::system::error_code & ec, boost::asio::ip::tcp::socket & msocket) 15 | { 16 | if ( ec ) 17 | std::cout << ec.message() << std::endl; 18 | else 19 | msocket.write_some(boost::asio::buffer(std::string("GET / HTTP/1.1\r\n\r\n"))); 20 | } 21 | 22 | int main() 23 | { 24 | boost::asio::io_service io_service; 25 | boost::asio::ip::tcp::socket msocket(io_service); 26 | 27 | // 支持环境变量 socks5_proxy/ http_proxy 哦! 28 | // avproxy::autoproxychain 构建一个 proxychain 29 | // avproxy::autoproxychain 支持环境变量 socks5_proxy/ http_proxy, 要更精确的控制,请自己构建 30 | // proxychain 做为参数. 31 | avproxy::async_proxy_connect( 32 | avproxy::autoproxychain(msocket, avproxy::proxy::tcp::query("www.google.com", "81")), 33 | boost::bind(&connected, boost::asio::placeholders::error, boost::ref(msocket)) 34 | ); 35 | io_service.run(); 36 | } -------------------------------------------------------------------------------- /example/multi_proxychain.cpp: -------------------------------------------------------------------------------- 1 | 2 | /*** 3 | * 4 | * multi_proxychain.cpp 5 | * 6 | * avproxy 示例 - 使用 avproxy::proxychain 进行代理嵌套 7 | * 8 | * 9 | * testclient -> socks5 proxy 10 | * -> http proxy 11 | * -> target host 12 | * 13 | */ 14 | 15 | #include "avproxy.hpp" 16 | 17 | 18 | static void connected(const boost::system::error_code & ec, boost::asio::ip::tcp::socket & msocket) 19 | { 20 | if ( ec ) 21 | std::cout << ec.message() << std::endl; 22 | else 23 | msocket.write_some(boost::asio::buffer(std::string("GET / HTTP/1.1\r\n\r\n"))); 24 | } 25 | 26 | int main() 27 | { 28 | boost::asio::io_service io_service; 29 | boost::asio::ip::tcp::socket msocket(io_service); 30 | 31 | avproxy::proxy_chain proxychain(io_service); 32 | proxychain.add(avproxy::proxy::tcp(msocket, boost::asio::ip::tcp::resolver::query("mysocks5proxy.me", "1080"))); 33 | proxychain.add(avproxy::proxy::socks5(msocket, boost::asio::ip::tcp::resolver::query("myhttpproxy.me", "8080"))); 34 | proxychain.add(avproxy::proxy::http(msocket, boost::asio::ip::tcp::resolver::query("www.google.com", "80"))); 35 | 36 | avproxy::async_proxy_connect( 37 | proxychain, boost::bind(&connected, boost::asio::placeholders::error, boost::ref(msocket)) 38 | ); 39 | io_service.run(); 40 | } -------------------------------------------------------------------------------- /include/boost/acceptor_server.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #ifdef __llvm__ 5 | #pragma GCC diagnostic ignored "-Wdangling-else" 6 | #endif 7 | 8 | #ifndef AV_ACCEPTOR_SERVER_H 9 | #define AV_ACCEPTOR_SERVER_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace boost{ 16 | namespace detail{ 17 | 18 | template 19 | class acceptor_server_op : boost::asio::coroutine 20 | { 21 | boost::asio::io_service & io_service; 22 | boost::shared_ptr > m_acceptor_socket; 23 | boost::shared_ptr > m_client_socket; 24 | ProtocolProcesser protocolprocesser; 25 | void start_accept(){ 26 | io_service.post(boost::asio::detail::bind_handler(*this, boost::system::error_code())); 27 | } 28 | 29 | public: 30 | typedef typename Protocol::endpoint endpoint_type; 31 | 32 | acceptor_server_op(boost::asio::io_service & io, const endpoint_type & endpoint, ProtocolProcesser protocolprocesser_) 33 | :io_service(io), m_acceptor_socket(new boost::asio::basic_socket_acceptor(io, endpoint)), protocolprocesser(protocolprocesser_) 34 | { 35 | start_accept(); 36 | } 37 | 38 | acceptor_server_op(boost::shared_ptr > acceptor_socket, ProtocolProcesser protocolprocesser_) 39 | :io_service(acceptor_socket->get_io_service()), m_acceptor_socket(acceptor_socket), protocolprocesser(protocolprocesser_) 40 | { 41 | start_accept(); 42 | } 43 | 44 | 45 | void operator()(const boost::system::error_code & ec) 46 | { 47 | BOOST_ASIO_CORO_REENTER(this) 48 | { 49 | do{ 50 | m_client_socket.reset(new boost::asio::basic_stream_socket(io_service)); 51 | BOOST_ASIO_CORO_YIELD m_acceptor_socket->async_accept(*m_client_socket, *this); 52 | if (!ec) 53 | BOOST_ASIO_CORO_FORK acceptor_server_op(*this)(ec); 54 | }while (is_parent()); 55 | protocolprocesser(m_client_socket); 56 | } 57 | } 58 | 59 | }; 60 | 61 | } 62 | 63 | template 64 | void acceptor_server(boost::asio::io_service & io, const boost::asio::ip::basic_endpoint & endpoint, ProtocolProcesser protocolprocesser) 65 | { 66 | detail::acceptor_server_op(io, endpoint, protocolprocesser); 67 | } 68 | 69 | } 70 | 71 | 72 | #endif // AV_ACCEPTOR_SERVER_H 73 | -------------------------------------------------------------------------------- /include/boost/async_coro_queue.hpp: -------------------------------------------------------------------------------- 1 |  2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace boost { 13 | namespace detail { 14 | 15 | template 16 | class timed_out_handler_wrapper 17 | { 18 | public: 19 | timed_out_handler_wrapper(asio::io_service& io_service, 20 | const asio::deadline_timer::duration_type& timedout, 21 | RealHandler handler, 22 | const boost::shared_ptr &timed_outed) 23 | : m_io_service(io_service) 24 | , m_timer(make_shared(boost::ref(io_service))) 25 | , m_realhandler(make_shared(handler)) 26 | , m_timed_outed(timed_outed) 27 | { 28 | m_timer->expires_from_now(timedout); 29 | m_timer->async_wait(*this); 30 | } 31 | 32 | void operator()(boost::system::error_code ec) 33 | { 34 | 35 | if (ec == asio::error::operation_aborted) 36 | { 37 | // 计时器被取消,啥也不做, 因为回调已经执行了. 38 | return; 39 | } 40 | 41 | // 超时了 42 | 43 | // 标记 44 | *m_timed_outed = true; 45 | 46 | // 执行回调 47 | m_io_service.post( 48 | asio::detail::bind_handler( 49 | m_realhandler, 50 | system::errc::make_error_code(system::errc::timed_out), 51 | T() 52 | ) 53 | ); 54 | } 55 | 56 | void operator()(boost::system::error_code ec, const T &t) 57 | { 58 | // forward to real hander 59 | m_realhandler(ec, t); 60 | 61 | // 取消定时. 62 | m_timer->cancel(ec); 63 | } 64 | 65 | private: 66 | asio::io_service& m_io_service; 67 | 68 | boost::shared_ptr m_realhandler; 69 | 70 | boost::shared_ptr m_timer; 71 | 72 | boost::shared_ptr m_timed_outed; 73 | }; 74 | 75 | } // namespace detail 76 | 77 | /* 78 | * async_coro_queue 是一个用于协程的异步列队。 79 | * 80 | * ListType 只要任意支持 pop_front/push_back 的容器就可以。 81 | * 如 std::deque / std::list /boost::circular_buffer 82 | * 83 | * NOTE: 使用线程安全的列队做模板参数就可以让本协程列队用于多个线程跑的 io_service. 84 | */ 85 | 86 | template 87 | class async_coro_queue : boost::noncopyable{ 88 | public: // typetraits 89 | typedef typename ListType::value_type value_type; 90 | typedef typename ListType::size_type size_type; 91 | typedef typename ListType::reference reference; 92 | typedef typename ListType::const_reference const_reference; 93 | private: 94 | // async_pop 的回调原型 95 | typedef boost::function< 96 | void(boost::system::error_code ec, value_type) 97 | > async_pop_handler_type; 98 | 99 | public: 100 | // 构造函数 101 | async_coro_queue(boost::asio::io_service & io_service) 102 | :m_io_service(io_service) 103 | { 104 | } 105 | 106 | #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES 107 | // 构造函数的一个重载,为列队传入额外的参数 108 | template 109 | async_coro_queue(boost::asio::io_service & io_service, T t) 110 | :m_io_service(io_service), m_list(t) 111 | { 112 | } 113 | // 利用 C++11 的 泛模板参数写第三个构造函数重载 114 | #else 115 | template 116 | async_coro_queue(boost::asio::io_service & io_service, T&&... t) 117 | : m_io_service(io_service), m_list(std::forward(t)...) 118 | { 119 | } 120 | #endif 121 | 122 | private: 123 | boost::system::error_code make_canceled() 124 | { 125 | return system::errc::make_error_code(system::errc::operation_canceled); 126 | } 127 | 128 | // 公开的接口。 129 | public: 130 | 131 | /* 132 | * 回调的类型是 void pop_handler(boost::system::error_code ec, value_type) 133 | * 134 | * value_type 由容器(作为模板参数)决定。 135 | * 例子是 136 | 137 | // ec 如果有错误, 只可能是 boost::asio::error::operation_aborted 138 | 139 | void pop_handler(boost::system::error_code ec, value_type value) 140 | { 141 | // DO SOME THING WITH value 142 | 143 | // start again 144 | list.async_pop(pop_handler); 145 | } 146 | 147 | // 然后在其他地方 148 | list.push(value); 即可唤醒 pop_handler 149 | 150 | * NOTE: 如果列队里有数据, 回调将投递(不是立即回调,是立即投递到 io_service), 否则直到有数据才回调. 151 | */ 152 | template 153 | void async_pop(Handler handler) 154 | { 155 | if (m_list.empty()) 156 | { 157 | // 进入睡眠过程. 158 | m_handlers.push( 159 | std::make_pair( 160 | make_shared(false), async_pop_handler_type(handler) 161 | ) 162 | ); 163 | } 164 | else 165 | { 166 | m_io_service.post( 167 | boost::asio::detail::bind_handler( 168 | handler, boost::system::error_code(), m_list.front() 169 | ) 170 | ); 171 | m_list.pop_front(); 172 | } 173 | } 174 | 175 | /** 176 | * 用法同 async_pop, 但是增加了一个超时参数 177 | */ 178 | template 179 | void async_pop(Handler handler, boost::asio::deadline_timer::duration_type timeout) 180 | { 181 | if (m_list.empty()) 182 | { 183 | boost::shared_ptr timed_outed = make_shared(false); 184 | // 进入睡眠过程. 185 | m_handlers.push( 186 | std::make_pair( 187 | timed_outed, 188 | detail::timed_out_handler_wrapper( 189 | m_io_service, timeout, handler, timed_outed 190 | ) 191 | ) 192 | ); 193 | } 194 | else 195 | { 196 | m_io_service.post( 197 | boost::asio::detail::bind_handler( 198 | handler, boost::system::error_code(), m_list.front() 199 | ) 200 | ); 201 | m_list.pop_front(); 202 | } 203 | } 204 | 205 | 206 | /** 207 | * 向列队投递数据。 208 | * 如果列队为空,并且有协程正在休眠在 async_pop 上, 则立即唤醒此协程,并投递数据给此协程 209 | */ 210 | void push(const value_type &value) 211 | { 212 | // 有handler 挂着! 213 | if (!m_handlers.empty()) 214 | { 215 | // 如果 m_list 不是空, 肯定是有严重的 bug 216 | BOOST_ASSERT(m_list.empty()); 217 | 218 | if (! *(m_handlers.front().first)) 219 | { 220 | m_io_service.post( 221 | boost::asio::detail::bind_handler( 222 | m_handlers.front().second, 223 | boost::system::error_code(), 224 | value 225 | ) 226 | ); 227 | m_handlers.pop(); 228 | } 229 | else 230 | { 231 | m_handlers.pop(); 232 | return push(value); 233 | } 234 | } 235 | else 236 | { 237 | m_list.push_back(value); 238 | } 239 | } 240 | 241 | /** 242 | * cancele all async operations. 243 | */ 244 | void cancele() 245 | { 246 | while (!m_handlers.empty()) 247 | { 248 | if (! *(m_handlers.front().first)) 249 | { 250 | m_io_service.post( 251 | boost::asio::detail::bind_handler( 252 | m_handlers.front().second, 253 | make_canceled(), 254 | value_type() 255 | ) 256 | ); 257 | } 258 | m_handlers.pop(); 259 | } 260 | } 261 | 262 | /* 263 | * clear all items in queue 264 | */ 265 | void clear() 266 | { 267 | cancele(); 268 | m_list.clear(); 269 | } 270 | 271 | private: 272 | 273 | boost::asio::io_service & m_io_service; 274 | ListType m_list; 275 | // 保存 async_pop 回调函数 276 | std::queue< 277 | std::pair, async_pop_handler_type> 278 | > m_handlers; 279 | }; 280 | 281 | } // namespace boost 282 | -------------------------------------------------------------------------------- /include/boost/async_dir_walk.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace boost{ 11 | namespace detail{ 12 | 13 | class DirWalkDumyHandler{ 14 | public: 15 | void operator()(boost::system::error_code ec){} 16 | }; 17 | 18 | } // namespace detail 19 | 20 | typedef function async_dir_walk_continue_handler; 21 | 22 | template 23 | void async_dir_walk(boost::asio::io_service & io_service, boost::filesystem::path path, DirWalkHandler dir_walk_handler, CompleteHandler complete_handler) 24 | { 25 | async_foreach(io_service, boost::filesystem::directory_iterator(path), boost::filesystem::directory_iterator(), dir_walk_handler, complete_handler); 26 | } 27 | 28 | template 29 | void async_dir_walk(boost::asio::io_service & io_service, boost::filesystem::path path, DirWalkHandler dir_walk_handler) 30 | { 31 | async_dir_walk(io_service, path, dir_walk_handler, detail::DirWalkDumyHandler()); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /include/boost/async_foreach.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace boost{ 11 | namespace detail{ 12 | 13 | template 14 | class async_foreach_op : asio::coroutine 15 | { 16 | asio::io_service & m_io_service; 17 | InputIterator m_first, m_last, m_current; 18 | Pred _pred; 19 | Handler m_handler; 20 | public: 21 | typedef void result_type; 22 | 23 | async_foreach_op(asio::io_service & io_service, InputIterator first, InputIterator last, Pred pred, Handler handler) 24 | : m_io_service(io_service), m_first(first), m_last(last), _pred(pred), m_handler(handler) 25 | { 26 | avloop_idle_post(m_io_service, asio::detail::bind_handler(*this, boost::system::error_code())); 27 | } 28 | 29 | void operator()(system::error_code ec) 30 | { 31 | // 好了,每次回调检查一个文件,这样才好,对吧. 32 | BOOST_ASIO_CORO_REENTER(this) 33 | { 34 | for( m_current = m_first; m_current != m_last ; ++m_current) 35 | { 36 | // 好,处理 dir_it_cur dir_it_; 37 | BOOST_ASIO_CORO_YIELD 38 | _pred(*m_current, m_io_service.wrap(bind(*this, _1))); 39 | 40 | BOOST_ASIO_CORO_YIELD 41 | avloop_idle_post(m_io_service, asio::detail::bind_handler(*this, ec)); 42 | } 43 | 44 | avloop_idle_post(m_io_service, asio::detail::bind_handler(m_handler, ec)); 45 | } 46 | } 47 | 48 | }; 49 | 50 | template 51 | async_foreach_op 52 | make_async_foreach_op(asio::io_service &io_service, InputIterator first, InputIterator last , Pred pred, Handler handler) 53 | { 54 | return async_foreach_op(io_service, first, last, pred, handler); 55 | } 56 | 57 | } // namespace detail 58 | 59 | template 60 | void async_foreach(asio::io_service &io_service, InputIterator first, InputIterator last , Pred pred, Handler handler) 61 | { 62 | detail::make_async_foreach_op(io_service, first, last, pred, handler); 63 | } 64 | 65 | } // namespace boost 66 | -------------------------------------------------------------------------------- /include/boost/avloop.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace detail { 8 | 9 | class IdleService 10 | : public boost::asio::detail::service_base 11 | { 12 | virtual void shutdown_service() 13 | {} 14 | 15 | std::list > op_queue; 16 | 17 | public: 18 | 19 | IdleService(boost::asio::io_service& owner) 20 | : boost::asio::detail::service_base(owner) 21 | {} 22 | 23 | bool has_idle() const 24 | { 25 | return !op_queue.empty(); 26 | } 27 | 28 | template 29 | void post(Handler handler) 30 | { 31 | op_queue.push_back(handler); 32 | } 33 | 34 | void poll_one() 35 | { 36 | get_io_service().dispatch(op_queue.front()); 37 | op_queue.pop_front(); 38 | } 39 | }; 40 | 41 | #ifdef _WIN32 42 | class Win32MsgLoopService 43 | : public boost::asio::detail::service_base 44 | { 45 | virtual void shutdown_service() 46 | { 47 | m_is_stoped = true; 48 | PostQuitMessage(0); 49 | } 50 | 51 | bool m_is_stoped; 52 | 53 | public: 54 | Win32MsgLoopService(boost::asio::io_service& owner) 55 | : boost::asio::detail::service_base(owner) 56 | { 57 | m_is_stoped = false; 58 | } 59 | 60 | bool has_message() const 61 | { 62 | if (m_is_stoped) 63 | return false; 64 | MSG msg; 65 | return PeekMessage(&msg, 0, 0, 0, 0); 66 | } 67 | 68 | void poll_one() 69 | { 70 | MSG msg; 71 | if (PeekMessage(&msg, 0, 0, 0, 1)) 72 | { 73 | TranslateMessage(&msg); 74 | DispatchMessage(&msg); 75 | } 76 | if (msg.message == WM_QUIT) 77 | { 78 | m_is_stoped = true; 79 | } 80 | } 81 | }; 82 | 83 | #endif 84 | 85 | } // namespace detail 86 | 87 | template 88 | void avloop_idle_post(boost::asio::io_service& io_service, Handler handler) 89 | { 90 | using namespace ::detail; 91 | if (!boost::asio::has_service(io_service)) 92 | boost::asio::add_service(io_service, new IdleService(io_service)); 93 | 94 | boost::asio::use_service(io_service).post(handler); 95 | } 96 | 97 | static inline void avloop_run(boost::asio::io_service& io_service) 98 | { 99 | using namespace ::detail; 100 | 101 | if (!boost::asio::has_service(io_service)) 102 | boost::asio::add_service(io_service, new IdleService(io_service)); 103 | 104 | while (!io_service.stopped()) 105 | { 106 | if(!boost::asio::use_service(io_service).has_idle()) 107 | { 108 | if (!io_service.run_one()) 109 | break; 110 | } 111 | else 112 | { 113 | while (io_service.poll()); 114 | // 执行 idle handler! 115 | boost::asio::use_service(io_service).poll_one(); 116 | } 117 | } 118 | } 119 | 120 | #ifdef _WIN32 121 | // MsgWaitForMultipleObjectsEx 集成进去. 122 | static inline void avloop_run_gui(boost::asio::io_service& io_service) 123 | { 124 | using namespace ::detail; 125 | 126 | boost::asio::io_service::work work(io_service); 127 | 128 | if (!boost::asio::has_service(io_service)) 129 | boost::asio::add_service(io_service, new IdleService(io_service)); 130 | 131 | if (!boost::asio::has_service(io_service)) 132 | boost::asio::add_service(io_service, new Win32MsgLoopService(io_service)); 133 | 134 | while (!io_service.stopped()) 135 | { 136 | // 首先处理 asio 的消息. 137 | while (io_service.poll()) 138 | { 139 | // 然后执行 gui 循环,看有没有 gui 事件. 140 | if (boost::asio::use_service(io_service).has_message()) 141 | { 142 | // 执行以下. 143 | boost::asio::use_service(io_service).poll_one(); 144 | } 145 | } 146 | // 然后执行 gui 循环,看有没有 gui 事件. 147 | while(boost::asio::use_service(io_service).has_message()) 148 | { 149 | // 执行以下. 150 | boost::asio::use_service(io_service).poll_one(); 151 | } 152 | 153 | // 执行 idle handler! 154 | if (boost::asio::use_service(io_service).has_idle()) 155 | boost::asio::use_service(io_service).poll_one(); 156 | 157 | // 都没有事件了,执行 一次 1ms 的超时等待. 158 | auto ret = MsgWaitForMultipleObjectsEx(0, nullptr, 1, QS_ALLEVENTS, MWMO_WAITALL|MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); 159 | // 可能是有 gui 消息了, 呵呵, 从头来吧. 160 | } 161 | } 162 | #else 163 | static inline void avloop_run_gui(boost::asio::io_service& io_service) 164 | { 165 | return avloop_run(io_service); 166 | } 167 | #endif 168 | -------------------------------------------------------------------------------- /include/boost/avproxy.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "avproxy/avproxy.hpp" 4 | -------------------------------------------------------------------------------- /include/boost/avproxy/auto_proxychain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "detail/proxy_chain.hpp" 7 | #include "proxies.hpp" 8 | 9 | #include "boost/xpressive/xpressive.hpp" 10 | 11 | namespace avproxy{ 12 | 13 | // automanticaly build proxychain 14 | // accourding to env variables http_proxy and socks5_proxy 15 | // to use socks5 proxy, set socks5_proxy="host:port" 16 | template 17 | proxy_chain autoproxychain(Socket & socket, const typename Socket::protocol_type::resolver::query & _query, std::string proxy_settings_string = "") 18 | { 19 | using query_t = typename Socket::protocol_type::resolver::query; 20 | 21 | proxy_chain _proxychain(socket.get_io_service()); 22 | 23 | if (proxy_settings_string.empty()) 24 | { 25 | if (std::getenv("socks5_proxy")) 26 | proxy_settings_string = std::getenv("socks5_proxy"); 27 | if (std::getenv("http_proxy")) 28 | proxy_settings_string = std::getenv("http_proxy"); 29 | } 30 | 31 | if (!proxy_settings_string.empty()) 32 | { 33 | const boost::xpressive::sregex url_expr = (boost::xpressive::s1= (boost::xpressive::as_xpr("http://") | boost::xpressive::as_xpr("socks5://")) ) 34 | >> (boost::xpressive::s2= +boost::xpressive::set[ boost::xpressive::range('a','z') | boost::xpressive::range('A', 'Z') | boost::xpressive::range('0', '9') | '.' ] ) 35 | >> -! ( ':' >> (boost::xpressive::s3= +boost::xpressive::set[boost::xpressive::range('0', '9')]) ) 36 | >> ! boost::xpressive::as_xpr('/'); 37 | 38 | boost::xpressive::smatch what_url; 39 | 40 | if (boost::xpressive::regex_match(proxy_settings_string, what_url, url_expr)) 41 | { 42 | std::string host = what_url[2].str(); 43 | std::string optional_port = what_url[3].str(); 44 | 45 | if ( what_url[1].str() == "http://") 46 | { 47 | // 应该是 http_proxy=http://host[:port] 48 | if (optional_port.empty()) 49 | optional_port = "80"; 50 | _proxychain.add(proxy::tcp(socket, query_t(host, optional_port))); 51 | _proxychain.add(proxy::http(socket, _query)); 52 | return _proxychain; 53 | } 54 | 55 | if ( what_url[1].str() == "socks5://") 56 | { 57 | // 应该是 http_proxy=http://host[:port] 58 | if (optional_port.empty()) 59 | optional_port = "1080"; 60 | 61 | _proxychain.add(proxy::tcp(socket, query_t(host, optional_port))); 62 | _proxychain.add(proxy::socks5(socket, _query)); 63 | return _proxychain; 64 | } 65 | } 66 | } 67 | 68 | _proxychain.add(proxy::tcp(socket, _query)); 69 | return _proxychain; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /include/boost/avproxy/avproxy.hpp: -------------------------------------------------------------------------------- 1 |  2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef BOOST_ENABLE_SSL 9 | #include 10 | #endif 11 | 12 | 13 | #include "detail/proxy_chain.hpp" 14 | 15 | #include "proxy_connect.hpp" 16 | #include "proxies.hpp" 17 | #include "auto_proxychain.hpp" 18 | -------------------------------------------------------------------------------- /include/boost/avproxy/detail/error.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace avproxy{ 8 | namespace error{ 9 | 10 | enum proxy_errors{ 11 | proxy_connection_refused = 5000, 12 | proxy_refused = 5000, 13 | proxy_not_authorized, 14 | proxy_unknow_error, 15 | }; 16 | 17 | namespace detail{ 18 | class avproxy_category; 19 | } 20 | 21 | template 22 | const boost::system::error_category& error_category_single() 23 | { 24 | static error_category error_category_instance; 25 | return reinterpret_cast(error_category_instance); 26 | } 27 | 28 | inline const boost::system::error_category& get_avproxy_category() 29 | { 30 | return error_category_single(); 31 | } 32 | 33 | inline boost::system::error_code make_error_code(proxy_errors e) 34 | { 35 | return boost::system::error_code( 36 | static_cast(e), get_avproxy_category()); 37 | } 38 | 39 | 40 | namespace detail { 41 | 42 | class avproxy_category : public boost::system::error_category { 43 | public: 44 | const char* name() const BOOST_NOEXCEPT { 45 | return "avproxy.proxy"; 46 | } 47 | 48 | std::string message ( int value ) const { 49 | if ( value == proxy_connection_refused ) 50 | return "remote proxy refused the connection"; 51 | 52 | if ( value == proxy_not_authorized ) 53 | return "authorizing to proxy failed"; 54 | 55 | return "avproxy.proxy error"; 56 | } 57 | }; 58 | 59 | } // namespace detail 60 | 61 | } // namespace error 62 | } // namespace avproxy 63 | 64 | namespace boost { 65 | namespace system { 66 | 67 | template<> struct is_error_code_enum 68 | { 69 | static const bool value = true; 70 | }; 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /include/boost/avproxy/detail/proxy_chain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace avproxy { 8 | class proxy_chain; 9 | namespace detail { 10 | 11 | // 为proxy_chian提供便利的添加语法的辅助类. 12 | struct proxychain_adder{ 13 | proxychain_adder( proxy_chain & _chain) 14 | :chain(&_chain) 15 | { 16 | } 17 | 18 | template 19 | proxychain_adder operator()(const Proxy & proxy ); 20 | 21 | operator proxy_chain& (){ 22 | return *chain; 23 | } 24 | operator proxy_chain (); 25 | 26 | private: 27 | proxy_chain * chain; 28 | }; 29 | } 30 | 31 | 32 | namespace detail{ 33 | class proxy_wrapper; 34 | class proxy_type_erasure_base 35 | { 36 | public: 37 | typedef std::function< void (const boost::system::error_code&) > handler_type; 38 | friend class proxy_wrapper; 39 | 40 | private: 41 | virtual void async_connect(handler_type) = 0; 42 | }; 43 | 44 | template 45 | class proxy_adaptor : public proxy_type_erasure_base 46 | { 47 | friend class proxy_wrapper; 48 | proxy_adaptor(const RealProxy & realproxy) 49 | : realobj(realproxy) 50 | { 51 | } 52 | 53 | proxy_adaptor(RealProxy && realproxy) 54 | : realobj(realproxy) 55 | { 56 | } 57 | 58 | virtual void async_connect(proxy_type_erasure_base::handler_type handler) override 59 | { 60 | realobj.async_connect(handler); 61 | } 62 | RealProxy realobj; 63 | }; 64 | 65 | class proxy_wrapper 66 | { 67 | public: 68 | proxy_wrapper(const proxy_wrapper& other) = default; 69 | proxy_wrapper(proxy_wrapper&& other) = default; 70 | 71 | proxy_wrapper& operator=(const proxy_wrapper& other) = default; 72 | proxy_wrapper& operator=(proxy_wrapper&& other) = default; 73 | 74 | template::type, proxy_wrapper>::value, int>::type = 0 > 75 | proxy_wrapper(RealProxy&& realproxy) 76 | { 77 | _impl.reset(new proxy_adaptor::type>(realproxy)); 78 | } 79 | 80 | template::type, proxy_wrapper>::value, int>::type = 0 > 81 | proxy_wrapper(const RealProxy& realproxy) 82 | { 83 | _impl.reset(new proxy_adaptor::type>(realproxy)); 84 | } 85 | 86 | public: 87 | template 88 | void async_connect(Handler handler){ 89 | _impl->async_connect(handler); 90 | } 91 | 92 | private: 93 | std::shared_ptr _impl; 94 | }; 95 | 96 | } 97 | 98 | class proxy_chain : public std::vector 99 | { 100 | public: 101 | proxy_chain(boost::asio::io_service& _io):io_(_io){} 102 | proxy_chain(proxy_chain&& other) = default; 103 | proxy_chain(const proxy_chain& other) = default; 104 | 105 | void pop_front() 106 | { 107 | erase(begin()); 108 | } 109 | 110 | detail::proxychain_adder add(){ 111 | return detail::proxychain_adder(*this); 112 | } 113 | 114 | template 115 | proxy_chain add(const Proxy & proxy) 116 | { 117 | push_back(proxy); 118 | return *this; 119 | } 120 | 121 | boost::asio::io_service& get_io_service(){ 122 | return io_; 123 | } 124 | 125 | private: 126 | boost::asio::io_service& io_; 127 | friend struct detail::proxychain_adder; 128 | }; 129 | 130 | 131 | template 132 | detail::proxychain_adder detail::proxychain_adder::operator()( const Proxy & proxy ) 133 | { 134 | // 拷贝构造一个新的. 135 | chain->add(proxy); 136 | return *this; 137 | } 138 | 139 | inline 140 | detail::proxychain_adder::operator proxy_chain() 141 | { 142 | return *chain; 143 | } 144 | 145 | } // namespace avproxy 146 | -------------------------------------------------------------------------------- /include/boost/avproxy/detail/proxy_error_mapper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace avproxy{ 6 | 7 | namespace proxy{ 8 | 9 | namespace detail{ 10 | template 11 | void proxy_error_mapper(const boost::system::error_code & _ec, Handler handler) 12 | { 13 | boost::system::error_code ec = _ec; 14 | if (ec == boost::asio::error::connection_refused) 15 | { 16 | ec = avproxy::error::make_error_code(avproxy::error::proxy_connection_refused); 17 | } 18 | handler(ec); 19 | } 20 | } 21 | 22 | }// proxy 23 | 24 | }// avproxy 25 | -------------------------------------------------------------------------------- /include/boost/avproxy/detail/proxy_http.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "./error.hpp" 10 | #include "proxy_chain.hpp" 11 | #include "../proxy_connect.hpp" 12 | #include "proxy_error_mapper.hpp" 13 | 14 | namespace avproxy{ 15 | 16 | namespace proxy{ 17 | 18 | namespace detail{ 19 | 20 | template 21 | class async_safe_read_until_op : boost::asio::coroutine { 22 | private: 23 | AsyncReadStream &m_stream; 24 | boost::asio::basic_streambuf & m_buf; 25 | const std::string m_delim; 26 | ReadHandler m_handler; 27 | public: 28 | typedef void result_type; 29 | 30 | async_safe_read_until_op(AsyncReadStream& s, 31 | boost::asio::basic_streambuf& b, const std::string& delim, 32 | ReadHandler handler) 33 | :m_buf(b), m_stream(s), m_delim(delim), m_handler(handler) 34 | { 35 | m_stream.get_io_service().post(boost::bind(*this, boost::system::error_code(), 0)); 36 | } 37 | void operator()(const boost::system::error_code & ec, std::size_t length) 38 | { 39 | BOOST_ASIO_CORO_REENTER(this) 40 | { 41 | // 一次读取一个字节. 42 | do{ 43 | BOOST_ASIO_CORO_YIELD boost::asio::async_read(m_stream, m_buf.prepare(1), *this); 44 | if ( ec) break; 45 | m_buf.commit(length); 46 | }while(!check_delim()); 47 | m_stream.get_io_service().post( 48 | boost::asio::detail::bind_handler((m_handler), ec, m_buf.size()) 49 | ); 50 | } 51 | } 52 | private: 53 | bool check_delim() 54 | { 55 | // 检查 m_buf 里是不是有 delim 56 | std::string response(boost::asio::buffer_cast(m_buf.data()), m_buf.size()); 57 | return response.find(m_delim) != std::string::npos; 58 | } 59 | }; 60 | 61 | /** 62 | * async_safe_read_until 安全的读取到 delim 为止,绝对不多读一个字节。 63 | * 内部实现是每次读取一个字节,所以为了效率考虑请不要使用这个接口哦. 64 | */ 65 | template 66 | void async_safe_read_until(AsyncReadStream& s, 67 | boost::asio::basic_streambuf& b, const std::string& delim, ReadHandler handler) 68 | { 69 | // If you get an error on the following line it means that your handler does 70 | // not meet the documented type requirements for a ReadHandler. 71 | 72 | //BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 73 | 74 | async_safe_read_until_op( 75 | s, b, delim, handler 76 | ); 77 | } 78 | 79 | } 80 | 81 | // 使用 http代理 发起连接. 82 | // TODO, 添加认证支持. 83 | class http : boost::asio::coroutine{ 84 | public: 85 | typedef std::function< void (const boost::system::error_code&) > handler_type; 86 | typedef boost::asio::ip::tcp::resolver::query query; 87 | typedef boost::asio::ip::tcp::socket socket; 88 | typedef void result_type; 89 | 90 | // _query 目的地址 91 | http(socket &_socket,const query & _query) 92 | :socket_(_socket), query_(_query) 93 | { 94 | 95 | } 96 | 97 | // 执行 HTTP 的 handshake, 要异步哦. 98 | void async_connect(handler_type handler){ 99 | 100 | socket_.get_io_context().post(boost::asio::detail::bind_handler(*this, boost::system::error_code(), 0, handler)); 101 | } 102 | public: 103 | void operator()(boost::system::error_code ec, std::size_t length, handler_type handler) 104 | { 105 | const char * buffer = NULL; 106 | if (m_buffer) 107 | buffer = boost::asio::buffer_cast(m_buffer->data()); 108 | BOOST_ASIO_CORO_REENTER(this) 109 | { 110 | do{ 111 | // 写入 CONNECT XXX:XXX 112 | // TODO, 支持认证. 113 | BOOST_ASIO_CORO_YIELD boost::asio::async_write(socket_, boost::asio::buffer( 114 | std::string("CONNECT ") + query_.host_name() + ":" + query_.service_name() + "HTTP/1.1\r\n\r\n" 115 | ), boost::bind(*this, _1, _2, handler)); 116 | if (ec) break; 117 | m_buffer.reset(new boost::asio::streambuf); 118 | detail::async_safe_read_until(socket_, *m_buffer, "\r\n\r\n" , boost::bind(*this, _1, _2, handler)); 119 | if (ec) break; 120 | // 解析是不是 HTTP 200 OK 121 | if (check_status()==200) 122 | { 123 | ec = boost::system::error_code(); 124 | }else { 125 | ec = error::make_error_code(error::proxy_unknow_error); 126 | } 127 | }while (false); 128 | socket_.get_io_context().post(boost::asio::detail::bind_handler(handler, ec)); 129 | } 130 | } 131 | 132 | void _async_write_some(){ 133 | 134 | } 135 | 136 | private: 137 | unsigned check_status () 138 | { 139 | std::string ver; 140 | unsigned status; 141 | 142 | std::istream response(m_buffer.get()); 143 | response >> ver >> status; 144 | return status; 145 | } 146 | 147 | private: 148 | boost::shared_ptr m_buffer; 149 | socket& socket_; 150 | const query query_; 151 | }; 152 | 153 | 154 | } // namespace proxy 155 | } // namespace avproxy -------------------------------------------------------------------------------- /include/boost/avproxy/detail/proxy_socks5.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "./error.hpp" 10 | #include "proxy_chain.hpp" 11 | #include "../proxy_connect.hpp" 12 | 13 | #include "proxy_error_mapper.hpp" 14 | 15 | namespace avproxy{ 16 | 17 | namespace proxy{ 18 | 19 | // 使用 socks5代理 发起连接. 20 | // TODO, 添加认证支持. 21 | class socks5 : boost::asio::coroutine 22 | { 23 | public: 24 | typedef std::function< void (const boost::system::error_code&) > handler_type; 25 | typedef boost::asio::ip::tcp::resolver::query query; 26 | typedef boost::asio::ip::tcp::socket socket; 27 | typedef void result_type; 28 | 29 | socks5(socket &_socket,const query & _query) 30 | :socket_(_socket), query_(_query) 31 | { 32 | 33 | } 34 | 35 | void async_connect(handler_type handler) 36 | { 37 | // 执行 socks5 的 handshake, 要异步哦. 38 | socket_.get_io_context().post(boost::asio::detail::bind_handler(*this, boost::system::error_code(), 0, handler)); 39 | } 40 | 41 | public: 42 | void operator()(boost::system::error_code ec, std::size_t length, handler_type handler) 43 | { 44 | static const char socks5_command[3] = {5, 1, 0}; 45 | const char * buffer = NULL; 46 | if (m_buffer) 47 | buffer = boost::asio::buffer_cast(m_buffer->data()); 48 | BOOST_ASIO_CORO_REENTER(this) 49 | { 50 | do{ 51 | // 写入 0x05, 0x00 52 | // TODO, 支持认证. 53 | BOOST_ASIO_CORO_YIELD boost::asio::async_write(socket_, boost::asio::buffer(socks5_command), boost::bind(*this, _1, _2, handler)); 54 | if (ec) break; 55 | m_buffer.reset(new boost::asio::streambuf); 56 | BOOST_ASIO_CORO_YIELD boost::asio::async_read(socket_, m_buffer->prepare(2), boost::bind(*this, _1, _2, handler)); 57 | if (ec) break; 58 | // 解析是不是 0x05, 0x00 59 | m_buffer->commit(length); 60 | if (!(buffer[0] == 5 && buffer[1] == 0)) 61 | { 62 | ec = error::make_error_code(error::proxy_not_authorized); 63 | break; 64 | } 65 | // 执行 connect 命令. 66 | BOOST_ASIO_CORO_YIELD boost::asio::async_write(socket_, boost::asio::buffer(buildsocks5connectcmd()), boost::bind(*this, _1, _2, handler)); 67 | if (ec) break; 68 | m_buffer.reset(new boost::asio::streambuf); 69 | // 读取 socks5 server 返回值. 70 | BOOST_ASIO_CORO_YIELD boost::asio::async_read(socket_, m_buffer->prepare(4), boost::bind(*this, _1, _2, handler)); 71 | if (ec) break; 72 | m_buffer->commit(length); 73 | 74 | // 解析返回值. 75 | if (!(length==4 && buffer[0] == 5 && buffer[1] == 0 && buffer[2] == 0 )) 76 | { 77 | ec = error::make_error_code(error::proxy_not_authorized); 78 | break; 79 | } 80 | 81 | // ATYPE==ipv4 82 | if (boost::asio::buffer_cast(m_buffer->data())[3] == 1){ 83 | BOOST_ASIO_CORO_YIELD boost::asio::async_read(socket_, m_buffer->prepare(6), boost::bind(*this, _1, _2, handler)); 84 | m_buffer->commit(length); 85 | }else if (boost::asio::buffer_cast(m_buffer->data())[3]==4){ 86 | BOOST_ASIO_CORO_YIELD boost::asio::async_read(socket_, m_buffer->prepare(18), boost::bind(*this, _1, _2, handler)); 87 | m_buffer->commit(length); 88 | }else if (boost::asio::buffer_cast(m_buffer->data())[3]==3){ 89 | ec = error::make_error_code(error::proxy_unknow_error); 90 | }else{ 91 | // 出错. 92 | ec = error::make_error_code(error::proxy_unknow_error); 93 | } 94 | if (ec) break; 95 | }while (false); 96 | socket_.get_io_context().post(boost::asio::detail::bind_handler(handler, ec)); 97 | } 98 | } 99 | 100 | void _async_write_some(){ 101 | 102 | } 103 | 104 | private: 105 | // 0x05 0x01 0x00 0x03 [length]ipaddr [port] 106 | std::vector buildsocks5connectcmd() 107 | { 108 | std::vector cmd(4 + 1 + query_.host_name().length() + 2 ); 109 | unsigned short port = boost::lexical_cast(query_.service_name()); 110 | cmd[0] = 5; 111 | cmd[1] = 1; 112 | cmd[2] = 0; 113 | cmd[3] = 3; 114 | cmd[4] = query_.host_name().length(); 115 | std::memcpy(&cmd[5], query_.host_name().c_str(), query_.host_name().length()); 116 | cmd[5+query_.host_name().length()] = port >> 8; 117 | cmd[5+query_.host_name().length() + 1 ] = port & 0xFF; 118 | return cmd;//boost::asio::buffer(cmd, cmd.size()); 119 | } 120 | 121 | private: 122 | boost::shared_ptr m_buffer; 123 | socket& socket_; 124 | const query query_; 125 | }; 126 | 127 | 128 | } // namespace proxy 129 | } // namespace avproxy 130 | 131 | -------------------------------------------------------------------------------- /include/boost/avproxy/detail/proxy_ssl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "proxy_chain.hpp" 7 | #include "../proxy_connect.hpp" 8 | 9 | namespace avproxy{ 10 | namespace proxy{ 11 | 12 | // SSL 连接过程. 支持透过代理发起 SSL 连接哦! 13 | // TODO 14 | class proxy_ssl : public avproxy::detail::proxy_base{ 15 | public: 16 | typedef boost::asio::ip::tcp tcp; 17 | typedef tcp::resolver::query query; 18 | typedef tcp::socket socket; 19 | 20 | proxy_ssl(boost::asio::ssl::stream &stream, query _query) 21 | { 22 | 23 | } 24 | 25 | private: 26 | void _resolve(handler_type handler, proxy_chain subchain){ 27 | // 递归调用 avconnect 传递到下一层. 28 | avproxy::async_proxy_connect(subchain, handler); 29 | } 30 | 31 | void _handshake(handler_type handler, proxy_chain subchain ){ 32 | // 调用 ssl 的 async_handshake 33 | // TODO 34 | } 35 | 36 | }; 37 | 38 | } // namespace proxy 39 | } // namespace avproxy -------------------------------------------------------------------------------- /include/boost/avproxy/detail/proxy_tcp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "proxy_chain.hpp" 4 | #include "../proxy_connect.hpp" 5 | 6 | namespace avproxy{ 7 | namespace proxy{ 8 | // 使用 TCP 发起连接. 也就是不使用代理啦. 9 | class tcp 10 | { 11 | public: 12 | typedef boost::asio::ip::tcp::resolver::query query; 13 | typedef boost::asio::ip::tcp::socket socket; 14 | 15 | tcp(socket &_socket,const query & _query) 16 | :socket_(_socket), query_(_query) 17 | { 18 | } 19 | 20 | template 21 | void async_connect(handler_type handler) 22 | { 23 | avproxy::async_connect(socket_, query_, handler); 24 | } 25 | 26 | socket& socket_; 27 | const query query_; 28 | }; 29 | 30 | 31 | } // namespace proxy 32 | } // namespace avproxy -------------------------------------------------------------------------------- /include/boost/avproxy/proxies.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "detail/proxy_chain.hpp" 4 | #include "detail/proxy_tcp.hpp" 5 | #include "detail/proxy_socks5.hpp" 6 | #include "detail/proxy_http.hpp" 7 | 8 | #ifdef BOOST_ENABLE_SSL 9 | #include "detail/proxy_ssl.hpp" 10 | #endif 11 | -------------------------------------------------------------------------------- /include/boost/avproxy/proxy_connect.hpp: -------------------------------------------------------------------------------- 1 |  2 | #pragma once 3 | 4 | #ifdef __llvm__ 5 | #pragma GCC diagnostic ignored "-Wdangling-else" 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "detail/proxy_chain.hpp" 19 | 20 | namespace avproxy { 21 | 22 | // convient helper class that made for direct TCP connection without proxy 23 | // usage: 24 | // avproxy::async_connect( socket , ip::tcp::resolve::query( "host" , "port" ) , handler ); 25 | // the hander should be this signature 26 | // void handle_connect( 27 | // const boost::system::error_code & ec 28 | // ) 29 | class async_connect 30 | { 31 | public: 32 | typedef void result_type; // for boost::bind 33 | public: 34 | template 35 | async_connect(Socket & socket,const typename Socket::protocol_type::resolver::query & _query, BOOST_ASIO_MOVE_ARG(Handler) handler) 36 | { 37 | //BOOST_ASIO_CONNECT_HANDLER_CHECK(Handler, handler) type_check; 38 | _async_connect(socket, _query, boost::function(handler)); 39 | } 40 | 41 | template 42 | void operator()(const boost::system::error_code & ec, typename Socket::protocol_type::resolver::results_type resolve_result, Socket & socket, boost::shared_ptr resolver, Handler handler) 43 | { 44 | boost::asio::async_connect(socket, resolve_result, [handler, resolver](auto ec, auto endpoint){ 45 | handler(ec); 46 | }); 47 | } 48 | 49 | private: 50 | template 51 | void _async_connect(Socket & socket,const typename Socket::protocol_type::resolver::query & _query, BOOST_ASIO_MOVE_ARG(Handler) handler) 52 | { 53 | //BOOST_ASIO_CONNECT_HANDLER_CHECK(Handler, handler) type_check; 54 | 55 | typedef typename Socket::protocol_type::resolver resolver_type; 56 | 57 | boost::shared_ptr 58 | resolver(new resolver_type(socket.get_io_service())); 59 | resolver->async_resolve(_query, boost::bind(*this, _1, _2, boost::ref(socket), resolver, handler)); 60 | } 61 | }; 62 | 63 | // 带 proxy 执行连接. 64 | template 65 | class async_proxy_connect_op : boost::asio::coroutine 66 | { 67 | public: 68 | typedef void result_type; // for boost::bind_handler 69 | public: 70 | async_proxy_connect_op(const proxy_chain &proxy_chain, Handler &handler) 71 | : proxy_chain_(proxy_chain) 72 | , m_handler(handler) 73 | { 74 | } 75 | 76 | void operator()(boost::system::error_code ec) 77 | { 78 | BOOST_ASIO_CORO_REENTER(this) 79 | { 80 | do 81 | { 82 | // resolve 83 | BOOST_ASIO_CORO_YIELD proxy_chain_.begin()->async_connect(*this); 84 | proxy_chain_.pop_front(); 85 | }while(proxy_chain_.size() && !ec); 86 | m_handler(ec); 87 | } 88 | } 89 | private: 90 | proxy_chain proxy_chain_; 91 | Handler m_handler; 92 | }; 93 | 94 | template 95 | inline BOOST_ASIO_INITFN_RESULT_TYPE(RealHandler, 96 | void(boost::system::error_code)) 97 | async_proxy_connect(const proxy_chain &proxy_chain, BOOST_ASIO_MOVE_ARG(RealHandler) handler) 98 | { 99 | using namespace boost::asio; 100 | 101 | BOOST_ASIO_CONNECT_HANDLER_CHECK(RealHandler, handler) type_check; 102 | 103 | boost::asio::async_completion 104 | init(BOOST_ASIO_MOVE_CAST(RealHandler)(handler)); 105 | 106 | async_proxy_connect_op(proxy_chain, init.completion_handler) 108 | (boost::system::error_code()); 109 | return init.result.get(); 110 | 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /include/boost/base64.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace boost { 15 | 16 | typedef archive::iterators::transform_width< 17 | archive::iterators::binary_from_base64 >, 8, 6, char> 18 | base64decodeIterator; 19 | 20 | typedef archive::iterators::base64_from_binary< 21 | archive::iterators::transform_width > 22 | base64encodeIterator; 23 | 24 | // BASE64 解码. 25 | inline std::string base64_decode(std::string str) 26 | { 27 | static int shrik_map[] = {0, 2, 1}; 28 | 29 | // 移除尾部的 == 后面的 \r\n\r\n 30 | while ( boost::is_any_of("\r\n.")(* str.rbegin())) 31 | str.erase(str.length()-1); 32 | // 统计结尾的 = 数目 33 | std::size_t num = 0; 34 | if (str.find_last_of("=")!=std::string::npos) 35 | num = str.find_last_of("=") - str.find_first_of("=") + 1; 36 | 37 | BOOST_ASSERT(num < 3); 38 | 39 | std::size_t num_to_shrik = shrik_map[num]; 40 | 41 | // convert base64 characters to binary values 42 | std::string result(base64decodeIterator(str.c_str()), base64decodeIterator(str.c_str() + str.length())); 43 | 44 | result.erase(result.length() -1 - num_to_shrik, num_to_shrik); 45 | return result; 46 | } 47 | 48 | // BASE64 编码. 49 | inline std::string base64_encode(std::string src) 50 | { 51 | std::vector result(src.length()/3*4+6); 52 | unsigned one_third_len = src.length()/3; 53 | 54 | unsigned len_rounded_down = one_third_len*3; 55 | unsigned j = len_rounded_down + one_third_len; 56 | 57 | std::string base64str; 58 | 59 | // 3 的整数倍可以编码. 60 | std::copy(base64encodeIterator(src.begin()), base64encodeIterator(src.begin() + len_rounded_down), result.begin()); 61 | 62 | base64str = result.data(); 63 | 64 | // 结尾 0 填充以及使用 = 补上 65 | if (len_rounded_down != src.length()) 66 | { 67 | std::string tail; 68 | tail.resize(4, 0); 69 | unsigned i=0; 70 | for(; i < src.length() - len_rounded_down; ++i) 71 | { 72 | tail[i] = src[len_rounded_down+i]; 73 | } 74 | 75 | std::string tailbase; 76 | tailbase.resize(5); 77 | 78 | std::copy(base64encodeIterator(tail.begin()), base64encodeIterator(tail.begin() + 3), tailbase.begin()); 79 | for (int k=0;k<(3-i);k++){ 80 | tailbase[3-k] = '='; 81 | } 82 | 83 | base64str += tailbase.data(); 84 | } 85 | return base64str; 86 | } 87 | 88 | // BASE64 编码. 89 | template 90 | void base64_encode(std::string src, OStreamIterator ostream_iterator) 91 | { 92 | unsigned one_third_len = src.length()/3; 93 | 94 | unsigned len_rounded_down = one_third_len*3; 95 | unsigned j = len_rounded_down + one_third_len; 96 | 97 | std::string base64str; 98 | 99 | typedef boost::archive::iterators::insert_linebreaks base64encode_linebreaks_Iterator; 100 | // 3 的整数倍可以编码. 101 | std::copy(base64encode_linebreaks_Iterator(src.begin()), base64encode_linebreaks_Iterator(src.begin() + len_rounded_down), 102 | ostream_iterator 103 | ); 104 | 105 | // 结尾 0 填充以及使用 = 补上 106 | if (len_rounded_down != src.length()) 107 | { 108 | std::string tail; 109 | tail.resize(4, 0); 110 | unsigned i=0; 111 | for(; i < src.length() - len_rounded_down; ++i) 112 | { 113 | tail[i] = src[len_rounded_down+i]; 114 | } 115 | 116 | std::string tailbase; 117 | tailbase.resize(5); 118 | 119 | std::copy(base64encode_linebreaks_Iterator(tail.begin()), base64encode_linebreaks_Iterator(tail.begin() + 3), tailbase.begin()); 120 | for (int k=0;k<(3-i);k++){ 121 | tailbase[3-k] = '='; 122 | } 123 | 124 | std::string base64str(tailbase.data()); 125 | std::copy(base64str.begin(), base64str.end(), ostream_iterator); 126 | } 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /include/boost/cfunction.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace boost { 11 | 12 | /* 13 | * cfunction 用于将 boost::function 拆分为一个 C 函数指针和一个 void * user_data 指针. 14 | * 15 | * 只要接受 一个 C 函数指针 + void * user_data 的地方, 就可以利用 cfunction 封装 boost::function, 16 | * 而 boost::function 又可以继续封装 boost::bind, boost::bind 的强大就无需多说了吧. 17 | * 18 | * 例子在是这样的, 相信这个例子一看大家全明白了, 呵呵 19 | * 20 | static void * my_thread_func2(int a, int b, int c, cfunction func2) 21 | { 22 | // 故意睡一下,保证 那个线程的 func2 对象析构,这个拷贝的 func2 也能维持好 C 函数的数据,避免下面的代码崩溃! 23 | sleep(10); 24 | std::cout << "这样就不用管理 func2 啦!自动释放不是?" << std::endl; 25 | std::cout << a << b << c << std::endl; 26 | return NULL; 27 | } 28 | 29 | static void * my_thread_func(int a, int b, int c) 30 | { 31 | cfunction func2; 32 | 33 | // 通过将自己绑定进去,func2 这个对象就不必保持生命期, 回调执行完毕会自动清空数据! 34 | func2 = boost::bind(&my_thread_func2, 3, 2, 3, func2); 35 | 36 | pthread_t new_thread; 37 | 38 | pthread_create(&new_thread, NULL, func2.c_func_ptr(), func2.c_void_ptr()); 39 | 40 | // 让线程进入不可 join 状态,无需等待线程退出 41 | pthread_detach(new_thread); 42 | 43 | std::cout << a << b << c << std::endl; 44 | return NULL; 45 | // 这里 func2 对象析构了,但是估计那个线程函数还没有执行完毕,如果不 bind 进去,到这里析构后,那个线程就会崩溃。 46 | // 但是,因为将 func2 对象绑定进去了,所以那个线程可以继续安然无恙的运行。 47 | } 48 | 49 | int main(int, char*[]) 50 | { 51 | cfunction func; 52 | 53 | func = boost::bind(&my_thread_func, 1, 2, 3); 54 | 55 | pthread_t new_thread; 56 | 57 | pthread_create(&new_thread, NULL, func.c_func_ptr(), func.c_void_ptr()); 58 | // 等待 线程退出,这样这个 func 对象要保证回调期间的生命期 59 | pthread_join(new_thread, NULL); 60 | 61 | // 等待另一个unjoinable 的线程退出 62 | sleep(100); 63 | return 0; 64 | } 65 | 66 | * 67 | */ 68 | template 69 | class cfunction 70 | { 71 | public: 72 | typedef typename boost::function_traits::result_type return_type; 73 | typedef boost::function closure_type; 74 | private: 75 | boost::shared_ptr m_wrapped_func; 76 | public: 77 | cfunction() 78 | : m_wrapped_func(make_shared()) 79 | { 80 | } 81 | 82 | cfunction(const closure_type &bindedfuntor) 83 | : m_wrapped_func(make_shared()) 84 | { 85 | *m_wrapped_func = bindedfuntor; 86 | } 87 | 88 | cfunction& operator = (const closure_type& bindedfuntor) 89 | { 90 | *m_wrapped_func = closure_type(bindedfuntor); 91 | return *this; 92 | } 93 | 94 | void * c_void_ptr() 95 | { 96 | return m_wrapped_func.get(); 97 | } 98 | 99 | CFuncType c_func_ptr() 100 | { 101 | return (CFuncType)wrapperd_callback; 102 | } 103 | 104 | private: // 这里是一套重载, 被 c_func_ptr() 依据 C 接口的类型挑一个出来并实例化. 105 | static return_type wrapperd_callback(void* user_data) 106 | { 107 | closure_type * wrapped_func = reinterpret_cast(user_data); 108 | 109 | return (*wrapped_func)(); 110 | } 111 | 112 | #define ARG(z, n, _) Arg ## n arg ## n 113 | 114 | #define TEXT(z, n, text) text ## n 115 | 116 | #define TTP(z, n, _) \ 117 | template< \ 118 | BOOST_PP_ENUM_ ## z(BOOST_PP_INC(n), TEXT, typename Arg) \ 119 | > \ 120 | static return_type wrapperd_callback(\ 121 | BOOST_PP_ENUM_ ## z(BOOST_PP_INC(n), ARG, nil), void* user_data) \ 122 | {\ 123 | closure_type * wrapped_func = reinterpret_cast(user_data); \ 124 | return (*wrapped_func)(BOOST_PP_ENUM_ ## z(BOOST_PP_INC(n), TEXT, arg) ); \ 125 | } 126 | 127 | BOOST_PP_REPEAT_FROM_TO(0, 9, TTP, nil) 128 | }; 129 | 130 | 131 | } // namespace boost 132 | -------------------------------------------------------------------------------- /include/boost/hash.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_HPP 10 | #define BOOST_HASH_HPP 11 | 12 | // Checksums 13 | #include 14 | #include 15 | 16 | // Cryptographic Hashes 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | // Infrastructure 25 | #include 26 | #include 27 | #include 28 | 29 | #endif // BOOST_HASH_HPP 30 | -------------------------------------------------------------------------------- /include/boost/hash/adler.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_ADLER_HPP 10 | #define BOOST_HASH_ADLER_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef BOOST_HASH_SHOW_PROGRESS 18 | #include 19 | #endif 20 | 21 | namespace boost { 22 | namespace hashes { 23 | 24 | template 25 | class basic_adler { 26 | public: 27 | static unsigned const value_bits = 8; 28 | typedef typename uint_t::least value_type; 29 | 30 | BOOST_STATIC_ASSERT(Bits % 2 == 0); 31 | BOOST_STATIC_ASSERT(Bits >= value_bits); 32 | 33 | static unsigned const digest_bits = Bits; 34 | 35 | static unsigned const word_bits = Bits; 36 | typedef typename uint_t::least word_type; 37 | 38 | typedef boost::array state_type; 39 | 40 | typedef hashes::digest digest_type; 41 | 42 | static word_type const modulo = detail::largest_prime::value; 43 | 44 | public: 45 | basic_adler() { reset(); } 46 | void reset() { state_[0] = 0; state_[1] = 1; } 47 | 48 | digest_type digest() const { 49 | word_type x = state_[0] << (Bits/2) | state_[1]; 50 | digest_type d; 51 | // RFC 1950, Section 2.2 stores the ADLER-32 in big-endian 52 | pack_n(&x, 1, 55 | d.data(), digest_bits/octet_bits); 56 | return d; 57 | } 58 | 59 | digest_type end_message() { 60 | digest_type d = digest(); 61 | reset(); 62 | return d; 63 | } 64 | 65 | public: 66 | 67 | basic_adler & 68 | update_one(value_type x) { 69 | if (Bits < 16) x %= modulo; // avoid overflow 70 | #ifdef BOOST_HASH_SHOW_PROGRESS 71 | printf("(%.4x, %.4x) + %.2x ==> ", (int)state_[0], (int)state_[1], (int)x); 72 | #endif 73 | state_[1] = (state_[1] + x) % modulo; 74 | state_[0] = (state_[0] + state_[1]) % modulo; 75 | #ifdef BOOST_HASH_SHOW_PROGRESS 76 | printf("(%.4x, %.4x) mod %.4x\n", (int)state_[0], (int)state_[1], (int)modulo); 77 | #endif 78 | return *this; 79 | } 80 | 81 | template 82 | basic_adler & 83 | update_n(IterT p, size_t n) { 84 | #ifndef BOOST_HASH_NO_OPTIMIZATION 85 | 86 | unsigned const fast_word_bits = (word_bits < 16 ? 16 : word_bits); 87 | typedef typename uint_t::least/*fast*/ fast_word_type; 88 | /* 89 | 90 | Worst-case behaviour for delaying the modulo: 91 | - every input is 255 92 | - s1 and s0 start out at modulo-1 93 | 94 | So after k inputs, we have: 95 | - s1 = (modulo-1) + k*255 96 | - s0 = (modulo-1) + Sigma(i = 1 to k)[ (modulo-1) + i*255 ] 97 | = (modulo-1) + k*(modulo-1) + Sigma(i = 1 to k)[ i*255 ] 98 | = (k+1)*(modulo-1) + 255 * Sigma(i = 1 to k)[i] 99 | = (k+1)*(modulo-1) + 255 * k*(k+1)/2 100 | 101 | And to avoid overflow we need s1, s0 <= 2**fast_word_bits - 1 102 | 103 | s1 = (modulo-1) + k*255 <= 2**fast_word_bits - 1 104 | k*255 <= 2**fast_word_bits - 1 - (modulo-1) 105 | k <= (2**fast_word_bits - modulo)/255 106 | 107 | Then use an overestimate for s0 to make the numbers nicer 108 | s0 < (k+1)*modulo + 256/2(k+1)**2 < 2**fast_word_bits 109 | 110 | Which solves as 111 | k < ( sqrt(512*2**fast_word_bits + modulo**2) - m - 256 )/256 112 | 113 | So then overestimating m as 2**(word_bits/2) and other safe approximations gives 114 | k < 2**((fast_word_bits-7)/2) - 2**((word_bits-16)/2) - 1 115 | 116 | Bits Limit 117 | ---- ----- 118 | 8 16 119 | 16 16 120 | 24 240 121 | 32 3840 122 | 40 61440 123 | 48 983040 124 | 56 15728640 125 | 64 251658240 126 | 127 | */ 128 | 129 | unsigned const less = (1 << (fast_word_bits/2 - 8)); 130 | unsigned const limit = (1 << (fast_word_bits/2 - 4)) 131 | - (word_bits < 16 ? 0 : less); 132 | 133 | #define BOOST_HASH_ADLER_STEP \ 134 | { value_type x = *p++; s1 += x; s0 += s1; } 135 | 136 | #define BOOST_HASH_ADLER_8_STEPS \ 137 | { \ 138 | BOOST_HASH_ADLER_STEP BOOST_HASH_ADLER_STEP \ 139 | BOOST_HASH_ADLER_STEP BOOST_HASH_ADLER_STEP \ 140 | BOOST_HASH_ADLER_STEP BOOST_HASH_ADLER_STEP \ 141 | BOOST_HASH_ADLER_STEP BOOST_HASH_ADLER_STEP \ 142 | } 143 | 144 | fast_word_type s0 = state_[0]; 145 | fast_word_type s1 = state_[1]; 146 | 147 | for ( ; n >= limit; n -= limit) { 148 | unsigned m = limit; 149 | for ( ; m >= 8; m -=8) { 150 | BOOST_HASH_ADLER_8_STEPS 151 | } 152 | while (m--) { 153 | BOOST_HASH_ADLER_STEP 154 | } 155 | s1 %= modulo; 156 | s0 %= modulo; 157 | } 158 | for ( ; n >= 8; n -=8) { 159 | BOOST_HASH_ADLER_8_STEPS 160 | } 161 | while (n--) { 162 | BOOST_HASH_ADLER_STEP 163 | } 164 | s1 %= modulo; 165 | s0 %= modulo; 166 | 167 | state_[0] = s0; 168 | state_[1] = s1; 169 | 170 | #else 171 | while (n--) update_one(*p++); 172 | #endif 173 | return *this; 174 | } 175 | 176 | template 177 | basic_adler & 178 | update(IterT b, IterT e, std::random_access_iterator_tag) { 179 | return update_n(b, e-b); 180 | } 181 | template 182 | basic_adler & 183 | update(IterT b, IterT e, Category) { 184 | while (b != e) update_one(*b++); 185 | return *this; 186 | } 187 | template 188 | basic_adler & 189 | update(IterT b, IterT e) { 190 | typedef typename std::iterator_traits::iterator_category cat; 191 | return update(b, e, cat()); 192 | } 193 | 194 | private: 195 | state_type state_; 196 | }; 197 | 198 | template 199 | struct adler { 200 | private: 201 | typedef basic_adler octet_hash_type; 202 | public: 203 | template 204 | struct stream_hash { 205 | BOOST_STATIC_ASSERT(value_bits == 8); 206 | typedef octet_hash_type type_; 207 | #ifdef BOOST_HASH_NO_HIDE_INTERNAL_TYPES 208 | typedef type_ type; 209 | #else 210 | struct type : type_ {}; 211 | #endif 212 | }; 213 | typedef typename octet_hash_type::digest_type digest_type; 214 | }; 215 | 216 | } // namespace hashes 217 | } // namespace boost 218 | 219 | #endif // BOOST_HASH_ADLER_HPP 220 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/basic_shacal.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_BASIC_SHACAL_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_BASIC_SHACAL_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef BOOST_HASH_SHOW_PROGRESS 17 | #include 18 | #endif 19 | 20 | // 21 | // Encrypt implemented directly from the SHA standard as found at 22 | // http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf 23 | // 24 | // Decrypt is a straight-forward inverse 25 | // 26 | // In SHA terminology: 27 | // - plaintext = H^(i-1) 28 | // - cyphertext = H^(i) 29 | // - key = M^(i) 30 | // - schedule = W 31 | // 32 | 33 | namespace boost { 34 | namespace hashes { 35 | namespace block_cyphers { 36 | 37 | // 38 | // The algorithms for SHA(-0) and SHA-1 are identical apart from the 39 | // key scheduling, so encapsulate that as a class that takes an 40 | // already-prepared schedule. (Constructor is protected to help keep 41 | // people from accidentally giving it just a key in a schedule.) 42 | // 43 | 44 | class basic_shacal { 45 | public: 46 | typedef detail::shacal_policy policy_type; 47 | 48 | static unsigned const word_bits = policy_type::word_bits; 49 | typedef policy_type::word_type word_type; 50 | 51 | static unsigned const key_bits = policy_type::key_bits; 52 | static unsigned const key_words = policy_type::key_words; 53 | typedef policy_type::key_type key_type; 54 | 55 | static unsigned const block_bits = policy_type::block_bits; 56 | static unsigned const block_words = policy_type::block_words; 57 | typedef policy_type::block_type block_type; 58 | 59 | static unsigned const rounds = policy_type::rounds; 60 | typedef policy_type::schedule_type schedule_type; 61 | 62 | protected: 63 | basic_shacal(schedule_type const &s) : schedule(s) {} 64 | private: 65 | schedule_type const schedule; 66 | 67 | public: 68 | block_type 69 | encypher(block_type const &plaintext) { 70 | return encypher_block(plaintext); 71 | } 72 | private: 73 | block_type 74 | encypher_block(block_type const &plaintext) { 75 | return encypher_block(schedule, plaintext); 76 | } 77 | static block_type 78 | encypher_block(schedule_type const &schedule, 79 | block_type const &plaintext) { 80 | 81 | #ifdef BOOST_HASH_SHOW_PROGRESS 82 | for (unsigned t = 0; t < block_words; ++t) { 83 | std::printf(word_bits == 32 ? 84 | "H[%d] = %.8x\n" : 85 | "H[%d] = %.16lx\n", 86 | t, plaintext[t]); 87 | } 88 | #endif 89 | 90 | // Initialize working variables with block 91 | word_type a = plaintext[0], b = plaintext[1], 92 | c = plaintext[2], d = plaintext[3], 93 | e = plaintext[4]; 94 | 95 | // Encypher block 96 | #ifdef BOOST_HASH_NO_OPTIMIZATION 97 | 98 | for (unsigned t = 0; t < rounds; ++t) { 99 | word_type T = policy_type::ROTL<5>(a) 100 | + policy_type::f(t,b,c,d) 101 | + e 102 | + policy_type::constant(t) 103 | + schedule[t]; 104 | 105 | e = d; 106 | d = c; 107 | c = policy_type::ROTL<30>(b); 108 | b = a; 109 | a = T; 110 | 111 | #ifdef BOOST_HASH_SHOW_PROGRESS 112 | printf(word_bits == 32 ? 113 | "t = %2d: %.8x %.8x %.8x %.8x %.8x\n" : 114 | "t = %2d: %.16lx %.16lx %.16lx %.16lx %.16lx\n", 115 | t, a, b, c, d, e); 116 | #endif 117 | } 118 | 119 | #else // BOOST_HASH_NO_OPTIMIZATION 120 | 121 | # ifdef BOOST_HASH_SHOW_PROGRESS 122 | # define BOOST_HASH_SHACAL1_TRANSFORM_PROGRESS \ 123 | printf(word_bits == 32 ? \ 124 | "t = %2d: %.8x %.8x %.8x %.8x %.8x\n" : \ 125 | "t = %2d: %.16lx %.16lx %.16lx %.16lx %.16lx\n", \ 126 | t, a, b, c, d, e); 127 | # else 128 | # define BOOST_HASH_SHACAL1_TRANSFORM_PROGRESS 129 | # endif 130 | 131 | # define BOOST_HASH_SHACAL1_TRANSFORM \ 132 | word_type T = policy_type::ROTL<5>(a) \ 133 | + policy_type::f(t,b,c,d) \ 134 | + e \ 135 | + policy_type::constant(t) \ 136 | + schedule[t]; \ 137 | e = d; \ 138 | d = c; \ 139 | c = policy_type::ROTL<30>(b); \ 140 | b = a; \ 141 | a = T; \ 142 | BOOST_HASH_SHACAL1_TRANSFORM_PROGRESS 143 | 144 | BOOST_STATIC_ASSERT(rounds == 80); 145 | BOOST_STATIC_ASSERT(rounds % block_words == 0); 146 | for (unsigned t = 0; t < 20; ) { 147 | for (int n = block_words; n--; ++t) { 148 | BOOST_HASH_SHACAL1_TRANSFORM 149 | } 150 | } 151 | for (unsigned t = 20; t < 40; ) { 152 | for (int n = block_words; n--; ++t) { 153 | BOOST_HASH_SHACAL1_TRANSFORM 154 | } 155 | } 156 | for (unsigned t = 40; t < 60; ) { 157 | for (int n = block_words; n--; ++t) { 158 | BOOST_HASH_SHACAL1_TRANSFORM 159 | } 160 | } 161 | for (unsigned t = 60; t < 80; ) { 162 | for (int n = block_words; n--; ++t) { 163 | BOOST_HASH_SHACAL1_TRANSFORM 164 | } 165 | } 166 | 167 | #endif 168 | 169 | block_type cyphertext = {{a, b, c, d, e}}; 170 | return cyphertext; 171 | } 172 | 173 | public: 174 | block_type 175 | decypher(block_type const &plaintext) { 176 | return decypher_block(plaintext); 177 | } 178 | private: 179 | block_type 180 | decypher_block(block_type const &plaintext) { 181 | return decypher_block(schedule, plaintext); 182 | } 183 | static block_type 184 | decypher_block(schedule_type const &schedule, 185 | block_type const &cyphertext) { 186 | 187 | #ifdef BOOST_HASH_SHOW_PROGRESS 188 | for (unsigned t = 0; t < block_words; ++t) { 189 | std::printf(word_bits == 32 ? 190 | "H[%d] = %.8x\n" : 191 | "H[%d] = %.16lx\n", 192 | t, cyphertext[t]); 193 | } 194 | #endif 195 | 196 | // Initialize working variables with block 197 | word_type a = cyphertext[0], b = cyphertext[1], 198 | c = cyphertext[2], d = cyphertext[3], 199 | e = cyphertext[4]; 200 | 201 | // Decypher block 202 | for (unsigned t = rounds; t--; ) { 203 | word_type T = a; 204 | 205 | a = b; 206 | b = policy_type::ROTR<30>(c); 207 | c = d; 208 | d = e; 209 | e = T 210 | - policy_type::ROTL<5>(a) 211 | - policy_type::f(t, b, c, d) 212 | - policy_type::constant(t) 213 | - schedule[t]; 214 | 215 | #ifdef BOOST_HASH_SHOW_PROGRESS 216 | std::printf(word_bits == 32 ? 217 | "t = %2d: %.8x %.8x %.8x %.8x %.8x\n" : 218 | "t = %2d: %.16lx %.16lx %.16lx %.16lx %.16lx\n", 219 | t, a, b, c, d, e); 220 | #endif 221 | } 222 | 223 | block_type plaintext = {{a, b, c, d, e}}; 224 | return plaintext; 225 | } 226 | 227 | }; 228 | 229 | } // namespace block_cyphers 230 | } // namespace hashes 231 | } // namespace boost 232 | 233 | #endif // BOOST_HASH_BLOCK_CYPHERS_BASIC_SHACAL_HPP 234 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/detail/basic_functions.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_DETAIL_BASIC_FUNCTIONS_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_DETAIL_BASIC_FUNCTIONS_HPP 11 | 12 | #include 13 | #include 14 | 15 | namespace boost { 16 | namespace hashes { 17 | namespace block_cyphers { 18 | namespace detail { 19 | 20 | template 21 | struct basic_functions { 22 | static unsigned const word_bits = word_bits_N; 23 | typedef typename uint_t::exact word_type; 24 | 25 | static word_type SHR(word_type x, unsigned n) { 26 | return x >> n; 27 | } 28 | template 29 | static word_type SHR(word_type x) { 30 | BOOST_STATIC_ASSERT(n < word_bits); 31 | return x >> n; 32 | } 33 | static word_type SHL(word_type x, unsigned n) { 34 | return x << n; 35 | } 36 | template 37 | static word_type SHL(word_type x) { 38 | BOOST_STATIC_ASSERT(n < word_bits); 39 | return x << n; 40 | } 41 | 42 | static word_type ROTR(word_type x, unsigned n) { 43 | return SHR(x, n) | SHL(x, word_bits-n); 44 | } 45 | template 46 | static word_type ROTR(word_type x) { 47 | return SHR(x) | SHL(x); 48 | } 49 | static word_type ROTL(word_type x, unsigned n) { 50 | return SHL(x, n) | SHR(x, word_bits-n); 51 | } 52 | template 53 | static word_type ROTL(word_type x) { 54 | return SHL(x) | SHR(x); 55 | } 56 | }; 57 | 58 | } // namespace detail 59 | } // namespace block_cyphers 60 | } // namespace hashes 61 | } // namespace boost 62 | 63 | #endif // BOOST_HASH_BLOCK_CYPHERS_DETAIL_BASIC_FUNCTIONS_HPP 64 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/detail/md4_policy.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_DETAIL_MD4_POLICY_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_DETAIL_MD4_POLICY_HPP 11 | 12 | #include 13 | #include 14 | 15 | namespace boost { 16 | namespace hashes { 17 | namespace block_cyphers { 18 | namespace detail { 19 | 20 | struct md4_functions : basic_functions<32> { 21 | static word_type ff(word_type x, word_type y, word_type z) { 22 | return (x & y) | (~x & z); 23 | } 24 | static word_type gg(word_type x, word_type y, word_type z) { 25 | return (x & y) | (x & z) | (y & z); 26 | } 27 | static word_type hh(word_type x, word_type y, word_type z) { 28 | return x ^ y ^ z; 29 | } 30 | }; 31 | 32 | struct md4_policy : md4_functions { 33 | 34 | static unsigned const block_bits = 128; 35 | static unsigned const block_words = block_bits/word_bits; 36 | typedef array block_type; 37 | 38 | static unsigned const key_words = 16; 39 | static unsigned const key_bits = key_words*word_bits; 40 | typedef array key_type; 41 | 42 | static unsigned const rounds = 48; 43 | typedef array key_indexes_type; 44 | 45 | static unsigned key_index(unsigned t) { 46 | static key_indexes_type const key_indexes = {{ 47 | 0, 1, 2, 3, 48 | 4, 5, 6, 7, 49 | 8, 9, 10, 11, 50 | 12, 13, 14, 15, 51 | 52 | 0, 4, 8, 12, 53 | 1, 5, 9, 13, 54 | 2, 6, 10, 14, 55 | 3, 7, 11, 15, 56 | 57 | 0, 8, 4, 12, 58 | 2, 10, 6, 14, 59 | 1, 9, 5, 13, 60 | 3, 11, 7, 15, 61 | }}; 62 | return key_indexes[t]; 63 | } 64 | }; 65 | 66 | } // namespace detail 67 | } // namespace block_cyphers 68 | } // namespace hashes 69 | } // namespace boost 70 | 71 | #endif // BOOST_HASH_BLOCK_CYPHERS_DETAIL_MD4_POLICY_HPP 72 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/detail/md5_policy.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_DETAIL_MD5_POLICY_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_DETAIL_MD5_POLICY_HPP 11 | 12 | #include 13 | #include 14 | 15 | namespace boost { 16 | namespace hashes { 17 | namespace block_cyphers { 18 | namespace detail { 19 | 20 | struct md5_functions : detail::basic_functions<32> { 21 | static word_type ff(word_type x, word_type y, word_type z) { 22 | return (x & y) | (~x & z); 23 | } 24 | static word_type gg(word_type x, word_type y, word_type z) { 25 | return (x & z) | (y & ~z); 26 | // return F(z, x, y); 27 | } 28 | static word_type hh(word_type x, word_type y, word_type z) { 29 | return x ^ y ^ z; 30 | } 31 | static word_type ii(word_type x, word_type y, word_type z) { 32 | return y ^ (x | ~z); 33 | } 34 | }; 35 | 36 | struct md5_policy : md5_functions { 37 | 38 | static unsigned const block_bits = 128; 39 | static unsigned const block_words = block_bits/word_bits; 40 | typedef array block_type; 41 | 42 | static unsigned const key_words = 16; 43 | static unsigned const key_bits = key_words*word_bits; 44 | typedef array key_type; 45 | 46 | static unsigned const rounds = 64; 47 | typedef array constants_type; 48 | typedef array key_indexes_type; 49 | 50 | static word_type constant(unsigned t) { 51 | static constants_type const constants = {{ 52 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 53 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 54 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 55 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 56 | 57 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 58 | 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 59 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 60 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 61 | 62 | 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 63 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 64 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 65 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 66 | 67 | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 68 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 69 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 70 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, 71 | }}; 72 | return constants[t]; 73 | } 74 | 75 | static unsigned key_index(unsigned t) { 76 | static key_indexes_type const key_indexes = {{ 77 | 0, 1, 2, 3, 78 | 4, 5, 6, 7, 79 | 8, 9, 10, 11, 80 | 12, 13, 14, 15, 81 | 82 | 1, 6, 11, 0, 83 | 5, 10, 15, 4, 84 | 9, 14, 3, 8, 85 | 13, 2, 7, 12, 86 | 87 | 5, 8, 11, 14, 88 | 1, 4, 7, 10, 89 | 13, 0, 3, 6, 90 | 9, 12, 15, 2, 91 | 92 | 0, 7, 14, 5, 93 | 12, 3, 10, 1, 94 | 8, 15, 6, 13, 95 | 4, 11, 2, 9, 96 | }}; 97 | return key_indexes[t]; 98 | } 99 | }; 100 | 101 | } // namespace detail 102 | } // namespace block_cyphers 103 | } // namespace hashes 104 | } // namespace boost 105 | 106 | #endif // BOOST_HASH_BLOCK_CYPHERS_DETAIL_MD5_POLICY_HPP 107 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/detail/shacal1_policy.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL1_POLICY_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL1_POLICY_HPP 11 | 12 | #include 13 | 14 | namespace boost { 15 | namespace hashes { 16 | namespace block_cyphers { 17 | namespace detail { 18 | 19 | typedef shacal_policy shacal1_policy; 20 | 21 | } // namespace detail 22 | } // namespace block_cyphers 23 | } // namespace hashes 24 | } // namespace boost 25 | 26 | #endif // BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL1_POLICY_HPP 27 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/detail/shacal2_policy.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL2_POLICY_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL2_POLICY_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | namespace boost { 18 | namespace hashes { 19 | namespace block_cyphers { 20 | namespace detail { 21 | 22 | template 23 | struct basic_shacal2_policy : shacal2_functions { 24 | 25 | using shacal2_functions::word_bits; 26 | typedef typename shacal2_functions::word_type word_type; 27 | 28 | static unsigned const block_words = 8; 29 | static unsigned const block_bits = block_words*word_bits; 30 | typedef array block_type; 31 | 32 | static unsigned const key_words = 16; 33 | static unsigned const key_bits = key_words*word_bits; 34 | typedef array key_type; 35 | 36 | }; 37 | 38 | template 39 | struct shacal2_policy; 40 | 41 | template <> 42 | struct shacal2_policy<256> : basic_shacal2_policy<32> { 43 | 44 | static unsigned const rounds = 64; 45 | typedef array schedule_type; 46 | typedef array constants_type; 47 | 48 | static word_type constant(unsigned t) { 49 | static constants_type const constants = {{ 50 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 51 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 52 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 53 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 54 | 55 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 56 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 57 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 58 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 59 | 60 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 61 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 62 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 63 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 64 | 65 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 66 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 67 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 68 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, 69 | }}; 70 | return constants[t]; 71 | } 72 | 73 | }; 74 | 75 | template <> 76 | struct shacal2_policy<512> : basic_shacal2_policy<64> { 77 | 78 | static unsigned const rounds = 80; 79 | typedef array schedule_type; 80 | typedef array constants_type; 81 | 82 | static word_type constant(unsigned t) { 83 | static constants_type const constants = {{ 84 | UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), 85 | UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), 86 | UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), 87 | UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), 88 | UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), 89 | UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), 90 | UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), 91 | UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), 92 | 93 | UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), 94 | UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), 95 | UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), 96 | UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), 97 | UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), 98 | UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), 99 | UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), 100 | UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), 101 | 102 | UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), 103 | UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), 104 | UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), 105 | UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), 106 | UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), 107 | UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), 108 | UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), 109 | UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), 110 | 111 | UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), 112 | UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), 113 | UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), 114 | UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), 115 | UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), 116 | UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), 117 | UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), 118 | UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), 119 | 120 | UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), 121 | UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), 122 | UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), 123 | UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), 124 | UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), 125 | UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), 126 | UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), 127 | UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817), 128 | }}; 129 | return constants[t]; 130 | } 131 | 132 | }; 133 | 134 | } // namespace detail 135 | } // namespace block_cyphers 136 | } // namespace hashes 137 | } // namespace boost 138 | 139 | #endif // BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL2_POLICY_HPP 140 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/detail/shacal_functions.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL_FUNCTIONS_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL_FUNCTIONS_HPP 11 | 12 | #include 13 | 14 | namespace boost { 15 | namespace hashes { 16 | namespace block_cyphers { 17 | namespace detail { 18 | 19 | // 20 | // Implemented directly from the standard as found at 21 | // http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf 22 | // 23 | 24 | // Specifically, subsection 4.1 25 | 26 | template 27 | struct basic_shacal_functions : basic_functions { 28 | typedef typename basic_functions::word_type word_type; 29 | 30 | static word_type Ch(word_type x, word_type y, word_type z) { 31 | return (x & y) ^ (~x & z); 32 | } 33 | static word_type Maj(word_type x, word_type y, word_type z) { 34 | return (x & y) ^ (x & z) ^ (y & z); 35 | } 36 | }; 37 | 38 | struct shacal_functions : public basic_shacal_functions<32> { 39 | static word_type Parity(word_type x, word_type y, word_type z) { 40 | return x ^ y ^ z; 41 | } 42 | static word_type f(unsigned t, word_type x, word_type y, word_type z) { 43 | if (t < 40) { 44 | if (t < 20) return Ch(x, y, z); 45 | } else { 46 | if (t < 60) return Maj(x, y, z); 47 | } 48 | return Parity(x, y, z); 49 | } 50 | }; 51 | 52 | typedef shacal_functions shacal0_functions; 53 | typedef shacal_functions shacal1_functions; 54 | 55 | template 56 | struct shacal2_functions; 57 | template <> 58 | struct shacal2_functions<32> : public basic_shacal_functions<32> { 59 | static word_type Sigma_0(word_type x) { 60 | return ROTR< 2>(x) ^ ROTR<13>(x) ^ ROTR<22>(x); 61 | } 62 | static word_type Sigma_1(word_type x) { 63 | return ROTR< 6>(x) ^ ROTR<11>(x) ^ ROTR<25>(x); 64 | } 65 | 66 | static word_type sigma_0(word_type x) { 67 | return ROTR< 7>(x) ^ ROTR<18>(x) ^ SHR< 3>(x); 68 | } 69 | static word_type sigma_1(word_type x) { 70 | return ROTR<17>(x) ^ ROTR<19>(x) ^ SHR<10>(x); 71 | } 72 | }; 73 | template <> 74 | struct shacal2_functions<64> : public basic_shacal_functions<64> { 75 | static word_type Sigma_0(word_type x) { 76 | return ROTR<28>(x) ^ ROTR<34>(x) ^ ROTR<39>(x); 77 | } 78 | static word_type Sigma_1(word_type x) { 79 | return ROTR<14>(x) ^ ROTR<18>(x) ^ ROTR<41>(x); 80 | } 81 | 82 | static word_type sigma_0(word_type x) { 83 | return ROTR< 1>(x) ^ ROTR< 8>(x) ^ SHR< 7>(x); 84 | } 85 | static word_type sigma_1(word_type x) { 86 | return ROTR<19>(x) ^ ROTR<61>(x) ^ SHR< 6>(x); 87 | } 88 | }; 89 | 90 | } // namespace detail 91 | } // namespace block_cyphers 92 | } // namespace hashes 93 | } // namespace boost 94 | 95 | #endif // BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL_FUNCTIONS_HPP 96 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/detail/shacal_policy.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL_POLICY_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL_POLICY_HPP 11 | 12 | #include 13 | #include 14 | 15 | namespace boost { 16 | namespace hashes { 17 | namespace block_cyphers { 18 | namespace detail { 19 | 20 | struct shacal_policy : shacal_functions { 21 | 22 | static unsigned const block_words = 5; 23 | static unsigned const block_bits = block_words*word_bits; 24 | typedef array block_type; 25 | 26 | static unsigned const key_words = 16; 27 | static unsigned const key_bits = key_words*word_bits; 28 | typedef array key_type; 29 | 30 | static unsigned const rounds = 80; 31 | typedef array schedule_type; 32 | typedef array constants_type; 33 | 34 | static word_type constant(unsigned t) { 35 | static constants_type const constants = {{ 36 | 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 37 | 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 38 | 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 39 | 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 40 | 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 41 | 42 | 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 43 | 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 44 | 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 45 | 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 46 | 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 47 | 48 | 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 49 | 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 50 | 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 51 | 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 52 | 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 53 | 54 | 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 55 | 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 56 | 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 57 | 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 58 | 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 59 | }}; 60 | return constants[t]; 61 | } 62 | 63 | }; 64 | 65 | typedef shacal_policy shacal0_policy; 66 | 67 | } // namespace detail 68 | } // namespace block_cyphers 69 | } // namespace hashes 70 | } // namespace boost 71 | 72 | #endif // BOOST_HASH_BLOCK_CYPHERS_DETAIL_SHACAL_POLICY_HPP 73 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/detail/threefish_policy.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_DETAIL_THREEFISH_POLICY_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_DETAIL_THREEFISH_POLICY_HPP 11 | 12 | #include 13 | #include 14 | 15 | namespace boost { 16 | namespace hashes { 17 | namespace block_cyphers { 18 | namespace detail { 19 | 20 | template 21 | struct basic_threefish_policy : basic_functions<64> { 22 | 23 | static unsigned const block_bits = Version; 24 | static unsigned const block_words = block_bits/word_bits; 25 | typedef array block_type; 26 | 27 | static unsigned const key_bits = Version; 28 | static unsigned const key_words = key_bits/word_bits; 29 | typedef array key_type; 30 | typedef array key_schedule_type; 31 | 32 | static unsigned const tweak_bits = 128; 33 | static unsigned const tweak_words = tweak_bits/word_bits; 34 | typedef array tweak_type; 35 | typedef array tweak_schedule_type; 36 | 37 | typedef array permutations_type; 38 | typedef array, 8> 39 | rotations_type; 40 | 41 | }; 42 | 43 | template 44 | struct threefish_policy; 45 | 46 | template <> 47 | struct threefish_policy<256> : basic_threefish_policy<256> { 48 | 49 | static unsigned const rounds = 72; 50 | typedef array constants_type; 51 | 52 | static unsigned permutation(unsigned i) { 53 | static permutations_type const permutations = {{ 54 | 0, 3, 2, 1, 55 | }}; 56 | return permutations[i]; 57 | } 58 | 59 | static unsigned rotation(unsigned d, unsigned j) { 60 | static rotations_type const rotations = {{ 61 | #ifdef BOOST_HASH_THREEFISH_OLD_ROTATION_CONSTANTS 62 | {{ 5, 56}}, 63 | {{36, 28}}, 64 | {{13, 46}}, 65 | {{58, 44}}, 66 | {{26, 20}}, 67 | {{53, 35}}, 68 | {{11, 42}}, 69 | {{59, 50}}, 70 | #else 71 | {{14, 16}}, 72 | {{52, 57}}, 73 | {{23, 40}}, 74 | {{ 5, 37}}, 75 | {{25, 33}}, 76 | {{46, 12}}, 77 | {{58, 22}}, 78 | {{32, 32}}, 79 | #endif 80 | }}; 81 | return rotations[d][j]; 82 | } 83 | 84 | }; 85 | 86 | template <> 87 | struct threefish_policy<512> : basic_threefish_policy<512> { 88 | 89 | static unsigned const rounds = 72; 90 | typedef array constants_type; 91 | 92 | static unsigned permutation(unsigned i) { 93 | static permutations_type const permutations = {{ 94 | 2, 1, 4, 7, 6, 5, 0, 3, 95 | }}; 96 | return permutations[i]; 97 | } 98 | 99 | static unsigned rotation(unsigned d, unsigned j) { 100 | static rotations_type const rotations = {{ 101 | #ifdef BOOST_HASH_THREEFISH_OLD_ROTATION_CONSTANTS 102 | {{38, 30, 50, 53}}, 103 | {{48, 20, 43, 31}}, 104 | {{34, 14, 15, 27}}, 105 | {{26, 12, 58, 7}}, 106 | {{33, 49, 8, 42}}, 107 | {{39, 27, 41, 14}}, 108 | {{29, 26, 11, 9}}, 109 | {{33, 51, 39, 35}}, 110 | #else 111 | {{46, 36, 19, 37}}, 112 | {{33, 27, 14, 42}}, 113 | {{17, 49, 36, 39}}, 114 | {{44, 9, 54, 56}}, 115 | {{39, 30, 34, 24}}, 116 | {{13, 50, 10, 17}}, 117 | {{25, 29, 39, 43}}, 118 | {{ 8, 35, 56, 22}}, 119 | #endif 120 | }}; 121 | return rotations[d][j]; 122 | } 123 | 124 | }; 125 | 126 | template <> 127 | struct threefish_policy<1024> : basic_threefish_policy<1024> { 128 | 129 | static unsigned const rounds = 80; 130 | typedef array constants_type; 131 | 132 | static unsigned permutation(unsigned i) { 133 | static permutations_type const permutations = {{ 134 | 0, 9, 2, 13, 6, 11, 4, 15, 10, 7, 12, 3, 14, 5, 8, 1, 135 | }}; 136 | return permutations[i]; 137 | } 138 | 139 | static unsigned rotation(unsigned d, unsigned j) { 140 | static rotations_type const rotations = {{ 141 | #ifdef BOOST_HASH_THREEFISH_OLD_ROTATION_CONSTANTS 142 | {{55, 43, 37, 40, 16, 22, 38, 12}}, 143 | {{25, 25, 46, 13, 14, 13, 52, 57}}, 144 | {{33, 8, 18, 57, 21, 12, 32, 54}}, 145 | {{34, 43, 25, 60, 44, 9, 59, 34}}, 146 | {{28, 7, 47, 48, 51, 9, 35, 41}}, 147 | {{17, 6, 18, 25, 43, 42, 40, 15}}, 148 | {{58, 7, 32, 45, 19, 18, 2, 56}}, 149 | {{47, 49, 27, 58, 37, 48, 53, 56}}, 150 | #else 151 | {{24, 13, 8, 47, 8, 17, 22, 37}}, 152 | {{38, 19, 10, 55, 49, 18, 23, 52}}, 153 | {{33, 4, 51, 13, 34, 41, 59, 17}}, 154 | {{ 5, 20, 48, 41, 47, 28, 16, 25}}, 155 | {{41, 9, 37, 31, 12, 47, 44, 30}}, 156 | {{16, 34, 56, 51, 4, 53, 42, 41}}, 157 | {{31, 44, 47, 46, 19, 42, 44, 25}}, 158 | {{ 9, 48, 35, 52, 23, 31, 37, 20}}, 159 | #endif 160 | }}; 161 | return rotations[d][j]; 162 | } 163 | 164 | }; 165 | 166 | } // namespace detail 167 | } // namespace block_cyphers 168 | } // namespace hashes 169 | } // namespace boost 170 | 171 | #endif // BOOST_HASH_BLOCK_CYPHERS_DETAIL_THREEFISH_POLICY_HPP 172 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/md4.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_MD4_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_MD4_HPP 11 | 12 | #include 13 | 14 | #ifdef BOOST_HASH_SHOW_PROGRESS 15 | #include 16 | #endif 17 | 18 | // 19 | // Encrypt implemented directly from the RFC as found at 20 | // http://www.faqs.org/rfcs/rfc1320.html 21 | // 22 | // Decrypt is a straight-forward inverse 23 | // 24 | // In MD4 terminology: 25 | // - plaintext = AA, BB, CC, and DD 26 | // - cyphertext = A, B, C, and D 27 | // - key = M^(i) and X 28 | // 29 | 30 | namespace boost { 31 | namespace hashes { 32 | namespace block_cyphers { 33 | 34 | class md4 { 35 | public: 36 | typedef detail::md4_policy policy_type; 37 | 38 | static unsigned const word_bits = policy_type::word_bits; 39 | typedef policy_type::word_type word_type; 40 | 41 | static unsigned const key_bits = policy_type::key_bits; 42 | static unsigned const key_words = policy_type::key_words; 43 | typedef policy_type::key_type key_type; 44 | 45 | static unsigned const block_bits = policy_type::block_bits; 46 | static unsigned const block_words = policy_type::block_words; 47 | typedef policy_type::block_type block_type; 48 | 49 | public: 50 | md4(key_type const &k) : key(k) { 51 | #ifdef BOOST_HASH_SHOW_PROGRESS 52 | for (unsigned t = 0; t < key_words; ++t) { 53 | std::printf("X[%2d] = %.8x\n", 54 | t, key[t]); 55 | } 56 | #endif 57 | } 58 | private: 59 | key_type const key; 60 | 61 | public: 62 | block_type 63 | encypher(block_type const &plaintext) { 64 | return encypher_block(plaintext); 65 | } 66 | private: 67 | block_type 68 | encypher_block(block_type const &plaintext) { 69 | return encypher_block(key, plaintext); 70 | } 71 | static block_type 72 | encypher_block(key_type const &key, 73 | block_type const &plaintext) { 74 | 75 | #ifdef BOOST_HASH_SHOW_PROGRESS 76 | for (unsigned t = 0; t < block_words; ++t) { 77 | std::printf("%c%c = %.8x\n", 78 | 'A'+t, 'A'+t, plaintext[t]); 79 | } 80 | #endif 81 | 82 | // Initialize working variables with block 83 | word_type a = plaintext[0], b = plaintext[1], 84 | c = plaintext[2], d = plaintext[3]; 85 | 86 | // Encypher block 87 | #define BOOST_HASH_MD4_ENCYPHER_STEP(aa, bb, cc, dd, fun, k, s, val) \ 88 | { \ 89 | word_type T = aa \ 90 | + policy_type::fun(bb,cc,dd) \ 91 | + key[policy_type::key_index(k)] \ 92 | + val; \ 93 | aa = policy_type::ROTL(T); \ 94 | } 95 | for (unsigned t = 0; t < 16; t += 4) { 96 | BOOST_HASH_MD4_ENCYPHER_STEP(a, b, c, d, ff, t+0, 3, 0x00000000) 97 | BOOST_HASH_MD4_ENCYPHER_STEP(d, a, b, c, ff, t+1, 7, 0x00000000) 98 | BOOST_HASH_MD4_ENCYPHER_STEP(c, d, a, b, ff, t+2, 11, 0x00000000) 99 | BOOST_HASH_MD4_ENCYPHER_STEP(b, c, d, a, ff, t+3, 19, 0x00000000) 100 | 101 | #ifdef BOOST_HASH_SHOW_PROGRESS 102 | printf("Round 1: %.8x %.8x %.8x %.8x\n", 103 | a, b, c, d); 104 | #endif 105 | } 106 | for (unsigned t = 16; t < 32; t += 4) { 107 | BOOST_HASH_MD4_ENCYPHER_STEP(a, b, c, d, gg, t+0, 3, 0x5a827999) 108 | BOOST_HASH_MD4_ENCYPHER_STEP(d, a, b, c, gg, t+1, 5, 0x5a827999) 109 | BOOST_HASH_MD4_ENCYPHER_STEP(c, d, a, b, gg, t+2, 9, 0x5a827999) 110 | BOOST_HASH_MD4_ENCYPHER_STEP(b, c, d, a, gg, t+3, 13, 0x5a827999) 111 | 112 | #ifdef BOOST_HASH_SHOW_PROGRESS 113 | printf("Round 2: %.8x %.8x %.8x %.8x\n", 114 | a, b, c, d); 115 | #endif 116 | } 117 | for (unsigned t = 32; t < 48; t += 4) { 118 | BOOST_HASH_MD4_ENCYPHER_STEP(a, b, c, d, hh, t+0, 3, 0x6ed9eba1) 119 | BOOST_HASH_MD4_ENCYPHER_STEP(d, a, b, c, hh, t+1, 9, 0x6ed9eba1) 120 | BOOST_HASH_MD4_ENCYPHER_STEP(c, d, a, b, hh, t+2, 11, 0x6ed9eba1) 121 | BOOST_HASH_MD4_ENCYPHER_STEP(b, c, d, a, hh, t+3, 15, 0x6ed9eba1) 122 | 123 | #ifdef BOOST_HASH_SHOW_PROGRESS 124 | printf("Round 3: %.8x %.8x %.8x %.8x\n", 125 | a, b, c, d); 126 | #endif 127 | } 128 | 129 | block_type cyphertext = {{a, b, c, d}}; 130 | return cyphertext; 131 | } 132 | 133 | public: 134 | block_type 135 | decypher(block_type const &plaintext) { 136 | return decypher_block(plaintext); 137 | } 138 | private: 139 | block_type 140 | decypher_block(block_type const &plaintext) { 141 | return decypher_block(key, plaintext); 142 | } 143 | static block_type 144 | decypher_block(key_type const &key, 145 | block_type const &cyphertext) { 146 | 147 | #ifdef BOOST_HASH_SHOW_PROGRESS 148 | for (unsigned t = 0; t < block_words; ++t) { 149 | std::printf("%c = %.8x\n", 150 | 'A'+t, cyphertext[t]); 151 | } 152 | #endif 153 | 154 | // Initialize working variables with block 155 | word_type a = cyphertext[0], b = cyphertext[1], 156 | c = cyphertext[2], d = cyphertext[3]; 157 | 158 | // Decypher block 159 | #define BOOST_HASH_MD4_DECYPHER_STEP(aa, bb, cc, dd, fun, k, s, val) \ 160 | { \ 161 | word_type T = policy_type::ROTR(aa); \ 162 | aa = T \ 163 | - policy_type::fun(bb,cc,dd) \ 164 | - key[policy_type::key_index(k)] \ 165 | - val; \ 166 | } 167 | for (unsigned t = 48; t -= 4, t >= 32; ) { 168 | BOOST_HASH_MD4_DECYPHER_STEP(b, c, d, a, hh, t+3, 15, 0x6ed9eba1) 169 | BOOST_HASH_MD4_DECYPHER_STEP(c, d, a, b, hh, t+2, 11, 0x6ed9eba1) 170 | BOOST_HASH_MD4_DECYPHER_STEP(d, a, b, c, hh, t+1, 9, 0x6ed9eba1) 171 | BOOST_HASH_MD4_DECYPHER_STEP(a, b, c, d, hh, t+0, 3, 0x6ed9eba1) 172 | 173 | #ifdef BOOST_HASH_SHOW_PROGRESS 174 | printf("Round 3: %.8x %.8x %.8x %.8x\n", 175 | a, b, c, d); 176 | #endif 177 | } 178 | for (unsigned t = 32; t -= 4, t >= 16; ) { 179 | BOOST_HASH_MD4_DECYPHER_STEP(b, c, d, a, gg, t+3, 13, 0x5a827999) 180 | BOOST_HASH_MD4_DECYPHER_STEP(c, d, a, b, gg, t+2, 9, 0x5a827999) 181 | BOOST_HASH_MD4_DECYPHER_STEP(d, a, b, c, gg, t+1, 5, 0x5a827999) 182 | BOOST_HASH_MD4_DECYPHER_STEP(a, b, c, d, gg, t+0, 3, 0x5a827999) 183 | 184 | #ifdef BOOST_HASH_SHOW_PROGRESS 185 | printf("Round 2: %.8x %.8x %.8x %.8x\n", 186 | a, b, c, d); 187 | #endif 188 | } 189 | for (unsigned t = 16; t -= 4, t < 16; ) { 190 | BOOST_HASH_MD4_DECYPHER_STEP(b, c, d, a, ff, t+3, 19, 0x00000000) 191 | BOOST_HASH_MD4_DECYPHER_STEP(c, d, a, b, ff, t+2, 11, 0x00000000) 192 | BOOST_HASH_MD4_DECYPHER_STEP(d, a, b, c, ff, t+1, 7, 0x00000000) 193 | BOOST_HASH_MD4_DECYPHER_STEP(a, b, c, d, ff, t+0, 3, 0x00000000) 194 | 195 | #ifdef BOOST_HASH_SHOW_PROGRESS 196 | printf("Round 1: %.8x %.8x %.8x %.8x\n", 197 | a, b, c, d); 198 | #endif 199 | } 200 | 201 | block_type plaintext = {{a, b, c, d}}; 202 | return plaintext; 203 | } 204 | 205 | }; 206 | 207 | } // namespace block_cyphers 208 | } // namespace hashes 209 | } // namespace boost 210 | 211 | #endif // BOOST_HASH_BLOCK_CYPHERS_MD4_HPP 212 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/md5.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_MD5_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_MD5_HPP 11 | 12 | #include 13 | 14 | #ifdef BOOST_HASH_SHOW_PROGRESS 15 | #include 16 | #endif 17 | 18 | // 19 | // Encrypt implemented directly from the RFC as found at 20 | // http://www.faqs.org/rfcs/rfc1321.html 21 | // 22 | // Decrypt is a straight-forward inverse 23 | // 24 | // In MD5 terminology: 25 | // - plaintext = AA, BB, CC, and DD 26 | // - cyphertext = A, B, C, and D 27 | // - key = M^(i) and X 28 | // 29 | 30 | namespace boost { 31 | namespace hashes { 32 | namespace block_cyphers { 33 | 34 | class md5 { 35 | public: 36 | typedef detail::md5_policy policy_type; 37 | 38 | static unsigned const word_bits = policy_type::word_bits; 39 | typedef policy_type::word_type word_type; 40 | 41 | static unsigned const key_bits = policy_type::key_bits; 42 | static unsigned const key_words = policy_type::key_words; 43 | typedef policy_type::key_type key_type; 44 | 45 | static unsigned const block_bits = policy_type::block_bits; 46 | static unsigned const block_words = policy_type::block_words; 47 | typedef policy_type::block_type block_type; 48 | 49 | public: 50 | md5(key_type const &k) : key(k) { 51 | #ifdef BOOST_HASH_SHOW_PROGRESS 52 | for (unsigned t = 0; t < key_words; ++t) { 53 | std::printf("X[%2d] = %.8x\n", 54 | t, key[t]); 55 | } 56 | #endif 57 | } 58 | private: 59 | key_type const key; 60 | 61 | public: 62 | block_type 63 | encypher(block_type const &plaintext) { 64 | return encypher_block(plaintext); 65 | } 66 | private: 67 | block_type 68 | encypher_block(block_type const &plaintext) { 69 | return encypher_block(key, plaintext); 70 | } 71 | static block_type 72 | encypher_block(key_type const &key, 73 | block_type const &plaintext) { 74 | 75 | #ifdef BOOST_HASH_SHOW_PROGRESS 76 | for (unsigned t = 0; t < block_words; ++t) { 77 | std::printf("%c%c = %.8x\n", 78 | 'A'+t, 'A'+t, plaintext[t]); 79 | } 80 | #endif 81 | 82 | // Initialize working variables with block 83 | word_type a = plaintext[0], b = plaintext[1], 84 | c = plaintext[2], d = plaintext[3]; 85 | 86 | // Encypher block 87 | #define BOOST_HASH_MD5_ENCYPHER_STEP(aa, bb, cc, dd, fun, k, s, i) \ 88 | { \ 89 | word_type T = aa \ 90 | + policy_type::fun(bb,cc,dd) \ 91 | + key[policy_type::key_index(k)] \ 92 | + policy_type::constant(i-1); \ 93 | aa = bb + policy_type::ROTL(T); \ 94 | } 95 | for (unsigned t = 0; t < 16; t += 4) { 96 | BOOST_HASH_MD5_ENCYPHER_STEP(a, b, c, d, ff, t+0, 7, t+1) 97 | BOOST_HASH_MD5_ENCYPHER_STEP(d, a, b, c, ff, t+1, 12, t+2) 98 | BOOST_HASH_MD5_ENCYPHER_STEP(c, d, a, b, ff, t+2, 17, t+3) 99 | BOOST_HASH_MD5_ENCYPHER_STEP(b, c, d, a, ff, t+3, 22, t+4) 100 | 101 | #ifdef BOOST_HASH_SHOW_PROGRESS 102 | printf("Round 1: %.8x %.8x %.8x %.8x\n", 103 | a, b, c, d); 104 | #endif 105 | } 106 | for (unsigned t = 16; t < 32; t += 4) { 107 | BOOST_HASH_MD5_ENCYPHER_STEP(a, b, c, d, gg, t+0, 5, t+1) 108 | BOOST_HASH_MD5_ENCYPHER_STEP(d, a, b, c, gg, t+1, 9, t+2) 109 | BOOST_HASH_MD5_ENCYPHER_STEP(c, d, a, b, gg, t+2, 14, t+3) 110 | BOOST_HASH_MD5_ENCYPHER_STEP(b, c, d, a, gg, t+3, 20, t+4) 111 | 112 | #ifdef BOOST_HASH_SHOW_PROGRESS 113 | printf("Round 2: %.8x %.8x %.8x %.8x\n", 114 | a, b, c, d); 115 | #endif 116 | } 117 | for (unsigned t = 32; t < 48; t += 4) { 118 | BOOST_HASH_MD5_ENCYPHER_STEP(a, b, c, d, hh, t+0, 4, t+1) 119 | BOOST_HASH_MD5_ENCYPHER_STEP(d, a, b, c, hh, t+1, 11, t+2) 120 | BOOST_HASH_MD5_ENCYPHER_STEP(c, d, a, b, hh, t+2, 16, t+3) 121 | BOOST_HASH_MD5_ENCYPHER_STEP(b, c, d, a, hh, t+3, 23, t+4) 122 | 123 | #ifdef BOOST_HASH_SHOW_PROGRESS 124 | printf("Round 3: %.8x %.8x %.8x %.8x\n", 125 | a, b, c, d); 126 | #endif 127 | } 128 | for (unsigned t = 48; t < 64; t += 4) { 129 | BOOST_HASH_MD5_ENCYPHER_STEP(a, b, c, d, ii, t+0, 6, t+1) 130 | BOOST_HASH_MD5_ENCYPHER_STEP(d, a, b, c, ii, t+1, 10, t+2) 131 | BOOST_HASH_MD5_ENCYPHER_STEP(c, d, a, b, ii, t+2, 15, t+3) 132 | BOOST_HASH_MD5_ENCYPHER_STEP(b, c, d, a, ii, t+3, 21, t+4) 133 | 134 | #ifdef BOOST_HASH_SHOW_PROGRESS 135 | printf("Round 4: %.8x %.8x %.8x %.8x\n", 136 | a, b, c, d); 137 | #endif 138 | } 139 | 140 | block_type cyphertext = {{a, b, c, d}}; 141 | return cyphertext; 142 | } 143 | 144 | public: 145 | block_type 146 | decypher(block_type const &plaintext) { 147 | return decypher_block(plaintext); 148 | } 149 | private: 150 | block_type 151 | decypher_block(block_type const &plaintext) { 152 | return decypher_block(key, plaintext); 153 | } 154 | static block_type 155 | decypher_block(key_type const &key, 156 | block_type const &cyphertext) { 157 | 158 | #ifdef BOOST_HASH_SHOW_PROGRESS 159 | for (unsigned t = 0; t < block_words; ++t) { 160 | std::printf("%c = %.8x\n", 161 | 'A'+t, cyphertext[t]); 162 | } 163 | #endif 164 | 165 | // Initialize working variables with block 166 | word_type a = cyphertext[0], b = cyphertext[1], 167 | c = cyphertext[2], d = cyphertext[3]; 168 | 169 | // Decypher block 170 | #define BOOST_HASH_MD5_DECYPHER_STEP(aa, bb, cc, dd, fun, k, s, i) \ 171 | { \ 172 | word_type T = policy_type::ROTR(aa - bb); \ 173 | aa = T \ 174 | - policy_type::fun(bb,cc,dd) \ 175 | - key[policy_type::key_index(k)] \ 176 | - policy_type::constant(i-1); \ 177 | } 178 | for (unsigned t = 64; t -= 4, t >= 48; ) { 179 | BOOST_HASH_MD5_DECYPHER_STEP(b, c, d, a, ii, t+3, 21, t+4) 180 | BOOST_HASH_MD5_DECYPHER_STEP(c, d, a, b, ii, t+2, 15, t+3) 181 | BOOST_HASH_MD5_DECYPHER_STEP(d, a, b, c, ii, t+1, 10, t+2) 182 | BOOST_HASH_MD5_DECYPHER_STEP(a, b, c, d, ii, t+0, 6, t+1) 183 | 184 | #ifdef BOOST_HASH_SHOW_PROGRESS 185 | printf("Round 4: %.8x %.8x %.8x %.8x\n", 186 | a, b, c, d); 187 | #endif 188 | } 189 | for (unsigned t = 48; t -= 4, t >= 32; ) { 190 | BOOST_HASH_MD5_DECYPHER_STEP(b, c, d, a, hh, t+3, 23, t+4) 191 | BOOST_HASH_MD5_DECYPHER_STEP(c, d, a, b, hh, t+2, 16, t+3) 192 | BOOST_HASH_MD5_DECYPHER_STEP(d, a, b, c, hh, t+1, 11, t+2) 193 | BOOST_HASH_MD5_DECYPHER_STEP(a, b, c, d, hh, t+0, 4, t+1) 194 | 195 | #ifdef BOOST_HASH_SHOW_PROGRESS 196 | printf("Round 3: %.8x %.8x %.8x %.8x\n", 197 | a, b, c, d); 198 | #endif 199 | } 200 | for (unsigned t = 32; t -= 4, t >= 16; ) { 201 | BOOST_HASH_MD5_DECYPHER_STEP(b, c, d, a, gg, t+3, 20, t+4) 202 | BOOST_HASH_MD5_DECYPHER_STEP(c, d, a, b, gg, t+2, 14, t+3) 203 | BOOST_HASH_MD5_DECYPHER_STEP(d, a, b, c, gg, t+1, 9, t+2) 204 | BOOST_HASH_MD5_DECYPHER_STEP(a, b, c, d, gg, t+0, 5, t+1) 205 | 206 | #ifdef BOOST_HASH_SHOW_PROGRESS 207 | printf("Round 2: %.8x %.8x %.8x %.8x\n", 208 | a, b, c, d); 209 | #endif 210 | } 211 | for (unsigned t = 16; t -= 4, t < 16; ) { 212 | BOOST_HASH_MD5_DECYPHER_STEP(b, c, d, a, ff, t+3, 22, t+4) 213 | BOOST_HASH_MD5_DECYPHER_STEP(c, d, a, b, ff, t+2, 17, t+3) 214 | BOOST_HASH_MD5_DECYPHER_STEP(d, a, b, c, ff, t+1, 12, t+2) 215 | BOOST_HASH_MD5_DECYPHER_STEP(a, b, c, d, ff, t+0, 7, t+1) 216 | 217 | #ifdef BOOST_HASH_SHOW_PROGRESS 218 | printf("Round 1: %.8x %.8x %.8x %.8x\n", 219 | a, b, c, d); 220 | #endif 221 | } 222 | 223 | block_type plaintext = {{a, b, c, d}}; 224 | return plaintext; 225 | } 226 | 227 | }; 228 | 229 | } // namespace block_cyphers 230 | } // namespace hashes 231 | } // namespace boost 232 | 233 | #endif // BOOST_HASH_BLOCK_CYPHERS_MD5_HPP 234 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/shacal.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_SHACAL_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_SHACAL_HPP 11 | 12 | #include 13 | 14 | // 15 | // Implemented directly from the SHA standard as found at 16 | // http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf 17 | // 18 | // In SHA terminology: 19 | // - plaintext = H^(i-1) 20 | // - cyphertext = H^(i) 21 | // - key = M^(i) 22 | // - schedule = W 23 | // 24 | 25 | namespace boost { 26 | namespace hashes { 27 | namespace block_cyphers { 28 | 29 | // The original FIPS-180 seems to be gone, but FIPS 180-1 30 | // (http://www.itl.nist.gov/fipspubs/fip180-1.htm) says the only change 31 | // in SHA-1 from SHA(-0) is the rotation in the key scheduling. 32 | class shacal : public basic_shacal { 33 | public: 34 | shacal(key_type const &k) 35 | : basic_shacal(build_schedule(k)) {} 36 | shacal(schedule_type s) 37 | : basic_shacal((prepare_schedule(s), s)) {} 38 | private: 39 | static schedule_type 40 | build_schedule(key_type const &key) { 41 | // Copy key into beginning of schedule 42 | schedule_type schedule; 43 | for (unsigned t = 0; t < key_words; ++t) { 44 | schedule[t] = key[t]; 45 | } 46 | prepare_schedule(schedule); 47 | return schedule; 48 | } 49 | static void 50 | prepare_schedule(schedule_type &schedule) { 51 | #ifdef BOOST_HASH_SHOW_PROGRESS 52 | for (unsigned t = 0; t < key_words; ++t) { 53 | std::printf(word_bits == 32 ? 54 | "W[%2d] = %.8x\n" : 55 | "W[%2d] = %.16lx\n", 56 | t, schedule[t]); 57 | } 58 | #endif 59 | 60 | for (unsigned t = key_words; t < rounds; ++t) { 61 | schedule[t] = schedule[t-3] 62 | ^ schedule[t-8] 63 | ^ schedule[t-14] 64 | ^ schedule[t-16]; 65 | } 66 | } 67 | }; 68 | typedef shacal shacal0; 69 | 70 | } // namespace block_cyphers 71 | } // namespace hashes 72 | } // namespace boost 73 | 74 | #endif // BOOST_HASH_BLOCK_CYPHERS_SHACAL_HPP 75 | -------------------------------------------------------------------------------- /include/boost/hash/block_cyphers/shacal1.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_BLOCK_CYPHERS_SHACAL1_HPP 10 | #define BOOST_HASH_BLOCK_CYPHERS_SHACAL1_HPP 11 | 12 | #include 13 | 14 | // 15 | // Implemented directly from the SHA standard as found at 16 | // http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf 17 | // 18 | // In SHA terminology: 19 | // - plaintext = H^(i-1) 20 | // - cyphertext = H^(i) 21 | // - key = M^(i) 22 | // - schedule = W 23 | // 24 | 25 | namespace boost { 26 | namespace hashes { 27 | namespace block_cyphers { 28 | 29 | class shacal1 : public basic_shacal { 30 | public: 31 | shacal1(key_type const &k) 32 | : basic_shacal(build_schedule(k)) {} 33 | shacal1(schedule_type s) 34 | : basic_shacal((prepare_schedule(s), s)) {} 35 | private: 36 | static schedule_type 37 | build_schedule(key_type const &key) { 38 | // Copy key into beginning of schedule 39 | schedule_type schedule; 40 | for (unsigned t = 0; t < key_words; ++t) { 41 | schedule[t] = key[t]; 42 | } 43 | prepare_schedule(schedule); 44 | return schedule; 45 | } 46 | static void 47 | prepare_schedule(schedule_type &schedule) { 48 | #ifdef BOOST_HASH_SHOW_PROGRESS 49 | for (unsigned t = 0; t < key_words; ++t) { 50 | std::printf(word_bits == 32 ? 51 | "W[%2d] = %.8x\n" : 52 | "W[%2d] = %.16lx\n", 53 | t, schedule[t]); 54 | } 55 | #endif 56 | 57 | for (unsigned t = key_words; t < rounds; ++t) { 58 | schedule[t] = schedule[t-3] 59 | ^ schedule[t-8] 60 | ^ schedule[t-14] 61 | ^ schedule[t-16]; 62 | schedule[t] = policy_type::ROTL<1>(schedule[t]); 63 | } 64 | } 65 | }; 66 | 67 | } // namespace block_cyphers 68 | } // namespace hashes 69 | } // namespace boost 70 | 71 | #endif // BOOST_HASH_BLOCK_CYPHERS_SHACAL1_HPP 72 | -------------------------------------------------------------------------------- /include/boost/hash/compute_digest.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_COMPUTE_DIGEST_HPP 10 | #define BOOST_HASH_COMPUTE_DIGEST_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | namespace boost { 24 | namespace hashes { 25 | 26 | template 27 | typename hash_T::digest_type 28 | compute_digest(iter_T b, iter_T e) { 29 | typedef typename std::iterator_traits::value_type value_type; 30 | BOOST_STATIC_ASSERT(std::numeric_limits::is_specialized); 31 | unsigned const value_bits = 32 | std::numeric_limits::digits + 33 | std::numeric_limits::is_signed; 34 | typedef typename hash_T::template stream_hash::type 35 | stream_hash_type; 36 | stream_hash_type sh; 37 | sh.update(b, e); 38 | return sh.end_message(); 39 | } 40 | 41 | template 42 | typename hash_T::digest_type 43 | compute_digest_n(iter_T b, size_t n) { 44 | typedef typename std::iterator_traits::value_type value_type; 45 | BOOST_STATIC_ASSERT(std::numeric_limits::is_specialized); 46 | unsigned const value_bits = 47 | std::numeric_limits::digits + 48 | std::numeric_limits::is_signed; 49 | typedef typename hash_T::template stream_hash::type 50 | stream_hash_type; 51 | stream_hash_type sh; 52 | sh.update_n(b, n); 53 | return sh.end_message(); 54 | } 55 | 56 | template 57 | typename hash_T::digest_type 58 | compute_digest(range_T const &r) { 59 | return compute_digest(boost::begin(r), boost::end(r)); 60 | } 61 | 62 | template 63 | typename hash_T::digest_type 64 | compute_digest_n(container_T const &c) { 65 | return compute_digest_n(c.begin(), c.size()); 66 | } 67 | 68 | template 69 | typename hash_T::digest_type 70 | compute_digest_data(container_T const &c) { 71 | return compute_digest_n(c.data(), c.size()); 72 | } 73 | 74 | template 76 | typename hash_T::digest_type 77 | compute_digest(std::basic_string const &s) { 78 | return compute_digest_data(s); 79 | } 80 | template 82 | typename hash_T::digest_type 83 | compute_digest_n(std::basic_string const &s) { 84 | return compute_digest_data(s); 85 | } 86 | 87 | template 88 | typename hash_T::digest_type 89 | compute_digest(char const *p) { 90 | return compute_digest_n(p, std::strlen(p)); 91 | } 92 | 93 | template 94 | typename hash_T::digest_type 95 | compute_digest(wchar_t const *p) { 96 | return compute_digest_n(p, std::wcslen(p)); 97 | } 98 | 99 | template 100 | struct digest_computer { 101 | typedef typename hash_T::digest_type digest_type; 102 | template 103 | digest_type operator()(T const &t) { 104 | return compute_digest(t); 105 | } 106 | template 107 | digest_type operator()(T const &t, U const &u) { 108 | return compute_digest(t, u); 109 | } 110 | }; 111 | 112 | template 113 | digest_computer 114 | compute_digest() { 115 | return digest_computer(); 116 | } 117 | 118 | template 119 | struct digest_computer_n { 120 | typedef typename hash_T::digest_type digest_type; 121 | template 122 | digest_type operator()(T const &t) { 123 | return compute_digest_n(t); 124 | } 125 | template 126 | digest_type operator()(T const &t, U const &u) { 127 | return compute_digest_n(t, u); 128 | } 129 | }; 130 | 131 | template 132 | digest_computer_n 133 | compute_digest_n() { 134 | return digest_computer_n(); 135 | } 136 | 137 | template 138 | struct digest_computer_data { 139 | typedef typename hash_T::digest_type digest_type; 140 | template 141 | digest_type operator()(T const &t) { 142 | return compute_digest_data(t); 143 | } 144 | template 145 | digest_type operator()(T const &t, U const &u) { 146 | return compute_digest_data(t, u); 147 | } 148 | }; 149 | 150 | template 151 | digest_computer_data 152 | compute_digest_data() { 153 | return digest_computer_data(); 154 | } 155 | 156 | } // namespace hashes 157 | } // namespace boost 158 | 159 | #endif // BOOST_HASH_COMPUTE_DIGEST_HPP 160 | -------------------------------------------------------------------------------- /include/boost/hash/crc.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_CRC_HPP 10 | #define BOOST_HASH_CRC_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #ifdef BOOST_HASH_SHOW_PROGRESS 21 | #include 22 | #endif 23 | 24 | namespace boost { 25 | namespace hashes { 26 | 27 | // Boost.CRC undefs this, so re-define it 28 | #define BOOST_CRC_PARM_TYPE typename ::boost::uint_t::fast 29 | 30 | template 33 | class basic_crc { 34 | public: 35 | typedef crc_optimal crc_computer; 38 | typedef typename crc_computer::value_type word_type; 39 | 40 | static unsigned const value_bits = CHAR_BIT; 41 | typedef typename uint_t::least value_type; 42 | 43 | BOOST_STATIC_ASSERT(Bits >= value_bits); 44 | 45 | static unsigned const digest_bits = Bits; 46 | typedef hashes::digest digest_type; 47 | 48 | public: 49 | basic_crc() { reset(); } 50 | void reset() { crc_.reset(); } 51 | 52 | digest_type digest() const { 53 | word_type x = crc_.checksum(); 54 | digest_type d; 55 | // TODO: Justify bit order 56 | pack_n(&x, 1, 59 | d.data(), digest_bits/octet_bits); 60 | return d; 61 | } 62 | 63 | digest_type end_message() { 64 | digest_type d = digest(); 65 | reset(); 66 | return d; 67 | } 68 | 69 | public: 70 | basic_crc & 71 | update_one(value_type x) { 72 | #ifdef BOOST_HASH_SHOW_PROGRESS 73 | printf("%.8lx + %.2x ==> ", (long)crc_.checksum(), (int)x); 74 | #endif 75 | crc_.process_byte(x); 76 | #ifdef BOOST_HASH_SHOW_PROGRESS 77 | printf("%.8lx\n", (long)crc_.checksum()); 78 | #endif 79 | return *this; 80 | } 81 | 82 | template 83 | basic_crc & 84 | update_n(IterT p, size_t n) { 85 | while (n--) update_one(*p++); 86 | return *this; 87 | } 88 | #ifndef BOOST_HASH_NO_OPTIMIZATION 89 | template 90 | basic_crc & 91 | update_n(ValT const *p, size_t n) { 92 | if (sizeof(ValT) == 1) { 93 | crc_.process_bytes(p, n); 94 | } else { 95 | while (n--) update_one(*p++); 96 | } 97 | return *this; 98 | } 99 | template 100 | basic_crc & 101 | update_n(ValT *p, size_t n) { 102 | return update_n((ValT const *)p, n); 103 | } 104 | #endif 105 | 106 | template 107 | basic_crc & 108 | update(IterT b, IterT e, std::random_access_iterator_tag) { 109 | return update_n(b, e-b); 110 | } 111 | template 112 | basic_crc & 113 | update(IterT b, IterT e, Category) { 114 | while (b != e) update_one(*b++); 115 | return *this; 116 | } 117 | template 118 | basic_crc & 119 | update(IterT b, IterT e) { 120 | typedef typename std::iterator_traits::iterator_category cat; 121 | return update(b, e, cat()); 122 | } 123 | 124 | private: 125 | crc_computer crc_; 126 | }; 127 | 128 | template 131 | struct crc { 132 | private: 133 | typedef basic_crc 134 | octet_hash_type; 135 | public: 136 | template 137 | struct stream_hash { 138 | BOOST_STATIC_ASSERT(value_bits == CHAR_BIT); 139 | typedef octet_hash_type type_; 140 | #ifdef BOOST_HASH_NO_HIDE_INTERNAL_TYPES 141 | typedef type_ type; 142 | #else 143 | struct type : type_ {}; 144 | #endif 145 | }; 146 | typedef typename octet_hash_type::digest_type digest_type; 147 | }; 148 | 149 | // http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html#CRC-algorithm 150 | typedef crc<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc32_png; 151 | 152 | } // namespace hashes 153 | } // namespace boost 154 | 155 | #endif // BOOST_HASH_CRC_HPP 156 | -------------------------------------------------------------------------------- /include/boost/hash/cubehash.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_CUBEHASH_HPP 10 | #define BOOST_HASH_CUBEHASH_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | // As of 2009-07-15, the submission to NIST for SHA-3 is CubeHash16/32 17 | // http://cubehash.cr.yp.to/submission/tweak.pdf 18 | #ifndef BOOST_HASH_CUBEHASH_DEFAULT_R 19 | #define BOOST_HASH_CUBEHASH_DEFAULT_R 16 20 | #endif 21 | #ifndef BOOST_HASH_CUBEHASH_DEFAULT_B 22 | #define BOOST_HASH_CUBEHASH_DEFAULT_B 32 23 | #endif 24 | 25 | namespace boost { 26 | namespace hashes { 27 | 28 | template 29 | struct cubehash_compressor { 30 | public: 31 | typedef detail::cubehash_policy policy_type; 32 | 33 | static unsigned const word_bits = policy_type::word_bits; 34 | typedef typename policy_type::word_type word_type; 35 | 36 | static unsigned const state_bits = policy_type::state_bits; 37 | static unsigned const state_words = policy_type::state_words; 38 | typedef typename policy_type::state_type state_type; 39 | 40 | static unsigned const block_bits = policy_type::block_bits; 41 | static unsigned const block_words = policy_type::block_words; 42 | typedef typename policy_type::block_type block_type; 43 | 44 | public: 45 | void 46 | operator()(state_type &state, 47 | block_type const &block) { 48 | process_block(state, block); 49 | } 50 | 51 | private: 52 | static void 53 | process_block(state_type &state, 54 | block_type const &block) { 55 | #ifdef BOOST_HASH_SHOW_PROGRESS 56 | printf("Xoring the following block to the state:\n"); 57 | for (unsigned i = 0; i < block.size(); ++i) { 58 | printf("%.8x%c", block[i], (i+1) != block.size() ? ' ' : '\n'); 59 | } 60 | #endif 61 | for (unsigned i = 0; i < block_words; ++i) { 62 | state[i] ^= block[i]; 63 | } 64 | policy_type::transform_r(state); 65 | } 66 | 67 | }; 68 | 69 | template 70 | struct cubehash_finalizer { 71 | typedef detail::cubehash_policy policy_type; 72 | typedef typename policy_type::state_type state_type; 73 | void operator()(state_type &state) const { 74 | state[31] ^= 1; 75 | policy_type::transform_10r(state); 76 | } 77 | }; 78 | 79 | // 80 | // If the second and third parameters are unspecified (or left 0), then 81 | // the first parameter is the number of bits in the digest, and 82 | // r and b will be set to defaults. 83 | // 84 | // Otherwise the three parameters are r, b, and h respectively. 85 | // 86 | 87 | template 88 | struct cubehash; 89 | 90 | template 91 | struct cubehash { 92 | private: 93 | typedef detail::cubehash_policy policy_type; 94 | public: 95 | typedef merkle_damgard_block_hash< 96 | stream_endian::little_octet_big_bit, 97 | policy_type::digest_bits, 98 | typename policy_type::iv_generator, 99 | cubehash_compressor, 100 | cubehash_finalizer 101 | > block_hash_type_; 102 | #ifdef BOOST_HASH_NO_HIDE_INTERNAL_TYPES 103 | typedef block_hash_type_ block_hash_type; 104 | #else 105 | struct block_hash_type : block_hash_type_ {}; 106 | #endif 107 | template 108 | struct stream_hash { 109 | typedef stream_preprocessor< 110 | stream_endian::little_octet_big_bit, 111 | value_bits, 112 | 0, // No length padding! 113 | block_hash_type 114 | > type_; 115 | #ifdef BOOST_HASH_NO_HIDE_INTERNAL_TYPES 116 | typedef type_ type; 117 | #else 118 | struct type : type_ {}; 119 | #endif 120 | }; 121 | typedef typename block_hash_type::digest_type digest_type; 122 | }; 123 | 124 | template 125 | struct cubehash 126 | : cubehash {}; 129 | 130 | } // namespace hashes 131 | } // namespace boost 132 | 133 | #endif // BOOST_HASH_CUBEHASH_HPP 134 | -------------------------------------------------------------------------------- /include/boost/hash/davies_meyer_compressor.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_DAVIES_MEYER_COMPRESSOR_HPP 10 | #define BOOST_HASH_DAVIES_MEYER_COMPRESSOR_HPP 11 | 12 | namespace boost { 13 | namespace hashes { 14 | 15 | // 16 | // The Davies-Meyer construction turns a block cypher 17 | // into a one-way compression function 18 | // 19 | // http://en.wikipedia.org/wiki/One-way_compression_function#Davies-Meyer 20 | // 21 | 22 | template 23 | struct davies_meyer_compressor { 24 | public: 25 | typedef block_cypher_T block_cypher_type; 26 | 27 | static unsigned const word_bits = block_cypher_type::word_bits; 28 | typedef typename block_cypher_type::word_type word_type; 29 | 30 | static unsigned const state_bits = block_cypher_type::block_bits; 31 | static unsigned const state_words = block_cypher_type::block_words; 32 | typedef typename block_cypher_type::block_type state_type; 33 | 34 | static unsigned const block_bits = block_cypher_type::key_bits; 35 | static unsigned const block_words = block_cypher_type::key_words; 36 | typedef typename block_cypher_type::key_type block_type; 37 | 38 | public: 39 | void 40 | operator()(state_type &state, 41 | block_type const &block) { 42 | process_block(state, block); 43 | } 44 | 45 | private: 46 | static void 47 | process_block(state_type &state, 48 | block_type const &block) { 49 | block_cypher_type cypher(block); 50 | state_type new_state = cypher.encypher((state_type const &)state); 51 | combine_F f; 52 | f(state, new_state); 53 | } 54 | }; 55 | 56 | } // namespace hashes 57 | } // namespace boost 58 | 59 | #endif // BOOST_HASH_DAVIES_MEYER_COMPRESSOR_HPP 60 | -------------------------------------------------------------------------------- /include/boost/hash/detail/basic_functions.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_DETAIL_BASIC_FUNCTIONS_HPP 10 | #define BOOST_HASH_DETAIL_BASIC_FUNCTIONS_HPP 11 | 12 | #include 13 | 14 | namespace boost { 15 | namespace hashes { 16 | namespace detail { 17 | 18 | using block_cyphers::detail::basic_functions; 19 | 20 | } // namespace detail 21 | } // namespace hashes 22 | } // namespace boost 23 | 24 | #endif // BOOST_HASH_DETAIL_BASIC_FUNCTIONS_HPP 25 | -------------------------------------------------------------------------------- /include/boost/hash/detail/exploder.hpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2010 Scott McMurray. 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // (See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt) 7 | // 8 | 9 | #ifndef BOOST_HASH_DETAIL_EXPLODER_HPP 10 | #define BOOST_HASH_DETAIL_EXPLODER_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | namespace boost { 23 | namespace hashes { 24 | namespace detail { 25 | 26 | // By definition, for all exploders, InputBits > OutputBits, 27 | // so we're taking one value and splitting it into many smaller values 28 | 29 | template ::value_type> 31 | struct outvalue_helper { 32 | typedef T type; 33 | }; 34 | template 35 | struct outvalue_helper { 36 | typedef typename uint_t::least type; 37 | }; 38 | 39 | template 42 | struct exploder_step; 43 | 44 | template 45 | struct exploder_step, 46 | InputBits, OutputBits, k> { 47 | template 48 | static void step(InputValue const &x, OutIter &out) { 49 | int const shift = InputBits - (OutputBits+k); 50 | typedef typename outvalue_helper::type OutValue; 51 | InputValue y = unbounded_shr(x); 52 | *out++ = OutValue(low_bits(y)); 53 | } 54 | }; 55 | 56 | template 57 | struct exploder_step, 58 | InputBits, OutputBits, k> { 59 | template 60 | static void step(InputValue const &x, OutIter &out) { 61 | int const kb = (k % UnitBits); 62 | int const ku = k - kb; 63 | int const shift = 64 | OutputBits >= UnitBits ? k : 65 | InputBits >= UnitBits ? ku + (UnitBits-(OutputBits+kb)) : 66 | InputBits - (OutputBits+kb); 67 | typedef typename outvalue_helper::type OutValue; 68 | InputValue y = unbounded_shr(x); 69 | *out++ = OutValue(low_bits(y)); 70 | } 71 | }; 72 | 73 | template 74 | struct exploder_step, 75 | InputBits, OutputBits, k> { 76 | template 77 | static void step(InputValue const &x, OutIter &out) { 78 | int const kb = (k % UnitBits); 79 | int const ku = k - kb; 80 | int const shift = 81 | OutputBits >= UnitBits ? InputBits - (OutputBits+k) : 82 | InputBits >= UnitBits ? InputBits - (UnitBits+ku) + kb : 83 | kb; 84 | typedef typename outvalue_helper::type OutValue; 85 | InputValue y = unbounded_shr(x); 86 | *out++ = OutValue(low_bits(y)); 87 | } 88 | }; 89 | 90 | template 91 | struct exploder_step, 92 | InputBits, OutputBits, k> { 93 | template 94 | static void step(InputValue const &x, OutIter &out) { 95 | int const shift = k; 96 | typedef typename outvalue_helper::type OutValue; 97 | InputValue y = unbounded_shr(x); 98 | *out++ = OutValue(low_bits(y)); 99 | } 100 | }; 101 | 102 | template 103 | struct exploder_step, 104 | InputBits, OutputBits, k> { 105 | template 106 | static void step(InputValue const &x, OutIter &out) { 107 | typedef typename outvalue_helper::type OutValue; 108 | BOOST_STATIC_ASSERT(sizeof(InputValue)*CHAR_BIT == InputBits); 109 | BOOST_STATIC_ASSERT(sizeof(OutValue)*CHAR_BIT == OutputBits); 110 | OutValue value; 111 | std::memcpy(&value, (char*)&x + k/CHAR_BIT, OutputBits/CHAR_BIT); 112 | *out++ = value; 113 | } 114 | }; 115 | 116 | template 119 | struct exploder; 120 | 121 | template