调用OpenSSL的SHA1算法

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

SHA1相关的API声明

#include <openssl/sha.h>  
unsigned char *SHA1(const unsigned char *d, unsigned long n, unsigned char *md);  
int SHA1_Init(SHA_CTX *c);  
int SHA1_Update(SHA_CTX *c, const void *data, unsigned long len);  
int SHA1_Final(unsigned char *md, SHA_CTX *c); 

两种方法计算SHA1

  • 早期的SHA1函数很直白,参数d是数据块的起始地址,n是数据块的长度,计算的散列值存储在参数md指向的内存中。如果md为NULL,那么SHA1函数会把计算得到的散列值存储在函数内部的静态空间内,然后通过函数返回值返回给我们。
    md至少需要拥有20字节的空间大小,分配空间时可以直接使用OpenSSL为我们定义了的常量SHA_DIGEST_LENGTH
  • 第二种方法需要3个函数,其中的关键是SHA1_Update这个函数,它可以被调用多次。每次待计算散列值的数据会被叠加,最终产生一个散列值。例如:

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

两种方法的示例

示例1:

#include <stdio.h>  
#include <string.h>  
#include <openssl/sha.h>  
  
int main()  
{  
  
    unsigned char digest[SHA_DIGEST_LENGTH];  
    char string[] = "hello world";  
  
    SHA1((unsigned char*)&string, strlen(string), (unsigned char*)&digest);  
    char mdString[SHA_DIGEST_LENGTH*2+1];  
  
    for(int i = 0; i < SHA_DIGEST_LENGTH; i++)   
        sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]);  
  
    printf("SHA1 digest: %s\n", mdString);  
    return 0;  
  
} 

示例2:

#include <stdio.h>  
#include <string.h>  
#include <openssl/sha.h>  
  
int main() {  
  
    unsigned char digest[SHA_DIGEST_LENGTH];  
    const char* string = "hello world";  
  
    SHA_CTX ctx;  
    SHA1_Init(&ctx);  
    SHA1_Update(&ctx, string, strlen(string));  
    SHA1_Final(digest, &ctx);  
  
    char mdString[SHA_DIGEST_LENGTH*2+1];  
    for (int i = 0; i < SHA_DIGEST_LENGTH; i++)  
        sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]);  
  
    printf("SHA1 digest: %s\n", mdString);  
  
    return 0;  
  
}  

标签: Hash SHA

发表评论: