32 #ifndef MCKL_RANDOM_SKEIN_HPP 33 #define MCKL_RANDOM_SKEIN_HPP 44 template <
typename Generator>
59 static constexpr
int key() {
return 0; }
62 static constexpr
int cfg() {
return 4; }
65 static constexpr
int prs() {
return 8; }
68 static constexpr
int pub() {
return 12; }
71 static constexpr
int kdf() {
return 16; }
74 static constexpr
int non() {
return 20; }
77 static constexpr
int msg() {
return 48; }
80 static constexpr
int out() {
return 63; }
92 explicit param_type(std::size_t N = 0,
const void *data =
nullptr,
93 int type = type_field::msg())
94 : N_(N), data_(static_cast<const char *>(data)), type_(type & 0x3F)
99 std::size_t
bits()
const {
return N_; }
104 return N_ / CHAR_BIT + (N_ % CHAR_BIT == 0 ? 0 : 1);
108 const char *
data()
const {
return data_; }
111 int type()
const {
return type_; }
137 : N_(N), K_(K), C_(configure(N_, 0, 0, 0))
139 internal::union_le<char>(C_);
145 std::memset(&ret, 0,
sizeof(ret));
148 if (K_.bits() != 0) {
149 set_type(t1, type_field::key());
150 ret.G_ = ubi(ret.G_, K_, 0, t1);
153 set_type(t1, type_field::cfg());
154 ret.G_ = ubi(ret.G_,
param_type(256, C_.data()), 0, t1);
161 if (state.type_ == 0) {
163 "**Skein::hash** M[0].type() <= type_field::cfg()");
166 "**Skein::hash** M[i].type() <= M[i - 1].type()");
170 set_type(t1, M.
type());
171 state.G_ = ubi(state.G_, M, 0, t1);
172 state.type_ = M.
type();
178 "**Skein::hash** M[n - 1].type() >= type_field::out()");
180 Skein::output(state.G_, N_, H);
186 std::array<std::uint64_t, 4> C_;
207 int Yl = 20,
int Yf = 20,
int Ym = 2)
213 , C_(configure(N_, Yl_, Yf_, Ym_))
215 internal::union_le<char>(C_);
225 if (K_.bits() != 0) {
226 set_type(t1, type_field::key());
227 ret.G_ = ubi(ret.G_, K_, 0, t1);
230 set_type(t1, type_field::cfg());
231 ret.G_ = ubi(ret.G_,
param_type(256, C_.data()), 0, t1);
239 "**Skein::hash** M[i].type() != type_field::msg()");
241 ubi_tree_m1(state.G_, M, Yl_, state.M1_, state.t0_);
246 state.G_ = ubi_tree(state.G_, Yl_, Yf_, Ym_, 1, state.M1_);
247 Skein::output(state.G_, N_, H);
256 std::array<std::uint64_t, 4> C_;
263 static constexpr std::size_t
bits() {
return sizeof(
key_type) * CHAR_BIT; }
295 if ((Yl | Yf | Ym) == 0) {
297 auto state = hasher.
init();
298 for (std::size_t i = 0; i != n; ++i) {
299 hasher.
update(state, M[i]);
304 auto state = hasher.
init();
305 for (std::size_t i = 0; i != n; ++i) {
306 hasher.
update(state, M[i]);
313 static_assert(bits() >= 64,
314 "**Skein** used with a Generator with less than 64 bits");
316 static_assert(std::is_unsigned<value_type>::value,
317 "**Skein** used with a Generator with key_type::value_type not an " 318 "unsigned integer type");
320 static_assert(std::numeric_limits<value_type>::digits >= 32,
321 "**Skein** used with a Generator with key_type::value_type less than " 324 static_assert(
sizeof(
key_type) == Generator::size(),
325 "**Skein** used with a Generator with block and key different in " 331 std::size_t N = M.
bits();
332 const char *C = M.
data();
336 const bool B = N % CHAR_BIT != 0;
341 get_block(t0, C, message[0], N);
342 set_flags(t1,
true,
true, B);
343 enc_block(H, message[0], t0, t1);
349 set_flags(t1,
true,
false, B);
350 get_block(t0, C, message[0]);
351 enc_block(H, message[0], t0, t1);
357 get_block(t0, C, message[0], N);
358 set_flags(t1,
false,
true, B);
359 enc_block(H, message[0], t0, t1);
365 set_flags(t1,
false,
false, B);
366 const std::size_t n = N / bits() - (N % bits() == 0 ? 1 : 0);
367 const std::size_t m = n / k;
368 const std::size_t l = n % k;
369 for (std::size_t i = 0; i != m; ++i) {
370 std::memcpy(message.data(), C, bytes() * k);
371 for (std::size_t j = 0; j != k; ++j) {
373 enc_block(H, message[j], t0, t1);
378 std::memcpy(message.data(), C, bytes() * l);
379 for (std::size_t j = 0; j != l; ++j) {
381 enc_block(H, message[j], t0, t1);
387 set_flags(t1,
false,
true, B);
388 get_block(t0, C, message[0], N);
389 enc_block(H, message[0], t0, t1);
402 set_type(t1, type_field::msg());
403 M1.push_back(ubi(G, M, t0, t1));
406 std::size_t Nl = bytes() * (const_one<std::size_t>() << Yl);
407 std::size_t k1 = M.
bytes() / Nl + (M.
bytes() % Nl == 0 ? 0 : 1);
408 M1.reserve(M1.size() + k1);
411 set_type(t1, type_field::msg());
412 for (std::size_t i = 0; i != k1;
415 i + 1 == k1 ? M.
bits() - i * Nl * CHAR_BIT : Nl * CHAR_BIT;
417 internal::union_le<char>(M1.back());
428 if (M1.size() == 1) {
438 set_type(t1, type_field::msg());
439 return ubi(G, M, t0, t1);
442 std::size_t Nn = bytes() * (const_one<std::size_t>() << Yf);
443 std::size_t kl = M.
bytes() / Nn + (M.
bytes() % Nn == 0 ? 0 : 1);
444 set_level(t1, l + 1);
445 set_type(t1, type_field::msg());
446 for (std::size_t i = 0; i != kl; ++i) {
449 i + 1 == kl ? M.
bits() - i * Nn * CHAR_BIT : Nn * CHAR_BIT;
451 internal::union_le<char>(M1[i]);
455 return ubi_tree(G, Yl, Yf, Ym, l + 1, M1);
458 static void output(
const key_type &G, std::size_t N,
void *H)
460 N = N / CHAR_BIT + (N % CHAR_BIT == 0 ? 0 : 1);
461 char *C =
static_cast<char *
>(H);
465 set_type(t1, type_field::out());
466 set_flags(t1,
true,
true,
false);
469 generator.tweak(t0, t1);
473 const std::size_t n = N / bytes();
474 const std::size_t m = N % bytes();
475 if (n < std::numeric_limits<typename key_type::value_type>::max()) {
476 for (std::size_t i = 0; i != n; ++i) {
478 internal::union_le<char>(M);
479 generator(M.data(), buf.data());
480 buf.front() ^= M.front();
481 std::memcpy(C, buf.data(), bytes());
487 internal::union_le<char>(M);
488 generator(M.data(), buf.data());
489 buf.front() ^= M.front();
490 std::memcpy(C, buf.data(), m);
493 for (std::size_t i = 0; i != n; ++i) {
495 generator(M.data(), buf.data());
496 buf.front() ^= M.front();
497 for (std::size_t j = 0; j != M.size(); ++j) {
500 std::memcpy(C, buf.data(), bytes());
506 internal::union_le<char>(M);
507 generator(M.data(), buf.data());
508 for (std::size_t j = 0; j != M.size(); ++j) {
511 std::memcpy(C, buf.data(), m);
516 static void enc_block(
521 generator.tweak(t0, t1);
522 generator(M.data(), H.data());
523 for (std::size_t i = 0; i != M.size(); ++i) {
526 internal::union_le<char>(H);
529 static void set_flags(
value_type &t1,
bool first,
bool last,
bool bpad)
531 constexpr
int N = std::numeric_limits<value_type>::digits;
532 constexpr
value_type mask_first = const_one<value_type>() << (N - 2);
533 constexpr
value_type mask_last = const_one<value_type>() << (N - 1);
534 constexpr
value_type mask_bpad = const_one<value_type>() << (N - 9);
555 static void set_type(
value_type &t1,
int type)
557 constexpr
int N = std::numeric_limits<value_type>::digits;
561 t1 ^= (
static_cast<value_type>(type) << (N - 8)) & mask;
564 static void set_level(
value_type &t1,
int level)
566 constexpr
int N = std::numeric_limits<value_type>::digits;
570 t1 ^= (
static_cast<value_type>(level) << (N - 16)) & mask;
575 std::memcpy(M.data(), C, bytes());
579 static void get_block(
583 std::fill(M.begin(), M.end(), 0);
592 std::array<char, bytes()> tmp = {{0}};
593 std::size_t n = N / CHAR_BIT + (N % CHAR_BIT == 0 ? 0 : 1);
594 std::memcpy(tmp.data(), C, n);
598 int R = 7 -
static_cast<int>(N);
603 std::memcpy(M.data(), tmp.data(), bytes());
607 static std::array<std::uint64_t, 4> configure(
608 std::size_t N,
int Yl,
int Yf,
int Ym)
610 std::array<std::uint64_t, 4> C = {{0}};
611 std::get<0>(C) = 0x133414853;
612 std::get<1>(C) = static_cast<std::uint64_t>(N);
613 std::get<2>(C) += static_cast<std::uint64_t>(Yl);
614 std::get<2>(C) += static_cast<std::uint64_t>(Yf << 8);
615 std::get<2>(C) += static_cast<std::uint64_t>(Ym << 16);
637 #endif // MCKL_RANDOM_SKEIN_HPP void update(state_type &state, const param_type &M) const
typename key_type::value_type value_type
Type of the key and tweak words.
std::size_t bits() const
The length of the string in bits.
const char * data() const
The address of the string.
#define MCKL_PUSH_CLANG_WARNING(warning)
static void hash(std::size_t n, const param_type *M, std::size_t N, void *H, const param_type &K=param_type(), int Yl=0, int Yf=0, int Ym=0)
Full Skein interface.
typename Generator::key_type key_type
Type of the key.
Skein::value_type value_type
static constexpr int key()
Key (for MAC or KDF)
param_type(std::size_t N=0, const void *data=nullptr, int type=type_field::msg())
Construct a parameter given bit strings.
std::vector< T, Alloc > Vector
std::vector with Allocator as the default allocator
static constexpr int pub()
Public key (for digital signature hashing)
static constexpr int cfg()
Configuration block.
static constexpr std::size_t bits()
The number of bits of internal state.
Skein::value_type value_type
static void hash(const param_type &M, std::size_t N, void *H)
Simple hashing.
Configure type for stream hasher.
void output(const state_type &state, void *H) const
void output(state_type &state, void *H) const
static constexpr std::size_t bytes()
The number of bytes of internal state.
void update(state_type &state, const param_type &M) const
mono_hasher(std::size_t N, const param_type &K=param_type())
static constexpr int prs()
Personalization string.
Values of the type field.
std::size_t bytes() const
The length of the string in bytes.
tree_hasher(std::size_t N, const param_type &K=param_type(), int Yl=20, int Yf=20, int Ym=2)
static constexpr int kdf()
Key identifier (KDF)
void increment(std::array< T, K > &ctr, std::integral_constant< T, NSkip >)
Increment a counter by given steps.
int type() const
The type of the string.
static constexpr int out()
Output.
#define MCKL_POP_CLANG_WARNING
static constexpr int non()
Nonce (for stream cipher or randomized hashing)
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Type of input paramters such as keys and messages.
static constexpr int msg()
Message.
void runtime_assert(bool cond, const char *msg, bool soft=false)