转自:http://linux.die.net/man/3/evp_sha512
代码如下:
// mdtest.cpp #include <stdio.h> #include <string.h> #include <openssl/evp.h> int main(int argc, char* argv[]) { EVP_MD_CTX mdctx; const EVP_MD *md; char mess1[] = "Test Message\n"; char mess2[] = "Hello World\n"; unsigned char md_value[EVP_MAX_MD_SIZE]; unsigned int md_len; int i; OpenSSL_add_all_digests(); if(!argv[1]) { printf("Usage: mdtest digestname\n"); exit(1); } md = EVP_get_digestbyname(argv[1]); if(!md) { printf("Unknown message digest %s\n", argv[1]); exit(1); } EVP_MD_CTX_init(&mdctx); EVP_DigestInit_ex(&mdctx, md, NULL); EVP_DigestUpdate(&mdctx, mess1, strlen(mess1)); EVP_DigestUpdate(&mdctx, mess2, strlen(mess2)); EVP_DigestFinal_ex(&mdctx, md_value, &md_len); EVP_MD_CTX_cleanup(&mdctx); printf("Digest is: "); for(i = 0; i < md_len; i++) printf("%02x", md_value[i]); printf("\n"); return 0; }
g++ -o mdtest mdtest.cpp -I/yasi/code/openssl-1.0.1c/include -lssl -lcrypto -L/usr/lib64
运行及结果:
./mdtest sha1 Digest is: 0541d4e2b052e6ed4bb7e294a1884c2cfbbf30d8 ./mdtest sha224 Digest is: 1398d1428f5449ddad27d18c78d06ca1831937d2e342dafc76b693be ./mdtest sha256 Digest is: 318b20b83a6730b928c46163a2a1cefee4466132731c95c39613acb547ccb715 ./mdtest sha384 Digest is: 22511d0e8dfafe6ea698635d2e549056f8d48eba210a2b7040a3d89830660b1c1f5d38e218e86d036e489b1121b1bfc1 ./mdtest sha512 Digest is: bcc37e0208be19c45906c47bbf09dc07c7b9e8614759dd3f85ebe39c1b1e1fcd6d804e36ee0be3cf3d3b57d9f28845de522b641937bbadaf98becacdb0572498
代码中的 EVP_MAX_MD_SIZE 的值应该是64,因为SHA512编码后长度是64字节。但事实上,有时会发现这个宏的值在Openssl中定义为36,这时需要自己重新定义它为64:
#define EVP_MAX_MD_SIZE 64 /* SHA512 */
EVP_DigestFinal_ex(&mdctx, md_value, &md_len) 的 md_len 参数是output参数,“EVP_DigestFinal_ex 往 md_value 中写入了多少字节的内容”,这个信息(写入信息长度)将被写入 md_len。
独立的代码:
下面的代码可以直接拿来用
algo_hash.h
#ifndef _ALGO_HASH_H_ #define _ALGO_HASH_H_ void HashInit(); int HashEncode(const char * algo, const char * input, unsigned int input_length, char * &output, unsigned int &output_length); #endif
#include "algo_hash.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include <openssl/evp.h> void HashInit() { OpenSSL_add_all_digests(); } int HashEncode(const char * algo, const char * input, unsigned int input_length, char * &output, unsigned int &output_length) { EVP_MD_CTX ctx; const EVP_MD * md = EVP_get_digestbyname(algo); if(!md) { printf("Unknown message digest algorithm: %s\n", algo); return -1; } output = (char *)malloc(EVP_MAX_MD_SIZE); memset(output, 0, EVP_MAX_MD_SIZE); EVP_MD_CTX_init(&ctx); EVP_DigestInit_ex(&ctx, md, NULL); EVP_DigestUpdate(&ctx, input, input_length); EVP_DigestFinal_ex(&ctx, (unsigned char *)output, &output_length); EVP_MD_CTX_cleanup(&ctx); return 0; }
#include "algo_hash.h" #include "stdio.h" #include <iostream> #include <string> using namespace std; void hex_output(const char * buff, unsigned int length) { for(int i = 0; i < length; ++i) { printf("%-3x", (unsigned char)(*(buff + i))); } cout << endl; } int main(int argc, char* argv[]) { if(argc < 2) { cout << "Algorithm is required!" << endl; return -1; } HashInit(); string input = "DFADGJAOUEORQ798686VX8X7B8FG97"; char * output = NULL; unsigned int output_length = 0; int result = HashEncode(argv[1], input.c_str(), input.length(), output, output_length); cout << "Result: " << result << endl; cout << "Input length: " << input.length() << endl; cout << "Input: " << input << "~" << endl; cout << "Output length: " << output_length << endl; cout << "Output: " << endl; hex_output(output, output_length); return 0; }Makefile
INC_OPT = -I/usr/include/openssl -I. -g LNK_OPT = -L/usr/lib64 -lssl -g all: g++ $(INC_OPT) -c algo_hash.cpp g++ $(INC_OPT) -c main.cpp g++ $(LNK_OPT) -o test algo_hash.o main.o clean: rm -f *.o test
各种算法Hash后的子串的长度
算法 | Hash后的长度(字节) |
---|---|
SHA512 | 64 |
SHA384 | 48 |
SHA256 | 32 |
SHA224 | 28 |
SHA1 | 20 |
SHA | 20 |
MD5 | 16 |
MD2 | ? |
【补充】
如果只想做SHA1,可以用 https://www.openssl.org/docs/crypto/sha.html 介绍的下面函数。
unsigned char *SHA1(const unsigned char *d, unsigned long n, unsigned char *md);
类似的SHA256等函数,在openssl的源码中都有。