-2

I'm making program in C++ that works with vector<uint8_t> and uses Crypto++ library. I separate my vector to small ones and trying to convert it to Integer, but sometimes small vector block contains of zeros at the begining, so when i convert back from Integer to vector<uint8_t>, this vector does not contain this zeros. Here is the code:

void Test(vector<uint8_t> data)
{
    vector<uint8_t> cipher;
    size_t blockSize = _keySize / 8;
    for (size_t i = 0; i < data.size(); i += blockSize)
    {
        size_t blockLength = min(blockSize, data.size() - i);
        vector<uint8_t> block(data.begin() + i, data.begin() + i + blockLength);
        Integer m;
        m.Decode(block.data(), block.size());
        size_t Size = m.MinEncodedSize();
        vector<uint8_t> encrypt(Size);
        m.Encode(encrypt.data(), encrypt.size());
        if (encrypt != block)
        {
            cout << i << " " << unsigned(block[0]) << endl;
        }
    }
}

In this code _keySize is 1024, and data contains 140000 elements. Here is the output:

11264 0
17280 0
29952 0
53632 0
57728 0
63104 0
75392 0
137216 0
138880 0

I was trying to use OpenSSL library, but has same mistake.

  • What does _"trying to convert it to Integer"_ mean? – Ted Lyngmo May 25 '23 at 15:06
  • `Integer` is a type from the library (I'm not familiar with)? What I *do* see is that you needlessly produce copies of data all the time, though; first time on accepting the vector by value (you might prefer a `const` reference instead), then again by creating the `block` vectors – you could use the data from the input vector directly by `m.decode(data.data() + i, blockLength)` (unless `Integer` would modify the data, then you'd need at least one copy, but I don't assume so...). – Aconcagua May 25 '23 at 15:09
  • Side note: About [`using namespace std`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice)... – Aconcagua May 25 '23 at 15:10
  • `Integer` has a smell to me, sounds like some kind of big-integer library, be it independent or part of the crypto library – if producing a string representation from some internal value, why should it want to print leading zeros? Might be comparable to `int n; std::cin >> n; /* getting 0001 */ std::cout << n; /* just printing 1 unless some stream modifier provided*/`; you might need to tell the `Integer` how many bytes you want to have minimally, if that's available. – Aconcagua May 25 '23 at 15:18
  • Yes, Integer is a type from library to work with big numbers. This is just a test function to test conversion to Integer and reverse, so I produce copies of data, but the problem is not here (I think so). Integer modifies data, so when I reverse Integer back to vector, I lost zeros at the beginning. – Bloc8855 May 25 '23 at 15:20
  • *'Integer modifies data'* – are you sure? It might just *read* the input given to `decode` and construct some internal representation from that pretty likely is not based on smallest integer possible, but rather on largest directly supported by CPU... It's rather easy to veryify: What is the signature? Is it `decode(uint8_t` **`const`** `* data)` or without const? – Aconcagua May 25 '23 at 15:38

1 Answers1

0

This answer is based on assumptions as I'm not familiar with Crypto++ library; still it is plausible at least:

Integer sounds pretty much like an arbitrary size integer type as known from other big-integer libraries.

I'm drawing now a parallel to standard input/output streams:

On Decodeing data the string is read and some internal representation constructed from. It's pretty likely that this one is not based on the smallest possible integer type (signed or unsigned char), but rather on the largest one the underlying CPU supports natively (i.e. the one corresponding to the latter's register size).

This corresponds to reading some value from console into a variable:

int n;
std::cin >> n;

You can now pass in 1, 01, or any arbitrary number of leading zeros (well, not accounting for the fact that a leading zero switches by default to octal number format...). When you now output the variable again:

std::cout << n;

you simply get 1 as output, all the leading zeros dropped.

Analogously: Why should some big-integer type produce leading zeros on creating a string representation of its internal value?

At least it won't by default if you don't tell it. Provided this is possible at all then do so, check the API for if such function exists and how it is called. This would correspond to:

std::cout << std::setfill('0') << std::setw(4) << n;

to get 0001 printed.

If you discover no such API exists then you need to do by hand; start as following:

size_t size = m.MinEncodedSize();
if(size > blockLength)
{
    // well, NOW you really are in trouble!
    // TODO: some appropriate error handling
}
else
{
    vector<uint8_t> encrypt(blockLength, '0');
    // (note: NOT size; and initialize to '0', not 0!

    m.Encode(encrypt.data() + blockLength - size, size);
}

If my assumptions are correct you should now get the desired results.

Aconcagua
  • 24,880
  • 4
  • 34
  • 59