Is md5 input plain limited to 32 chars ?

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
It's probably just a limitation of mfontanini's library. The MD5 algorithm can handle inputs of any length.
Last edited on
Hi Peter,

thanks for your reply. Do you know some md5 implementation that can do right that?
No, sorry. I've used MD5 in PHP but never in C++.
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
The files are not self-contained. You'll have to add several CPPs to your project to get it to build.
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
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
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/
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
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
Topic archived. No new replies allowed.