用Openssl 做hash(C++)

来源:互联网 发布:数组是js数据类型吗? 编辑:程序博客网 时间:2024/06/06 05:26

转自: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;}

假设我们知道openssl 的头文件位于 /yasi/code/openssl-1.0.1c/include,而openssl 库文件位于 /usr/lib64,用下面的命令编译:

g++ -o mdtest mdtest.cpp -I/yasi/code/openssl-1.0.1c/include -lssl -lcrypto -L/usr/lib64


运行及结果:

./mdtest sha1Digest is: 0541d4e2b052e6ed4bb7e294a1884c2cfbbf30d8./mdtest sha224Digest is: 1398d1428f5449ddad27d18c78d06ca1831937d2e342dafc76b693be./mdtest sha256Digest is: 318b20b83a6730b928c46163a2a1cefee4466132731c95c39613acb547ccb715./mdtest sha384Digest is: 22511d0e8dfafe6ea698635d2e549056f8d48eba210a2b7040a3d89830660b1c1f5d38e218e86d036e489b1121b1bfc1./mdtest sha512Digest 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

algo_hash.cpp

#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;}

测试代码 main.cpp

#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. -gLNK_OPT = -L/usr/lib64 -lssl -gall:        g++ $(INC_OPT) -c algo_hash.cpp        g++ $(INC_OPT) -c main.cpp        g++ $(LNK_OPT) -o test algo_hash.o main.oclean:        rm -f *.o test

各种算法Hash后的子串的长度

算法Hash后的长度(字节)SHA51264SHA38448SHA25632SHA22428SHA120SHA20MD516MD2?


【补充】

如果只想做SHA1,可以用 https://www.openssl.org/docs/crypto/sha.html 介绍的下面函数。

unsigned char *SHA1(const unsigned char *d, unsigned long n,                  unsigned char *md);

类似的SHA256等函数,在openssl的源码中都有。


原创粉丝点击