25 #ifndef CRYPTO3_PSSR_HPP
26 #define CRYPTO3_PSSR_HPP
30 #include <nil/crypto3/utilities/bit_ops.hpp>
40 secure_vector<uint8_t>
pss_encode(HashFunction &
hash,
const secure_vector<uint8_t> &msg,
41 const secure_vector<uint8_t> &salt,
size_t output_bits) {
42 const size_t HASH_SIZE =
hash.output_length();
43 const size_t SALT_SIZE = salt.size();
45 if (msg.size() != HASH_SIZE) {
46 throw encoding_error(
"Cannot encode PSS string, input length invalid for hash");
48 if (output_bits < 8 * HASH_SIZE + 8 * SALT_SIZE + 9) {
49 throw encoding_error(
"Cannot encode PSS string, output length too small");
52 const size_t output_length = (output_bits + 7) / 8;
54 for (
size_t i = 0; i != 8; ++i) {
59 secure_vector<uint8_t> H =
hash.final();
61 secure_vector<uint8_t> EM(output_length);
63 EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01;
64 buffer_insert(EM, output_length - 1 - HASH_SIZE - SALT_SIZE, salt);
65 mgf1_mask(
hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - 1);
66 EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
67 buffer_insert(EM, output_length - 1 - HASH_SIZE, H);
68 EM[output_length - 1] = 0xBC;
73 const secure_vector<uint8_t> &message_hash,
size_t key_bits,
74 size_t *out_salt_size) {
75 const size_t HASH_SIZE =
hash.output_length();
76 const size_t KEY_BYTES = (key_bits + 7) / 8;
78 if (key_bits < 8 * HASH_SIZE + 9) {
82 if (message_hash.size() != HASH_SIZE) {
86 if (pss_repr.size() > KEY_BYTES || pss_repr.size() <= 1) {
90 if (pss_repr[pss_repr.size() - 1] != 0xBC) {
94 secure_vector<uint8_t> coded = pss_repr;
95 if (coded.size() < KEY_BYTES) {
96 secure_vector<uint8_t> temp(KEY_BYTES);
97 buffer_insert(temp, KEY_BYTES - coded.size(), coded);
101 const size_t TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits;
102 if (TOP_BITS > 8 - high_bit(coded[0])) {
106 uint8_t *DB = coded.data();
107 const size_t DB_size = coded.size() - HASH_SIZE - 1;
109 const uint8_t *H = &coded[DB_size];
110 const size_t H_size = HASH_SIZE;
113 DB[0] &= 0xFF >> TOP_BITS;
115 size_t salt_offset = 0;
116 for (
size_t j = 0; j != DB_size; ++j) {
125 if (salt_offset == 0) {
129 const size_t salt_size = DB_size - salt_offset;
131 for (
size_t j = 0; j != 8; ++j) {
134 hash.update(message_hash);
135 hash.update(&DB[salt_offset], salt_size);
137 const secure_vector<uint8_t> H2 =
hash.final();
141 if (out_salt_size && ok) {
142 *out_salt_size = salt_size;
153 template<
typename Scheme,
typename Hash>
155 template<
typename InputIterator1,
typename InputIterator2>
156 bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
157 InputIterator2 last2, std::size_t key_bits)
const {
161 if (required_salt_len &&
salt_size != m_salt_size) {
168 template<
typename SinglePassRange1,
typename SinglePassRange2>
169 bool verify(
const SinglePassRange1 &range1,
const SinglePassRange2 &range2,
170 std::size_t key_bits)
const {
171 return verify(boost::begin(range1), boost::end(range1), boost::begin(range2),
172 boost::end(range2), 0);
179 template<
typename InputMessageIterator,
typename InputSaltIterator,
typename OutputIterator>
180 OutputIterator
pss_encode(Hash &
hash, InputMessageIterator firstm, InputMessageIterator lastm,
181 InputSaltIterator firsts, InputSaltIterator lasts,
size_t output_bits) {
182 std::ptrdiff_t message_size = std::distance(firstm, lastm);
183 std::ptrdiff_t
salt_size = std::distance(firsts, lasts);
185 if (message_size != Hash::policy_type::digest_bits / 8) {
186 throw encoding_error(
"Cannot encode PSS string, input length invalid for hash");
188 if (output_bits < Hash::policy_type::digest_bits + 8 *
salt_size + 9) {
189 throw encoding_error(
"Cannot encode PSS string, output length too small");
192 const size_t output_length = (output_bits + 7) / 8;
194 for (
size_t i = 0; i != 8; ++i) {
199 secure_vector<uint8_t> H =
hash.final();
201 secure_vector<uint8_t> EM(output_length);
203 EM[output_length - Hash::policy_type::digest_bits / 8 -
salt_size - 2] = 0x01;
204 buffer_insert(EM, output_length - 1 - Hash::policy_type::digest_bits / 8 -
salt_size, salt);
205 mgf1_mask(
hash, H.data(), Hash::policy_type::digest_bits / 8, EM.data(),
206 output_length - Hash::policy_type::digest_bits / 8 - 1);
207 EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
208 buffer_insert(EM, output_length - 1 - Hash::policy_type::digest_bits / 8, H);
209 EM[output_length - 1] = 0xBC;
213 template<
typename InputIterator1,
typename InputMessageIterator>
215 const secure_vector<uint8_t> &message_hash,
size_t key_bits,
216 size_t *out_salt_size) {
217 const size_t KEY_BYTES = (key_bits + 7) / 8;
219 if (key_bits < Hash::policy_type::digest_bits + 9) {
223 if (message_hash.size() != Hash::policy_type::digest_bits / 8) {
227 if (pss_repr.size() > KEY_BYTES || pss_repr.size() <= 1) {
231 if (pss_repr[pss_repr.size() - 1] != 0xBC) {
235 secure_vector<uint8_t> coded = pss_repr;
236 if (coded.size() < KEY_BYTES) {
237 secure_vector<uint8_t> temp(KEY_BYTES);
238 buffer_insert(temp, KEY_BYTES - coded.size(), coded);
242 const size_t TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits;
243 if (TOP_BITS > 8 - high_bit(coded[0])) {
247 uint8_t *DB = coded.data();
248 const size_t DB_size = coded.size() - Hash::policy_type::digest_bits / 8 - 1;
250 const uint8_t *H = &coded[DB_size];
252 mgf1_mask(
hash, H, Hash::policy_type::digest_bits / 8, DB, DB_size);
253 DB[0] &= 0xFF >> TOP_BITS;
255 size_t salt_offset = 0;
256 for (
size_t j = 0; j != DB_size; ++j) {
265 if (salt_offset == 0) {
269 const size_t salt_size = DB_size - salt_offset;
271 for (
size_t j = 0; j != 8; ++j) {
274 hash.update(message_hash);
277 const secure_vector<uint8_t> H2 =
hash.final();
281 if (out_salt_size && ok) {
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
secure_vector< uint8_t > pss_encode(HashFunction &hash, const secure_vector< uint8_t > &msg, const secure_vector< uint8_t > &salt, size_t output_bits)
Definition: emsa_pssr.hpp:40
bool pss_verify(HashFunction &hash, const secure_vector< uint8_t > &pss_repr, const secure_vector< uint8_t > &message_hash, size_t key_bits, size_t *out_salt_size)
Definition: emsa_pssr.hpp:72
OutputIterator mgf1_mask(InputIterator first, InputIterator last, OutputIterator out, StreamHash sh=StreamHash())
MGF1 from PKCS #1 v2.0.
Definition: mgf1.hpp:48
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
PSSR aka EMSA4 in IEEE 1363.
Definition: emsa_pssr.hpp:154
bool verify(const SinglePassRange1 &range1, const SinglePassRange2 &range2, std::size_t key_bits) const
Definition: emsa_pssr.hpp:169
bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, std::size_t key_bits) const
Definition: emsa_pssr.hpp:156
OutputIterator pss_encode(Hash &hash, InputMessageIterator firstm, InputMessageIterator lastm, InputSaltIterator firsts, InputSaltIterator lasts, size_t output_bits)
Definition: emsa_pssr.hpp:180
bool pss_verify(HashFunction &hash, const secure_vector< uint8_t > &pss_repr, const secure_vector< uint8_t > &message_hash, size_t key_bits, size_t *out_salt_size)
Definition: emsa_pssr.hpp:214
std::size_t salt_size
Definition: emsa_pssr.hpp:177
std::size_t required_salt_length
Definition: emsa_pssr.hpp:176