OpenSSL消息摘要

                                                                           OpenSSL消息摘要

1.目的

    (1) 掌握OpenSSL消息摘要原理和常用API;

    (2) 基于OpenSSL库开发命令行消息摘要程序。

2.步骤

    (1) 实现独立的文件摘要函数,支持对文件的摘要计算,支持MD5和SHA-1两种摘要算法;

    (2) 在Main函数中调用上述函数,实现命令行参数控制,示例如下:

>myDigest md5 some.txt
……
>myDigest sha1 some.txt
……

    (3) 安装一个商业的摘要软件(“如文件MD5校验工具”),与自己编写的摘要软件对同一个文件求取摘要(Hash),看看所得结果是否相同?对大文件的支持是否完善?

3.结果

   (1) 消息参考实例结果:

       使用MD5摘要算法对两段字符串数据进行了摘要计算。

       File: main.c:  

 #include <stdio .h>
 #include <string .h>
 #include<openssl/evp.h>
void tDigest ()
 {
 unsignedcharmd_value[EVP_MAX_MD_SIZE];//保存输出的摘要值的数组
 int md_len, i;
 EVP_MD_CTX mdctx; //EVP 消息摘要结构体
 charmsg1[] = "Test Message1";//待计算摘要的消息1
 charmsg2[] = "TestMessage2"; //待计算摘要的消息2
 EVP_MD_CTX_init(&mdctx);//初始化摘要结构体
 EVP_DigestInit_ex(&mdctx,EVP_md5(), NULL); //设置摘要算法和密码算法引擎
 EVP_DigestUpdate(&mdctx,msg1, strlen(msg1)); //调用摘要Update计算msg1的摘要
 EVP_DigestUpdate(&mdctx,msg2, strlen(msg2)); //调用摘要Update计算msg2的摘要
 EVP_DigestFinal_ex(&mdctx, md_value,&md_len);//摘要结束,输出摘要值
 EVP_MD_CTX_cleanup(&mdctx); //释放内存
 printf ("Primary data %sand %s 's digests :\n",msg1, msg2);
 for(i = 0; i < md_len;i++)
 {
printf ("0x%02x ", md_value[i]);
 }
 printf ("\n");
}
  int main()
  {
    OpenSSL_add_all_algorithms();
    tDigest() ;
  return 0;
}

     OpenSSL消息摘要_第1张图片

    

    (2) 计算文件摘要命令行工具,支持md5和sha1摘要算法:

     File: main.c:

#include<stdio.h>
#include<string.h>
#include<openssl/evp.h>
int DigestFile(char *infile, unsigned char*alg)
{
  unsigned char md_value[EVP_MAX_MD_SIZE];
  int i;
  unsigned int md_len;
  EVP_MD_CTX mdctx;
  FILE *fpIn;
  int inl;
  unsigned char in[1024];
  const EVP_MD *evpMd;
  if(strcmp((const char*)alg,"md5") == 0)
  {
     evpMd = EVP_md5();
  }
  else if(strcmp((const char*)alg,"sha1") == 0)
  {
     evpMd = EVP_sha1();
  }
  else
  {
    printf ("Err Code [13]: Incorrect type of argument, md5 or sha1 accepted .\n");
    return 13;
  }
  fpIn = fopen( infile , "rb");
  if (fpIn == NULL)
  {
    printf ("Err Code [12]: Open file %s for read err , check the file path .\n", infile );
    return 12;
  }
  EVP_MD_CTX_init(&mdctx);
  EVP_DigestInit_ex(&mdctx, evpMd, NULL);
  while(1)
  {
   inl=fread(in,1,1024,fpIn);
   if ( inl <= 0)
   break;
   EVP_DigestUpdate(&mdctx, in, inl);
  }
  EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
  EVP_MD_CTX_cleanup(&mdctx);
  printf ("%s<%s> = ", alg, infile );
  for(i = 0; i < md_len; i++)
  {
    printf ("%02x", md_value[i]);
  }
  printf ("\n");
  fclose (fpIn);
  return 0;
}
int main(int argc, char*argv[])
{
 
 if (argc != 3)
 {
   printf ("Err code [11]: Incorrect number of args, 2 args received .\n");
   return 11;
 }
 OpenSSL_add_all_algorithms();
 DigestFile(argv[2],(unsigned char *)argv[1]);
 return 0;
}
 

  (3) 文件MD5校验工具摘要:

  OpenSSL消息摘要_第2张图片

OpenSSL消息摘要_第3张图片

4.问题及解决方法

   (1) 命令行参数不对:

   

   argc是命令行总的参数个数  
   argv[]
argc个参数,其中第0个参数是程序的全名,以后的参数命令行后面跟的用户输入的参数。

myDigest md5book.txt
 ……
myDigest sha1book.txt
 ……

  按上述示例输入正确的命令行参数。

  

 (2) 函数int DigestFile(char *infile, unsigned char*alg)形参和实参类型不匹配:

    使用强制类型转换:

 

unsigned int md_len;
......
if(strcmp((const char*)alg,"md5") == 0)
......
else if(strcmp((const char*)alg,"sha1") == 0)
......
EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
......
DigestFile(argv[2],(unsigned char *)argv[1]);
  

   (3) 上面的商业软件摘要结果与摘要函数结果相同,但对于大文件的支持还不够完善,摘要函数还有缺陷。摘要函数的输入文件位数不能超过1024位(unsigned char in[1024];),超过限制位数,摘要函数的摘要结果无法保证是正确的。

你可能感兴趣的:(OpenSSL,消息摘要)