bvector: use faster to/from string/byte conversion
This commit is contained in:
parent
bbca109f8b
commit
a7ffdbdee0
|
@ -519,7 +519,7 @@ int action_decrypt (bool armor, const std::string&symmetric,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!plaintext.to_string (data)) {
|
||||
if (!plaintext.to_string_check (data)) {
|
||||
err ("error: malformed data");
|
||||
return 1;
|
||||
}
|
||||
|
@ -862,7 +862,8 @@ int action_verify (bool armor, const std::string&detach,
|
|||
sencode_destroy (M);
|
||||
|
||||
std::string tmp;
|
||||
if (!msg.message.to_string (tmp) || tmp != MSG_CLEARTEXT) {
|
||||
if (!msg.message.to_string_check (tmp)
|
||||
|| tmp != MSG_CLEARTEXT) {
|
||||
err ("error: malformed cleartext signature");
|
||||
return 1;
|
||||
}
|
||||
|
@ -913,7 +914,8 @@ int action_verify (bool armor, const std::string&detach,
|
|||
sencode_destroy (M);
|
||||
|
||||
std::string tmp;
|
||||
if (!msg.message.to_string (tmp) || tmp != MSG_DETACHED) {
|
||||
if (!msg.message.to_string_check (tmp)
|
||||
|| tmp != MSG_DETACHED) {
|
||||
err ("error: malformed detached signature");
|
||||
return 1;
|
||||
}
|
||||
|
@ -1210,7 +1212,7 @@ int action_decrypt_verify (bool armor, bool yes,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!bv.to_string (data)) {
|
||||
if (!bv.to_string_check (data)) {
|
||||
err ("error: malformed data");
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -133,20 +133,15 @@ static void msg_pad_length (const std::vector<byte>& msg,
|
|||
static void message_pad (const bvector&in, std::vector<byte>&out,
|
||||
prng&rng, hash_func&pad_hash)
|
||||
{
|
||||
out.clear();
|
||||
in.to_bytes (out);
|
||||
|
||||
//make space for the bit stage
|
||||
if (in.size() == 0) out.resize (1, 0);
|
||||
else out.resize ( ( (in.size() - 1) >> 3) + 2, 0);
|
||||
|
||||
//copy message bits
|
||||
uint i;
|
||||
for (i = 0; i < in.size(); ++i)
|
||||
if (in[i]) out[i >> 3] |= 1 << (i & 0x7);
|
||||
out.resize (out.size() + 1, 0);
|
||||
|
||||
//pad with random bits to whole byte
|
||||
unsigned char rtmp = rng.random (256);
|
||||
for (; i & 0x7; ++i)
|
||||
uint i;
|
||||
for (i = in.size(); i & 0x7; ++i)
|
||||
if (rtmp >> (i & 0x7))
|
||||
out[i >> 3] |= 1 << (i & 0x7);
|
||||
|
||||
|
@ -214,10 +209,7 @@ static bool message_unpad (std::vector<byte> in, bvector&out,
|
|||
//convert to bvector
|
||||
uint msg_size = ( (in_end - (bit_overflow ? 2 : 1)) << 3)
|
||||
+ bit_overflow;
|
||||
out.clear();
|
||||
out.resize (msg_size);
|
||||
for (uint i = 0; i < msg_size; ++i)
|
||||
out[i] = 1 & (in[i >> 3] >> (i & 0x7));
|
||||
out.from_bytes (in, msg_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -275,7 +267,7 @@ static int fo_encrypt (const bvector&plain, bvector&cipher,
|
|||
hash_type hf;
|
||||
H = hf (M2);
|
||||
|
||||
//prepare the error vector
|
||||
//prepare the error vector (rotate the hash so we don't need ultralong hash functions)
|
||||
bvector ev_rank;
|
||||
ev_rank.resize (ranksize);
|
||||
for (i = 0; i < ranksize; ++i)
|
||||
|
@ -286,8 +278,8 @@ static int fo_encrypt (const bvector&plain, bvector&cipher,
|
|||
|
||||
//prepare plaintext
|
||||
bvector mce_plain;
|
||||
mce_plain.resize (plainsize);
|
||||
for (i = 0; i < plainsize; ++i) mce_plain[i] = 1 & (K[i >> 3] >> (i & 0x7));
|
||||
mce_plain.from_bytes (K);
|
||||
mce_plain.resize (plainsize, 0); //pad with 0's to exact size
|
||||
|
||||
//run McEliece
|
||||
if (Pub.encrypt (mce_plain, cipher, ev)) return 5;
|
||||
|
@ -301,11 +293,10 @@ static int fo_encrypt (const bvector&plain, bvector&cipher,
|
|||
//encrypt
|
||||
for (i = 0; i < M.size(); ++i) M[i] = M[i] ^ sc.gen();
|
||||
|
||||
//append the message part to the ciphertext
|
||||
cipher.resize (ciphersize + (M.size() << 3));
|
||||
for (i = 0; i < (M.size() << 3); ++i)
|
||||
cipher[ciphersize + i] = 1 & (M[i >> 3] >> (i & 0x7));
|
||||
|
||||
//append the message part to the key block.
|
||||
bvector Mb;
|
||||
Mb.from_bytes (M);
|
||||
cipher.append (Mb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -375,13 +366,14 @@ static int fo_decrypt (const bvector&cipher, bvector&plain,
|
|||
|
||||
//convert stuff to byte vectors
|
||||
std::vector<byte> K, M;
|
||||
K.resize (plainsize >> 3, 0);
|
||||
for (i = 0; i < plainsize; ++i)
|
||||
if (mce_plain[i]) K[i >> 3] |= 1 << (i & 0x7);
|
||||
|
||||
M.resize (msize >> 3, 0);
|
||||
for (i = 0; i < msize; ++i)
|
||||
if (cipher[ciphersize + i]) M[i >> 3] |= 1 << (i & 0x7);
|
||||
bvector Kb;
|
||||
mce_plain.get_block (0, plainsize, Kb);
|
||||
Kb.to_bytes (K);
|
||||
|
||||
bvector Mb;
|
||||
cipher.get_block (ciphersize, msize, Mb);
|
||||
Mb.to_bytes (M);
|
||||
|
||||
//prepare symmetric cipher
|
||||
scipher sc;
|
||||
|
@ -403,7 +395,7 @@ static int fo_decrypt (const bvector&cipher, bvector&plain,
|
|||
bvector ev_rank;
|
||||
ev.colex_rank (ev_rank);
|
||||
ev_rank.resize (ranksize, 0);
|
||||
for (i = 0; i < ranksize; ++i)
|
||||
for (i = 0; i < ranksize; ++i) //cyclic hash repetition again
|
||||
if (ev_rank[i] != (1 & (H[ (i >> 3) % H.size()]
|
||||
>> (i & 0x7))))
|
||||
return 7;
|
||||
|
|
|
@ -57,16 +57,12 @@
|
|||
|
||||
typedef chacha20 padding_generator;
|
||||
|
||||
static void msg_pad (const bvector&in, std::vector<byte>&out, size_t minsize)
|
||||
static void msg_pad (const bvector&in, std::vector<byte>&out, size_t tgt_size)
|
||||
{
|
||||
uint i;
|
||||
|
||||
out.clear();
|
||||
out.resize ( ( (in.size() - 1) >> 3) + 1, 0);
|
||||
for (i = 0; i < in.size(); ++i)
|
||||
if (in[i]) out[i >> 3] |= 1 << (i & 0x7);
|
||||
|
||||
if (out.size() >= minsize) return;
|
||||
in.to_bytes (out);
|
||||
if (out.size() >= tgt_size) return;
|
||||
|
||||
padding_generator g;
|
||||
g.init ();
|
||||
|
@ -74,8 +70,8 @@ static void msg_pad (const bvector&in, std::vector<byte>&out, size_t minsize)
|
|||
g.load_key_vector (out);
|
||||
|
||||
i = out.size();
|
||||
out.resize (minsize);
|
||||
for (; i < minsize; ++i) out[i] = g.gen();
|
||||
out.resize (tgt_size);
|
||||
for (; i < tgt_size; ++i) out[i] = g.gen();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -106,8 +102,7 @@ static int fmtseq_generic_sign (const bvector&msg,
|
|||
|
||||
//convert to bvector
|
||||
bvector hash;
|
||||
hash.resize (hs, 0);
|
||||
for (uint i = 0; i < hs; ++i) hash[i] = 1 & (H[i >> 3] >> (i & 0x7));
|
||||
hash.from_bytes (H);
|
||||
|
||||
//make a signature
|
||||
tree_hash hf;
|
||||
|
@ -145,8 +140,7 @@ static int fmtseq_generic_verify (const bvector&sig,
|
|||
|
||||
//convert to bvector
|
||||
bvector hash;
|
||||
hash.resize (hs, 0);
|
||||
for (uint i = 0; i < hs; ++i) hash[i] = 1 & (H[i >> 3] >> (i & 0x7));
|
||||
hash.from_bytes (H);
|
||||
|
||||
//check the signature
|
||||
tree_hash hf;
|
||||
|
|
|
@ -199,6 +199,7 @@ void bvector::get_block (size_t offset, size_t bs, bvector&out) const
|
|||
|
||||
uint bvector::and_hamming_weight (const bvector&a) const
|
||||
{
|
||||
/* sizes must match */
|
||||
uint r = 0;
|
||||
size_t s = _data.size();
|
||||
if (s > a._data.size()) s = a._data.size();
|
||||
|
@ -222,26 +223,48 @@ void bvector::from_poly_cotrace (const polynomial&r, gf2m&fld)
|
|||
item (i) = (r[i % s] >> (i / s)) & 1;
|
||||
}
|
||||
|
||||
bool bvector::to_string (std::string& out) const
|
||||
void bvector::to_bytes (std::vector<byte>& out) const
|
||||
{
|
||||
if (size() & 0x7) return false;
|
||||
out.resize ( (size() + 7) >> 3, 0);
|
||||
|
||||
out.clear();
|
||||
out.resize (size() >> 3, 0);
|
||||
|
||||
for (size_t i = 0; i < size(); ++i)
|
||||
if (item (i)) out[i >> 3] |= (1 << (i & 0x7));
|
||||
|
||||
return true;
|
||||
for (size_t i = 0; i < size(); i += 8)
|
||||
out[i >> 3] = (_data[i >> 6]
|
||||
>> ( ( (i >> 3) & 7) << 3)) & 0xff;
|
||||
}
|
||||
|
||||
void bvector::from_string (const std::string&in)
|
||||
void bvector::to_string (std::string& out) const
|
||||
{
|
||||
clear();
|
||||
resize (in.length() << 3);
|
||||
out.resize ( (size() + 7) >> 3, '\0');
|
||||
|
||||
for (size_t i = 0; i < size(); ++i)
|
||||
item (i) = (in[i >> 3] >> (i & 0x7)) & 1;
|
||||
for (size_t i = 0; i < size(); i += 8)
|
||||
out[i >> 3] = (_data[i >> 6]
|
||||
>> ( ( (i >> 3) & 7) << 3)) & 0xff;
|
||||
}
|
||||
|
||||
void bvector::from_string (const std::string&in, size_t bits)
|
||||
{
|
||||
if (bits) resize (bits);
|
||||
else resize (in.length() << 3);
|
||||
fill_zeros();
|
||||
|
||||
for (size_t i = 0; i < size(); i += 8)
|
||||
_data[i >> 6] |=
|
||||
( (uint64_t) (unsigned char) in[i >> 3])
|
||||
<< ( ( (i >> 3) & 7) << 3);
|
||||
fix_padding();
|
||||
}
|
||||
|
||||
void bvector::from_bytes (const std::vector<byte>&in, size_t bits)
|
||||
{
|
||||
if (bits) resize (bits);
|
||||
else resize (in.size() << 3);
|
||||
fill_zeros();
|
||||
|
||||
for (size_t i = 0; i < size(); i += 8)
|
||||
_data[i >> 6] |=
|
||||
( (uint64_t) (unsigned char) in[i >> 3])
|
||||
<< ( ( (i >> 3) & 7) << 3);
|
||||
fix_padding();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -197,8 +197,17 @@ public:
|
|||
void colex_rank (bvector&) const;
|
||||
bool colex_unrank (bvector&, uint n, uint k) const;
|
||||
|
||||
bool to_string (std::string&) const;
|
||||
void from_string (const std::string&);
|
||||
void to_string (std::string&) const;
|
||||
void to_bytes (std::vector<byte>&) const;
|
||||
|
||||
bool to_string_check (std::string&s) const {
|
||||
if (size() & 7) return false;
|
||||
to_string (s);
|
||||
return true;
|
||||
}
|
||||
|
||||
void from_string (const std::string&, size_t bits = 0);
|
||||
void from_bytes (const std::vector<byte>&, size_t bits = 0);
|
||||
|
||||
sencode* serialize();
|
||||
bool unserialize (sencode*);
|
||||
|
|
|
@ -62,14 +62,10 @@ static bool unserialize_uint_vector (std::vector<uint>*v, sencode*s)
|
|||
|
||||
sencode* bvector::serialize()
|
||||
{
|
||||
uint ss = (size() + 7) / 8;
|
||||
std::string bytes;
|
||||
bytes.resize (ss, '\0');
|
||||
//the padding of each vector is zero, we can stuff the bytes right in. Just make it sure here:
|
||||
fix_padding();
|
||||
|
||||
for (size_t i = 0; i < size(); i += 8)
|
||||
bytes[i >> 3] = (_data[i >> 6] >> ( ( (i >> 3) & 7) << 3)) & 0xff;
|
||||
to_string (bytes);
|
||||
|
||||
sencode_list*l = new sencode_list;
|
||||
l->items.push_back (new sencode_int (size()));
|
||||
|
@ -85,19 +81,17 @@ bool bvector::unserialize (sencode* s)
|
|||
sencode_int*CAST_INT (l->items[0], size);
|
||||
sencode_bytes*CAST_BYTES (l->items[1], bytes);
|
||||
if (bytes->b.size() != ( (size->i + 7) / 8)) return false;
|
||||
clear();
|
||||
resize (size->i, 0);
|
||||
for (i = 0; i < _size; i += 8)
|
||||
_data[i >> 6] |= ( (uint64_t) (unsigned char) bytes->b[i >> 3]) << ( ( (i >> 3) & 7) << 3);
|
||||
|
||||
/*
|
||||
* the important part. verify that padding is always zero, because
|
||||
* sencode serialization must be bijective
|
||||
*/
|
||||
for (i = _size; i < 8 * bytes->b.size(); ++i)
|
||||
for (i = size->i; i < 8 * bytes->b.size(); ++i)
|
||||
if ( (bytes->b[i / 8] >> (i % 8)) & 1)
|
||||
return false;
|
||||
|
||||
from_string (bytes->b, size->i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue