学习openssl中的hash算法

项目中实现了checksum服务,看了下实现,用的是openssl库中的hash算法。

很简单的一个实现如下:

 1         std::string ChecksumImplement::SHA1(const std::string & str)

 2         {

 3             unsigned char sha1_digest[SHA1_DIGEST_LENGTH] = {0};

 4             ::SHA1(reinterpret_cast<const unsigned char *> (str.c_str()), str.length(), sha1_digest);

 5             char buffout[SHA1_DIGEST_LENGTH * 4] = {0};

 6             for (int i = 0; i < SHA1_DIGEST_LENGTH; i++) {

 7                 sprintf(buffout + i * 2, "%02x", sha1_digest[i]);

 8             }

 9             return buffout;

10         }

 

更多说明:

SHA1散列函数是很常用的散列函数,它产生160bit(20字节)长度的散列值。

今天,我就来介绍利用OpenSSL现成的API来计算数据的SHA1散列值。

先来看OpenSSL的相关API声明:

1 #include <openssl/sha.h>  

2  unsigned char *SHA1(const unsigned char *d, unsigned long n,  

3                   unsigned char *md);  

4  int SHA1_Init(SHA_CTX *c);  

5  int SHA1_Update(SHA_CTX *c, const void *data,  

6                   unsigned long len);  

7  int SHA1_Final(unsigned char *md, SHA_CTX *c); 

这里有2个(套)API可以来计算数据的SHA1散列值。

最先的SHA1函数很直白,参数d是数据块的起始地址,n是数据块的长度,计算的散列值存储在参数md指向的内存中。如果md为NULL,那么SHA1函数会把计算得到的散列值存储在函数内部的静态空间内,然后通过函数返回值返回给我们。刚才我们说过SHA1散列值的长度为20字节,所以md至少需要拥有20字节的空间大小。当然,OpenSSL已经为我们定义了常量SHA_DIGEST_LENGTH。



对于第二套API,我们看到由3个函数组成。粗粗一看,有些看客会觉得3个函数不就是完成SHA1函数的功能吗?为什么要搞3个函数来啊?呵呵,OpenSSL显然是有充分的理由来这么做的。这么做的关键是SHA1_Update这个函数可以被调用多次,这些待计算散列值的数据会被叠加,最终产生一个散列值。也许有人现在还没想到它的使用场景,我下面来举个例子点破。



比如一个文件大小为6GB,我们知道32位程序无法访问大于4GB的内存空间(其实程序员可以操作的最多也就3GB,程序/数据/栈/保护区等会占用1GB左右的空间),这时如何计算这个文件的散列值?SHA1肯定是不行的了。这时我们可以分N次来读这个文件,每次读1MB的数据,然后调用SHA1_Update函数来累计计算散列值,读完文件的所有数据后,我们再调用SHA1_Final函数来得到最终的散列值。

 http://yinghao.blog.51cto.com/3072047/562542

 

 

项目里用第二套api实现了对文件做校验:

 1     std::string ChecksumImplement::SHA1File(const std::string & filepath)

 2         {

 3             FILE * fp = fopen(filepath.c_str(), "rb");

 4             if (!fp) {

 5                 fprintf(stderr, "Could not open file: %s\n", filepath.c_str());

 6                 return "";

 7             }

 8 

 9             unsigned char buffin[BUFF_SIZE];

10             unsigned char sha1_digest[SHA1_DIGEST_LENGTH] = {0};

11             size_t nread;

12 

13             SHA_CTX ctx;

14             SHA1_Init(&ctx);

15 

16             while (nread = fread(buffin, 1, BUFF_SIZE, fp)) {

17                 SHA1_Update(&ctx, buffin, nread);

18             }

19 

20             SHA1_Final(sha1_digest, &ctx);

21             fclose(fp);

22 

23             char buffout[SHA1_DIGEST_LENGTH * 4] = {0};

24             for (int i = 0; i < SHA1_DIGEST_LENGTH; i++)

25                 sprintf(buffout + i * 2, "%02x", sha1_digest[i]);

26 

27             return buffout;

28         }

 

当然了,还有MD5等其他算法,就不说了。

 

 

 

 

你可能感兴趣的:(OpenSSL)