Returning wrong MD5 hash in C - c

I am trying to generate MD5 hash for an string "Hello World" using the original/untouched md5.h and md5c.c from http://www.arp.harvard.edu. But my result differs from all md5 online tools i have tested. Whats wrong this this code? Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "md5.h"
void MD5hash(unsigned char *data, unsigned int dataLen, unsigned char *digest) {
MD5_CTX c;
MD5Init(&c);
MD5Update(&c, data, dataLen);
MD5Final(digest, &c);
}
int main(int argc, const char * argv[]) {
unsigned char digest[16];
const char *s = "Hello World";
unsigned int l = (unsigned int)strlen(s);
MD5hash((unsigned char *)s, l, digest);
for(int i = 0; i < 16; ++i)
printf("%02x", digest[i]);
return 0;
}
// My result: f2877a72c40494318c4b050bb436c582
// But online tools output: b10a8db164e0754105b7a99be72e3fe5

As #vipw mentioned there is an issue with padding. This MD5 implementation does not correctly manage padding for message sizes that are not a multiple of a MD5 block size (512-bit / 64 bytes).
To fix it on your side, replace:
const char *s = "Hello World";
by
const char s[64] = "Hello World";
EDIT:
There was a second issue related to portability in this MD5 implementation. In md5.h there is this type alias:
typedef unsigned long int UINT4;
On a Linux x86_64 system (which you are using), this must be changed to this:
typedef unsigned int UINT4;

You have an issue with padding. The MD5 Hash algorithm works on 512-bit blocks. When your final block is less than 512 bits, it needs to be padded. In your example, the first block is also the last block because it's less than 512 bits.
The padding is format is called Merkle–Damgård construction.
You can find some pseudo code that includes padding here.

Related

Segmentation fault error: How to access my sha256 function?

I want to get the hash value by putting the message value in the sha256 function. But I get a segmentation fault error.
This is my main function.
int main() {
unsigned char *digest;
unsigned char *message = "fsd";
unsigned int len=3;
sha256(message, len, digest);
printf("%s",digest); }
Below is sha256 function.
void sha256(const unsigned char *message, unsigned int len,
unsigned char *digest);
How should I access the function so that it doesn't throw an error?
digest needs to point somewhere. In your code digest is just an uninitialized poibter that points nowhere.
int main() {
unsigned char digest[some_length]; // the digest will be put here
unsigned char *message = "fsd";
unsigned int len=3;
sha256(message, len, digest);
printf("%s",digest);
}
where some_length is the length needed for the SHA256 digest, refer to the documentation of the sha256 function.
Also depending on what exactly sha256 does (you didn0't provide the code nor any documentation), printf("%s",digest); won't work because digest might contain unprintable characters.

Is there a standard way to generate a salt for crypt syscall?

I need to implement account management for my application, and I would rather not use chpasswd subprocess, or otherwise let the plaintext password out my my application's memory space.
I want to use putspent with a password hash I generate with crypt, but I can't find any standard function to randomize a salt for crypt. An online search only found weird hashing function implementations I'd rather not copy into my code. Is there a standard function that would generate a salt for me?
Otherwise, would it be wise to just re-use the current salt stored in my shadow file? I couldn't think of why it WOULD be a security hazard (it will not weaken my shadow file against a rainbow table attack), it just feels wrong because in systems security a rule of thumb is to always randomize everything... (Users are added with system utilities)
It depends on your libc version. In newer Versions there is crypt_gensalt which should be what you need. Use the *_rn versions to be thread-safe.
Example:
#include <crypt.h>
#include <stddef.h>
#include <stdio.h>
int main() {
char result[CRYPT_GENSALT_OUTPUT_SIZE];
const char* salt = crypt_gensalt_rn("$6$", 0, NULL, 0, result, sizeof(result));
if(salt == NULL)
return -1;
printf("salt: %s\n", salt);
struct crypt_data state_data = {0};
const char* hash = crypt_rn("password", salt, &state_data, sizeof(state_data));
printf("hash: %s\n", hash);
}
OpenSSL provides functions for sha512:
https://www.openssl.org/docs/man1.0.2/crypto/SHA512.html
int SHA256_Init(SHA256_CTX *c);
int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
int SHA256_Final(unsigned char *md, SHA256_CTX *c);
unsigned char *SHA256(const unsigned char *d, size_t n,
unsigned char *md);
For generating a salt for crypt(), you need 2 random bytes.
For this, you can use openssl:
#include <openssl/rand.h>
int RAND_bytes(unsigned char *buf, int num);
int RAND_pseudo_bytes(unsigned char *buf, int num);
Ref: https://www.openssl.org/docs/man1.0.2/crypto/RAND_bytes.html
Example:
unsigned char salt[2];
RAND_pseudo_bytes(salt, 2);
char *ptr = crypt(password, salt);

SHA1 error implementation in C

I have been working on getting the sha1() function working from openssl/sha.h however I am getting random output and some warning. I have read quite a bit and tried some of the example codes but I get warning on all of it and it doesn't display correctly.
Here is code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <openssl/sha.h>
int main()
{
const unsigned char data[] = "Hello, World";
unsigned long length = sizeof(data);
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
printf("%02x \n", hash);
return 0;
}
Below is the warning I am getting:
sha.c: In function ‘main’:
sha.c:12: warning: ‘SHA1’ is deprecated (declared at /usr/include/openssl/sha.h:124)
sha.c:13: warning: format ‘%02x’ expects type ‘unsigned int’, but argument 2 has type ‘unsigned char *’
sha.c:13: warning: format ‘%02x’ expects type ‘unsigned int’, but argument 2 has type ‘unsigned char *’
When I run it and I get the output:
62652b34
Any help would be great!
It also took me a while before I figured it all out. The best way is to use EVP, it provides generic functions for almost everything.
#include <openssl/evp.h>
You need to call this im main before calling you hash function. To initialize your hashes. Otherwise openssl will complain that the algorithm is not available.
OpenSSL_add_all_algorithms();
mode must be "SHA256", "SHA512", "SHA1" as string.
dataToHash is the input, dataSize is the size of the input,
outHashed should already be allocated, the hash will be written there
unsigned int hash(const char *mode, const char* dataToHash, size_t dataSize, unsigned char* outHashed) {
unsigned int md_len = -1;
const EVP_MD *md = EVP_get_digestbyname(mode);
if(NULL != md) {
EVP_MD_CTX mdctx;
EVP_MD_CTX_init(&mdctx);
EVP_DigestInit_ex(&mdctx, md, NULL);
EVP_DigestUpdate(&mdctx, dataToHash, dataSize);
EVP_DigestFinal_ex(&mdctx, outHashed, &md_len);
EVP_MD_CTX_cleanup(&mdctx);
}
return md_len;
}
A use example (this is not tested, I use the above code in a c++ wrapper)
const char *inData = "test data2";
unsigned char outHash[20]; // output is already allocated
hash("SHA1", inData, 10, outHash);
You shouldn't use the SHA1 method directly it is deprecated (your code could blow up with the next version).
If you want to use your version you need to print each char as hex:
int i;
for(i=0; i<SHA_DIGEST_LENGTH; i++) {
printf("%02x", hash[i]);
}
You can't dump the entire buffer that way. you need to loop it, such as below. The value you're getting for your output is actually the address of the hash buffer, which is clearly not what you're looking for. You want the hex-bytes in the buffer dumped as text
So...
int main()
{
const unsigned char data[] = "Hello, World";
unsigned long length = sizeof(data);
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
int i=0;
for (;i< sizeof(hash)/sizeof(hash[0]);++i)
printf("%02x \n", hash[i]);
return 0;
}
Regarding your warnings, the deprecation is because this interface is out-dated for performing the crypto-op you're attempting (SHA1). There are newer interfaces in OpenSSL that are current. Consider the EVP interface specifically.
printf("%02u \n", hash);
Remove warnings by printing unsigned char

Microchip C18 - Weird code behavior (maybe extended-mode / non-extended-mode related)

I have this weird problem with the Microchip C18 compiler for PIC18F67J60.
I have created a very simple function that should return the index of a Sub-String in a larger String.
I don't know whats wrong, but the behavior seems to be related to wether extended mode is enabled or not.
With Extended-Mode enabled in MPLAB.X I get:
The memcmppgm2ram function returns zero all the time.
With Extended-Mode disabled in MPLAB.X I get:
The value of iterator variable i counts as: 0, 1, 3, 7, 15, 21
I'm thinking some stack issue or something, because this is really weird.
The complete code is shown below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char bigString[] = "this is a big string";
unsigned char findSubStr(char *str, const rom char *subStr, unsigned char n, unsigned char m)
{
unsigned char i;
for (i=0; i < n-m; i++)
{
if(0 == memcmppgm2ram(&str[i], (const far rom void*)subStr, m))
return i;
}
return n; // not found
}
void main(void)
{
char n;
n = findSubStr(bigString, (const rom void*)"big", sizeof(bigString), 3);
}
memcmppgm2ram() expects a pointer to data memory (ram) as its first argument. You are passing a pointer to a string literal, which is located in program memory (rom).
You can use memcmppgm() instead, or copy the other string to ram using memcpypgm2ram() or strcpypgm2ram().
Unfortunately I can't test this, as I don't have access to this compiler at the moment.

How can I use openssl/md5 in C++ to hash a string?

I need to hash with md5 algorithm a string in my program.
There is the lib openssl but I'm a newbie about it.
How is possible hash a string using that and where I can find a good doc that teach me how to use this lib, also with other function like aes?
I've tried this code:
int main()
{
unsigned char result[MD5_DIGEST_LENGTH];
const unsigned char* str;
str = (unsigned char*)"hello";
unsigned int long_size = 100;
MD5(str,long_size,result);
}
But the compiler told me:
undefined reference to MD5.
Why is there and undefined reference to MD5?
You should take a look at the documentation. An option is to use this function:
#include <openssl/md5.h>
unsigned char *MD5(const unsigned char *d,
unsigned long n,
unsigned char *md);
To which they state:
MD2(), MD4(), and MD5() compute the MD2, MD4, and MD5 message digest of the n bytes at d and place it in md (which must have space for MD2_DIGEST_LENGTH == MD4_DIGEST_LENGTH == MD5_DIGEST_LENGTH == 16 bytes of output). If md is NULL, the digest is placed in a static array.
As for AES, if you also want to use OpenSSL, then take a look at EVP doc and this example of how to use it. Just note that you have to add
#define AES_BLOCK_SIZE 16
In the top of the file for it to work, though.
Btw. I can really recommend the Crypto++ library since it's great and has all kinds of cryptographic primitives; AES, Elliptic Curves, MAC, public-key crypto and so on.
The MD5 function is now deprecated, so if you want to avoid all those nasty warnings in your code...
Here's a simple example of how to use md5 with OpenSSL 3.0 and above with C++:
#include <openssl/evp.h>
#include <cstdio>
using namespace std;
string md5(const string& content)
{
EVP_MD_CTX* context = EVP_MD_CTX_new();
const EVP_MD* md = EVP_md5();
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
string output;
EVP_DigestInit_ex2(context, md, NULL);
EVP_DigestUpdate(context, content.c_str(), content.length());
EVP_DigestFinal_ex(context, md_value, &md_len);
EVP_MD_CTX_free(context);
output.resize(md_len * 2);
for (unsigned int i = 0 ; i < md_len ; ++i)
std::sprintf(&output[i * 2], "%02x", md_value[i]);
return output;
}
According to: https://www.openssl.org/docs/man3.0/man3/EVP_DigestInit_ex.html

Resources