Is md5 input plain limited to 32 chars ?

Sep 29, 2022 at 5:53pm
Hello all,

in cannot understand why you can pass more than 32 characters into the md5 hash function. Ive seen the Implementation of mfontanini ( https://github.com/mfontanini/Programs-Scripts/blob/master/constexpr_hashes/md5.h ) and it works with plain up to 32 chars only:

1
2
3
4
5
auto hash = md5("Hello World Hello World Hello W");
cout << hex;
for (auto i : hash) {
    printf("%02x", ((int) i) & 0xff);
}


output:
 
d8216ee73893543e348fc8d3c83954f9


But then i realized that f.ex. https://md5decrypt.net/en/ can handle more than 32 chars of Plain. Pythons hashlib can also handle longer plain.
But how is that done?

Id like to understand what stuff i have to change to gain the same outcome.
Id be glad if you can provide a code example to do so.

nice greetings

Luke

Last edited on Sep 29, 2022 at 5:54pm
Sep 29, 2022 at 6:15pm
It's probably just a limitation of mfontanini's library. The MD5 algorithm can handle inputs of any length.
Last edited on Sep 29, 2022 at 6:17pm
Sep 29, 2022 at 6:23pm
Hi Peter,

thanks for your reply. Do you know some md5 implementation that can do right that?
Sep 29, 2022 at 6:28pm
No, sorry. I've used MD5 in PHP but never in C++.
Sep 29, 2022 at 7:58pm
Thanks for your help helios, your repo looks real great, but i am getting some errors here like
undefined reference to `hash::dige
st::MD5::operator std::__cxx11::basic_string<char, std::char_traits<char>, std::
allocator<char> >() const'
Last edited on Sep 29, 2022 at 8:01pm
Sep 29, 2022 at 8:33pm
The files are not self-contained. You'll have to add several CPPs to your project to get it to build.
Sep 30, 2022 at 5:52am
I see no indication that the original code (linked by OP) is limited to 32-character input.

I think LukeProducts is confusing input (which is unlimited in size) with output, which for MD5 is always 128-bit.

What you are seeing is a 16-byte output, which (when printed as hexadecimal octets) produces a 32-character string. Remember that 16 bytes × 8 bits/byte = 128 bits. (16 bytes × 2 hex digits/byte = 32 hex digits.)
Last edited on Sep 30, 2022 at 5:52am
Sep 30, 2022 at 6:46am
Duthomhas wrote:
I see no indication that the original code (linked by OP) is limited to 32-character input.

If I pass a string that is of length 32 or longer I get the following warning:

In file included from test.cpp:2:
md5.h: In instantiation of ‘static constexpr char ConstexprHashes::buffer_builder<n, 56>::make_value(const char*) [with long unsigned int n = 32]’:
md5.h:170:68:   required from ‘constexpr ConstexprHashes::buffer_type ConstexprHashes::make_buffer_helper(const char (&)[n], ConstexprHashes::index_tuple<indexes ...>) [with long unsigned int n = 33; long unsigned int ...indexes = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; ConstexprHashes::buffer_type = ConstexprHashes::constexpr_array<char, 64>]’
md5.h:177:30:   required from ‘constexpr ConstexprHashes::buffer_type ConstexprHashes::make_buffer(const char (&)[n]) [with long unsigned int n = 33; ConstexprHashes::buffer_type = ConstexprHashes::constexpr_array<char, 64>]’
md5.h:255:47:   required from ‘constexpr ConstexprHashes::md5_type ConstexprHashes::md5(const char (&)[n]) [with long unsigned int n = 33; ConstexprHashes::md5_type = std::array<char, 16>]’
test.cpp:6:68:   required from here
md5.h:148:18: warning: overflow in conversion from ‘long unsigned int’ to ‘char’ changes value from ‘256’ to ‘'\000'’ [-Woverflow]
         return n << 3;
                ~~^~~~

And the resulting MD5 hash is no longer the same as with this tool https://md5decrypt.net/en/

Earlier I thought it was a compilation error but now I see it's "just" a warning. Not sure if this is what's causing it to return the wrong hash.
Last edited on Sep 30, 2022 at 6:56am
Sep 30, 2022 at 7:44am
Hello guys,

thank you all very much for your help.
I just found a implementation that works perfectly fine:
https://bobobobo.wordpress.com/2010/10/17/md5-c-implementation/
Sep 30, 2022 at 8:44am
LukeProducts wrote:
just found a implementation that works perfectly fine

Except that it doesn't produce the right hash value if sizeof(long) != 4.

https://bobobobo.wordpress.com/2010/10/17/md5-c-implementation/#comment-6923

Changing the typedefs to
1
2
typedef std::uint16_t UINT2;
typedef std::uint32_t UINT4;
seems to fix the problem but I cannot guarantee it will always work because I haven't studied the code in detail or testing it enough.
Last edited on Sep 30, 2022 at 9:20am
Sep 30, 2022 at 10:08am
I use the MD5 from openssl.

md5.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma once

#include <openssl/md5.h>
#include <iosfwd>
#include <string.h>

struct md5_t
{
    unsigned char value[MD5_DIGEST_LENGTH];
};
inline bool operator< (const md5_t& a, const md5_t& b) { return memcmp(a.value, b.value, MD5_DIGEST_LENGTH) <  0; }
inline bool operator==(const md5_t& a, const md5_t& b) { return memcmp(a.value, b.value, MD5_DIGEST_LENGTH) == 0; }

std::ostream& operator<<(std::ostream& os, const md5_t& n);

extract ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    struct context_t {
        static constexpr size_t datasz{64 * 1024};
        unsigned char data[datasz];
    };
    context_t ctx;
//...
    md5_t md5_scan(const std::string& filename)
    {
        MD5_CTX md_context;
        MD5_Init(&md_context);

        int fd;
        if ((fd = open(filename.c_str(), O_RDONLY)) != -1) {
            int nbytes;
            while ((nbytes = read(fd, ctx.data, sizeof(ctx.data))) != 0)
                MD5_Update(&md_context, ctx.data, nbytes);
            close(fd);
        }
        else
            throw std::runtime_error{"cannot open: " + filename};

        md5_t sig;
        MD5_Final(sig.value, &md_context);
        return sig;
    }
Last edited on Sep 30, 2022 at 10:17am
Topic archived. No new replies allowed.