转自:http://linux.die.net/man/3/evp_sha512
代码如下:
// mdtest.cpp
#include
#include
#include
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
#include
#include
#include
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
#include
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的源码中都有。