0

I'm making some experiments with Crypto++ library, I don't understand why before that reinterpret_cast the length is 20 byte and after is only 8 chars instead of 10. Thank you very much for your attention.

P.S. I'm sorry if the question isn't well posed according to the guidelines, I'm new here. Maybe it's not very general but I hope it can be useful to others nonetheless.

#include "cryptopp/cryptlib.h"
#include "cryptopp/sha.h"
#include "cryptopp/filters.h"
#include "cryptopp/hex.h"
#include "cryptopp/files.h"
#include <cstdlib>
#include <iostream>
#include <string>
using namespace CryptoPP;
    
int main (){
    std::string msg = "Yoda said, Do or do not. There is no try.";
    std::string digest;
        
    SHA1 hash;
    hash.Update((const byte*)msg.data(), msg.size());
    digest.resize(hash.DigestSize());
    hash.Final((byte*)&digest[0]);
    
    std::cout << "Message: " << msg << std::endl;
    
    std::cout << "Digest: "<<digest<<std::endl;
    //StringSource(digest, true, new Redirector(encoder));
    //std::cout << std::endl;
    std::cout << typeid(digest).name() << std::endl;
    std::cout<<digest.size()<<std::endl;


    //this is the line......
    const unsigned char* decoded = reinterpret_cast<const unsigned char *>( digest.c_str() );   


    std::cout << "Length of array = " << (sizeof(decoded)/sizeof(*decoded)) << std::endl;
    //byte decoded[] = digest;
    std::string encoded;
    
    HexEncoder encoder;
    encoder.Put(decoded, sizeof(decoded));
    encoder.MessageEnd();
    
    //word64 size = encoder.MaxRetrievable(); 
    int size=encoder.MaxRetrievable(); std::cout<<size<<std::endl;
    if(size)
    {
        encoded.resize(size);       
        encoder.Get((byte*)&encoded[0], encoded.size());
    }
    
    std::cout << encoded << std::endl;
}

This is the output:

Message: Yoda said, Do or do not. There is no try.
Digest: -y;{:r79R
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
20
Length of array = 8
16
05C0042DF9A7793B

What I was really trying to do was just to convert the result of the hash into an hexadecimal string that I could manipulate. The example on https://www.cryptopp.com/wiki/SHA only redirects the result through a pipeline to the terminal, but I wanted to have access to the encoded string. But after making that modification, I found out the digest is many digits shorter than the original, thus my attempt to find out why.

This was the original code basically from Crypto++ Wiki:

#include "cryptopp/cryptlib.h"
#include "cryptopp/sha.h"
#include "cryptopp/filters.h"
#include "cryptopp/hex.h"
#include "cryptopp/files.h"
#include <cstdlib>
#include <iostream>
#include <string>
using namespace CryptoPP;
    
int main(){ 
    HexEncoder encoder(new FileSink(std::cout));
        
    std::string msg = "Yoda said, Do or do not. There is no try.";
    std::string digest;
        
    SHA1 hash;
    hash.Update((const byte*)msg.data(), msg.size());
    digest.resize(hash.DigestSize());
    hash.Final((byte*)&digest[0]);
        
    std::cout << "Message: " << msg << std::endl;
        
    std::cout << "Digest: ";
    StringSource(digest, true, new Redirector(encoder));
    std::cout << std::endl;
    return 0;
}

and this was the output with the right length (160 bits):

05C0042DF9A7793B7BDE3AB9724C08CF37398652
4
  • 3
    I don't think sizeof does what you think it does. Commented Apr 22, 2022 at 22:35
  • Maybe I should just split the question in two being it now about 2 quite different problems? Commented Apr 22, 2022 at 22:55
  • That's a lot of code to demonstrate "before that reinterpret_cast the length is 20 byte and after is only 8 chars instead of 10." Why do you need more than about four lines (initialize a variable, show length 20, cast, and show length 8) to demonstrate this issue? Throwing in stuff about encoding obfuscates the question, making it less useful to future readers. Commented Apr 23, 2022 at 4:11
  • Does this answer your question? How can I get the real length of char*? Different between strlen and sizeof(target)/sizeof(target*)? Commented Apr 23, 2022 at 4:17

2 Answers 2

1

Your use of sizeof() is wrong. You are taking the size of a pointer, not the size of the data being pointed at. You can't use sizeof() to calculate the size of an array from just a pointer to the array.

Since your decoded data is stored in a std::string, you need to use std::string::size() to get its size, just like you are doing everywhere else in your code, eg:

const unsigned char* decoded = reinterpret_cast<const unsigned char *>( digest.c_str() );   

std::cout << "Length of array = " << digest.size() << std::endl;
...
encoder.Put(decoded, digest.size());
...
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, so what You are saying is that the casting is right, the resizing doesn't happen there and there's no reason I should check the lenght of "decoded"? Because "decoded" doesn't support the size() method as far as I've now seen being a pointer
@encelado The cast is fine. The resize happens when you call digest.resize(). decoded is just a pointer to binary data in memory, it has no methods of its own.
actually if I increase the size in the resize() argument the lenght of the output stays the same, and can't really figure out what that means. But putting a smaller number decreses the output. That made me think that the size had already shrinked for some previous reason. Oh, I'm sorry, only now I realized it was the sizeof(decoded) in encoder.Put() that had to be changed... Thank you very much! Now it works perfectly
0

That's because sizeof returns the size of the type of the operand.
unsigned char const* is a pointer to an unsigned char (ignoring cv-qualifiers), on a 64 bit machine, that's a 64 bit pointer, 8 bytes…
Live example on Compiler Explorer

If you know the data is a NUL terminated byte string, then
you could use std::strlen(), to check the size.
In any case, you can (and probably should) use the member function std::string::size(), which will return the size of the container. eg:

std::string x;
// some API populates x.data()
const auto x_size = x.size();

3 Comments

Ok thank you very much, so that isn't the right way to measure the size of the array... I admit I just copied it from an other answer having forgotten pretty much all (the very little I knew)about arrays since I've been using vectors
You can't use strlen() on a pointer to binary data (such as an unencoded hash). The data may have embedded 0x00 bytes in it, or may not have any 0x00 bytes at all. The correct solution is to use the size() of the container that is holding the bytes, or the size reported by the original hasher.
"You can't use strlen() on a pointer to binary data (such as an unencoded hash). " I agree, in this case using std::string::length() or std::string::size() is a solution. Another would be to use the cursor of the file buffer (end - beg == byte size). I'll correct that right away, thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.