I am playing with openssl in C and getting some warnings I like to get rid of and am unsure how to tackle it as the examples I had found seem to do what I am emulating.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
int main(int argc, char** argv)
{
int i;
unsigned char resSHA512[SHA512_DIGEST_LENGTH];
unsigned char unhashed[1024];
printf("Input string to hash: ");
fgets(unhashed, sizeof(unhashed), stdin);
unhashed[strcspn(unhashed, "\n")] = 0;
SHA512(unhashed, strlen(unhashed), resSHA512);
printf("\nSHA512: ");
for ( i = 0; i < SHA512_DIGEST_LENGTH; i++ )
{
printf("%02x", resSHA512[i]);
}
printf("\n");
return 0;
}
I also got an alert that SHA512 has been deprecated by open when I compile on my Mac using openssl I got through it's git repository. I get no warnings in Linux unless I used the -Wall flag with gcc.
Any help is greatly appreciated, as I am trying to learn new things!
Thank you
What you're reading in to unhashed is a string, so you should declare it as an array of char. That will address the warning with the string-related functions.
That leaves you with a warning when calling SHA512 which expects an unsigned char for its first argument. In this case you can safely cast the argument to unsigned char *.
The warning you see on Mac is because the entire OpenSSL library was marked deprecated on that OS in favor of its own crypto library.
Related
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
I have installed the gcc compiler from this sudo apt-get install build-essential command
and my program code is
#include<stdio.h>
main()
{
int *b;
b = (int*)malloc(10*sizeof(int));
printf("b=%u\n\n",b);
printf("b+1=%u\n\n",(b+1));
printf("b+2=%u\n\n",(b+2));
b[2]=4;
printf("*(b+2)=%d\n\n",*(b+2));
}
when i try to compile this program from cc -c program.c command
then i get some error
You're missing #include <stdlib.h> (for malloc), and the format strings are wrong. Use %p to print pointers.
Also, you don't need to (and probably shouldn't) cast the return value of malloc (in C).
And the correct signature for main without parameters is:
int main(void)
Corrected code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *b;
b = (int*)malloc(10*sizeof(int));
printf("b=%p\n\n", (void*) b);
printf("b+1=%p\n\n",(void*) (b+1));
printf("b+2=%p\n\n",(void*) (b+2));
b[2]=4;
printf("*(b+2)=%d\n\n",*(b+2));
return 0;
}
I don't know why it worked in the video, it's probably using some strange non-standard compiler.
But your errors are because you are using int instead of unsigned int and you pass pointers to printf when it expects unsigned int.
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
Why am I getting this message? The compiler is clang. Here is a simple program where it occurs for examples sake:
#include<stdio.h>
int fib(int);
int main()
{
int i;
scanf("%d",&i);
printf("The fibonacci number that is %i'th in the sequence is %i \n", i, fib(i));
return 0;
}
int fib(int n)
{
if (n==1 || n==0) return 1;
else return fib(n-1)+fib(n-2);
}
Assuming C
<stdio.h> is one of the standard C headers. Your compiler complains that it can not find this header. This means that your standard library is broken.
Consider reinstalling your compiler.
Assuming C++
<stdio.h> is the C standard header, with C++ we use <cstdio> instead. Though <stdio.h> is still required to exist in C++, so this probably isn't the problem.
Apart from these assumptions, it seems most likely (by your coding style and tags) that you are using C. Try this as some example code. This is guaranteed (by me) to compile on a working C compiler, if it doesn't then your compiler is horribly broken and you must install another one/reinstall:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
printf("Hello World!\n");
return EXIT_SUCCESS;
}
I got a runtime error similar to this while using C++ in Visual Studio 2017. The solution in my case was to simply clean and rebuild the solution
When I compile the following code:
#define _POSIX_C_SOURCE 200112L
#define _ISOC99_SOURCE
#define __EXTENSIONS__
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
char *symlinkpath = argv[1];
char actualpath [PATH_MAX];
char *ptr;
ptr = realpath(symlinkpath, actualpath);
printf("%s\n", ptr);
}
I get a warning on the line that contains the call to the realpath function, saying:
warning: assignment makes pointer from integer without a cast
Anybody know what's up? I'm running Ubuntu Linux 9.04
This is very simple. Glibc treats realpath() as a GNU extension, not POSIX. So, add this line:
#define _GNU_SOURCE
... prior to including stdlib.h so that it is prototyped and known to to return char *. Otherwise, gcc is going to assume it returns the default type of int. The prototype in stdlib.h is not seen unless _GNU_SOURCE is defined.
The following complies fine without warnings with -Wall passed:
#include <stdio.h>
#include <limits.h>
#define _GNU_SOURCE
#include <stdlib.h>
int
main(int argc, char *argv[])
{
char *symlinkpath = argv[1];
char actualpath [PATH_MAX];
char *ptr;
ptr = realpath(symlinkpath, actualpath);
printf("%s\n", ptr);
return 0;
}
You will see similar behavior with other popular extensions such as asprintf(). Its worth a look at /usr/include/ to see exactly how much that macro turns on and what it changes.
The compiler doesn't know what realpath is, so it assumes it's a function returning int. It does this for historical reasons: a lot of older C programs relied on it doing this.
You're probably missing the declaration of it, e.g. by forgetting to #include its header file.