用Openssl 做hash(C++)

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

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. -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后的长度(字节)
SHA51264
SHA38448
SHA25632
SHA22428
SHA120
SHA20
MD516
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的源码中都有。


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值