25 #ifndef CRYPTO3_ISO9796_HPP
26 #define CRYPTO3_ISO9796_HPP
35 template<
typename Hash>
36 secure_vector<uint8_t>
iso9796_encoding(
const secure_vector<uint8_t> &msg,
size_t output_bits,
37 size_t SALT_SIZE,
bool implicit, random_number_generator &rng) {
38 const size_t output_length = (output_bits + 7) / 8;
45 const size_t HASH_SIZE =
hash->output_length();
47 if (output_length <= HASH_SIZE + SALT_SIZE + tLength) {
48 throw encoding_error(
"ISO9796-2::encoding_of: Output length is too small");
52 const size_t capacity = output_length - HASH_SIZE - SALT_SIZE - tLength - 1;
55 secure_vector<uint8_t> msg1;
56 secure_vector<uint8_t> msg2;
57 if (msg.size() > capacity) {
58 msg1 = secure_vector<uint8_t>(msg.begin(), msg.begin() + capacity);
59 msg2 = secure_vector<uint8_t>(msg.begin() + capacity, msg.end());
67 uint64_t msgLength = msg1.size();
68 secure_vector<uint8_t> salt = rng.random_vec(SALT_SIZE);
69 hash->update_be(msgLength * 8);
73 secure_vector<uint8_t> H =
hash->final();
75 secure_vector<uint8_t> EM(output_length);
78 size_t offset = output_length - HASH_SIZE - SALT_SIZE - tLength - msgLength - 1;
82 buffer_insert(EM, offset + 1, msg1);
83 buffer_insert(EM, offset + 1 + msgLength, salt);
86 mgf1_mask(*
hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - tLength);
87 buffer_insert(EM, output_length - HASH_SIZE - tLength, H);
90 uint8_t hash_id = ieee1363_hash_id(
hash->name());
92 throw encoding_error(
"ISO9796-2::encoding_of: no hash identifier for " +
hash->name());
94 EM[output_length - 1] = 0xCC;
95 EM[output_length - 2] = hash_id;
98 EM[output_length - 1] = 0xBC;
107 size_t key_bits, std::unique_ptr<HashFunction> &
hash,
size_t SALT_SIZE) {
108 const size_t HASH_SIZE =
hash->output_length();
109 const size_t KEY_BYTES = (key_bits + 7) / 8;
111 if (const_coded.size() != KEY_BYTES) {
116 if (const_coded[const_coded.size() - 1] == 0xBC) {
119 uint8_t hash_id = ieee1363_hash_id(
hash->name());
120 if ((!const_coded[const_coded.size() - 2]) ||
121 (const_coded[const_coded.size() - 2] != hash_id) ||
122 (const_coded[const_coded.size() - 1] != 0xCC)) {
128 secure_vector<uint8_t> coded = const_coded;
130 ct::poison(coded.data(), coded.size());
132 uint8_t *DB = coded.data();
133 const size_t DB_size = coded.size() - HASH_SIZE - tLength;
135 const uint8_t *H = &coded[DB_size];
142 size_t msg1_offset = 1;
143 uint8_t waiting_for_delim = 0xFF;
144 uint8_t bad_input = 0;
145 for (
size_t j = 0; j < DB_size; ++j) {
146 const uint8_t one_m = ct::is_equal<uint8_t>(DB[j], 0x01);
148 const uint8_t add_m = waiting_for_delim & zero_m;
150 bad_input |= waiting_for_delim & ~(zero_m | one_m);
151 msg1_offset += ct::select<uint8_t>(add_m, 1, 0);
153 waiting_for_delim &= zero_m;
157 bad_input |= waiting_for_delim;
158 bad_input |= ct::is_less(coded.size(), tLength + HASH_SIZE + msg1_offset + SALT_SIZE);
161 msg1_offset = ct::select<size_t>(bad_input, 0, msg1_offset);
163 ct::unpoison(coded.data(), coded.size());
164 ct::unpoison(msg1_offset);
166 secure_vector<uint8_t> msg1(coded.begin() + msg1_offset,
167 coded.end() - tLength - HASH_SIZE - SALT_SIZE);
168 secure_vector<uint8_t> salt(coded.begin() + msg1_offset + msg1.size(),
169 coded.end() - tLength - HASH_SIZE);
172 const size_t capacity = (key_bits - 2 + 7) / 8 - HASH_SIZE - SALT_SIZE - tLength - 1;
173 secure_vector<uint8_t> msg1raw;
174 secure_vector<uint8_t> msg2;
175 if (raw.size() > capacity) {
176 msg1raw = secure_vector<uint8_t>(raw.begin(), raw.begin() + capacity);
177 msg2 = secure_vector<uint8_t>(raw.begin() + capacity, raw.end());
182 msg2 =
hash->final();
184 uint64_t msg1rawLength = msg1raw.size();
185 hash->update_be(msg1rawLength * 8);
186 hash->update(msg1raw);
189 secure_vector<uint8_t> H3 =
hash->final();
192 uint64_t msgLength = msg1.size();
193 hash->update_be(msgLength * 8);
197 secure_vector<uint8_t> H2 =
hash->final();
202 ct::unpoison(bad_input);
203 return (bad_input == 0);
208 template<
typename Scheme,
typename Hash>
211 template<
typename InputIterator,
typename OutputIterator>
212 OutputIterator
iso9796_encoding(InputIterator first, InputIterator last,
size_t output_bits,
213 size_t SALT_SIZE,
bool implicit, random_number_generator &rng) {
214 std::ptrdiff_t message_size = std::distance(first, last);
216 const size_t output_length = (output_bits + 7) / 8;
223 const size_t HASH_SIZE = this->
hash.output_length();
225 if (output_length <= HASH_SIZE + SALT_SIZE + t_length) {
226 throw encoding_error(
"ISO9796-2::encoding_of: Output length is too small");
230 const size_t capacity = output_length - HASH_SIZE - SALT_SIZE - t_length - 1;
233 secure_vector<uint8_t> msg1;
234 secure_vector<uint8_t> msg2;
235 if (message_size > capacity) {
236 msg1 = secure_vector<uint8_t>(first, first + capacity);
237 msg2 = secure_vector<uint8_t>(first + capacity, last);
240 std::copy(first, last, msg1);
242 msg2 =
hash->final();
245 uint64_t msgLength = msg1.size();
246 secure_vector<uint8_t> salt = rng.random_vec(SALT_SIZE);
247 hash->update_be(msgLength * 8);
251 secure_vector<uint8_t> H =
hash->final();
253 secure_vector<uint8_t> EM(output_length);
256 size_t offset = output_length - HASH_SIZE - SALT_SIZE - t_length - msgLength - 1;
260 buffer_insert(EM, offset + 1, msg1);
261 buffer_insert(EM, offset + 1 + msgLength, salt);
264 mgf1_mask(*
hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - t_length);
265 buffer_insert(EM, output_length - HASH_SIZE - t_length, H);
268 uint8_t hash_id = ieee1363_hash_id(
hash->name());
270 throw encoding_error(
"ISO9796-2::encoding_of: no hash identifier for " +
hash->name());
272 EM[output_length - 1] = 0xCC;
273 EM[output_length - 2] = hash_id;
276 EM[output_length - 1] = 0xBC;
284 template<
typename InputCodedIterator,
typename InputRawIterator,
typename OutputIterator>
286 InputRawIterator first_raw, InputRawIterator last_raw,
size_t key_bits,
287 std::unique_ptr<HashFunction> &
hash,
size_t SALT_SIZE) {
288 std::ptrdiff_t coded_size = std::distance(first_coded, last_coded);
289 std::ptrdiff_t raw_size = std::distance(first_raw, last_raw);
291 const size_t HASH_SIZE =
hash->output_length();
292 const size_t KEY_BYTES = (key_bits + 7) / 8;
294 if (coded_size != KEY_BYTES) {
299 if (const_coded[coded_size - 1] == 0xBC) {
302 uint8_t hash_id = ieee1363_hash_id(
hash->name());
303 if ((!const_coded[coded_size - 2]) || (const_coded[coded_size - 2] != hash_id) ||
304 (const_coded[coded_size - 1] != 0xCC)) {
310 secure_vector<uint8_t> coded = const_coded;
312 ct::poison(coded.data(), coded.size());
314 uint8_t *DB = coded.data();
315 const size_t DB_size = coded.size() - HASH_SIZE - tLength;
317 const uint8_t *H = &coded[DB_size];
324 size_t msg1_offset = 1;
325 uint8_t waiting_for_delim = 0xFF;
326 uint8_t bad_input = 0;
327 for (
size_t j = 0; j < DB_size; ++j) {
328 const uint8_t one_m = ct::is_equal<uint8_t>(DB[j], 0x01);
330 const uint8_t add_m = waiting_for_delim & zero_m;
332 bad_input |= waiting_for_delim & ~(zero_m | one_m);
333 msg1_offset += ct::select<uint8_t>(add_m, 1, 0);
335 waiting_for_delim &= zero_m;
339 bad_input |= waiting_for_delim;
340 bad_input |= ct::is_less(coded.size(), tLength + HASH_SIZE + msg1_offset + SALT_SIZE);
343 msg1_offset = ct::select<size_t>(bad_input, 0, msg1_offset);
345 ct::unpoison(coded.data(), coded.size());
346 ct::unpoison(msg1_offset);
348 secure_vector<uint8_t> msg1(coded.begin() + msg1_offset, coded.end() - tLength - HASH_SIZE - SALT_SIZE);
349 secure_vector<uint8_t> salt(coded.begin() + msg1_offset + msg1.size(),
350 coded.end() - tLength - HASH_SIZE);
353 const size_t capacity = (key_bits - 2 + 7) / 8 - HASH_SIZE - SALT_SIZE - tLength - 1;
354 secure_vector<uint8_t> msg1raw;
355 secure_vector<uint8_t> msg2;
356 if (raw_size > capacity) {
357 msg1raw = secure_vector<uint8_t>(first_raw, first_raw + capacity);
358 msg2 = secure_vector<uint8_t>(first_raw + capacity, last_raw);
361 std::copy(first_raw, last_raw, msg1raw);
363 msg2 =
hash->final();
365 uint64_t msg1rawLength = msg1raw.size();
366 hash->update_be(msg1rawLength * 8);
367 hash->update(msg1raw);
370 secure_vector<uint8_t> H3 =
hash->final();
373 uint64_t msgLength = msg1.size();
374 hash->update_be(msgLength * 8);
378 secure_vector<uint8_t> H2 =
hash->final();
383 ct::unpoison(bad_input);
384 return (bad_input == 0);
388 template<
typename Scheme,
typename Hash>
390 template<
typename InputIterator1,
typename InputIterator2>
391 bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
392 std::size_t key_bits)
const {
396 template<
typename SinglePassRange1,
typename SinglePassRange2>
397 bool verify(
const SinglePassRange1 &range1,
const SinglePassRange2 &range2, std::size_t key_bits)
const {
398 return verify(boost::begin(range1), boost::end(range1), boost::begin(range2), boost::end(range2), 0);
402 template<
typename Scheme,
typename Hash>
404 template<
typename InputIterator1,
typename InputIterator2>
405 bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
406 std::size_t key_bits)
const {
410 template<
typename SinglePassRange1,
typename SinglePassRange2>
411 bool verify(
const SinglePassRange1 &range1,
const SinglePassRange2 &range2, std::size_t key_bits)
const {
412 return verify(boost::begin(range1), boost::end(range1), boost::begin(range2), boost::end(range2), 0);
std::enable_if<!boost::accumulators::detail::is_accumulator_set< OutputIterator >::value, OutputIterator >::type hash(InputIterator first, InputIterator last, OutputIterator out)
Definition: algorithm/hash.hpp:78
bool is_zero(const Range &a)
Definition: basic_operations.hpp:43
OutputIterator mgf1_mask(InputIterator first, InputIterator last, OutputIterator out, StreamHash sh=StreamHash())
MGF1 from PKCS #1 v2.0.
Definition: mgf1.hpp:48
bool iso9796_verification(const secure_vector< uint8_t > &const_coded, const secure_vector< uint8_t > &raw, size_t key_bits, std::unique_ptr< HashFunction > &hash, size_t SALT_SIZE)
Definition: iso9796.hpp:106
secure_vector< uint8_t > iso9796_encoding(const secure_vector< uint8_t > &msg, size_t output_bits, size_t SALT_SIZE, bool implicit, random_number_generator &rng)
Definition: iso9796.hpp:36
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: memory_operations.hpp:143
EMSA, from IEEE 1363s Encoding Method for Signatures, Appendix.
Definition: emsa.hpp:48
Definition: iso9796.hpp:389
bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, std::size_t key_bits) const
Definition: iso9796.hpp:391
bool verify(const SinglePassRange1 &range1, const SinglePassRange2 &range2, std::size_t key_bits) const
Definition: iso9796.hpp:397
Definition: iso9796.hpp:403
bool verify(const SinglePassRange1 &range1, const SinglePassRange2 &range2, std::size_t key_bits) const
Definition: iso9796.hpp:411
bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, std::size_t key_bits) const
Definition: iso9796.hpp:405
Definition: iso9796.hpp:209
bool iso9796_verification(InputCodedIterator first_coded, InputCodedIterator last_coded, InputRawIterator first_raw, InputRawIterator last_raw, size_t key_bits, std::unique_ptr< HashFunction > &hash, size_t SALT_SIZE)
Definition: iso9796.hpp:285
OutputIterator iso9796_encoding(InputIterator first, InputIterator last, size_t output_bits, size_t SALT_SIZE, bool implicit, random_number_generator &rng)
Definition: iso9796.hpp:212