Segmentation fault error: How to access my sha256 function? - c

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.

Related

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);

Returning wrong MD5 hash in 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.

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

converting unsigned char * to jbytearray

I am trying to convert an unsigned char * to jbyteArray using the following code
int callWR(const char *name,unsigned char *ubuf)
{
jbyteArray bArray=env->NewByteArray(strlen((const char *)ubuf));
env->SetByteArrayRegion(bArray, 0, strlen((const char *)ubuf), (jbyte *)ubuf);
jstring tableName= (env)->NewStringUTF(name);
int status;
status=(int)(env)->CallStaticIntMethod(clsMC,midWRow,tableName,bArray);
env->DeleteLocalRef(bArray);
return status;
}
Is this the right method to pass a byte array argument through JNI to a java function? is type casting (jbyte *)ubuf an efficient way of converting a unsigned char * to jbyte *? The values that I am getting at the destination seem to be messed up. Help please.

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.

Resources