从OpenSSL库中分离算法-MD5算法

Posted 逆光倾城

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从OpenSSL库中分离算法-MD5算法相关的知识,希望对你有一定的参考价值。

从OpenSSL库中分离算法-MD5算法

OpenSSL简介:

OpenSSL 是用于传输层安全性 (TLS) 和安全套接字层 (SSL) 协议的一个强大、商业级和功能齐全的工具包,它也是一个通用的密码学库。包含有RSA、SM4、DES、AES等诸多加密算法。

OpenSSL GitHub地址如下:

GitHub - openssl/openssl: TLS/SSL and crypto library

在日常的开发工作中,有时只想用OpenSSL库中的一种算法,此时调用整个OpenSSL库,往往是没必要的;再或者在嵌入式平台使用某一算法,那我们只移植这个算法,没有必要移植整个OpenSSL库。

MD5简介

MD5全称是第5代信息摘要算法,由英文拼写(Message-Digest Algorithm)缩略而成,即MD5,既然是第5代,那么之前还有MD4、MD3、MD2,前几代算法有的经过一段时间的应用,有的只是昙花一现,而MD5可以说是一棵常青树,虽然它也存在被碰撞的安全隐患。

MD5是一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。

移植过程

跳转操作视频-Bilibili

一、下载代码

从OpenSSL的Github仓库下载代码,可以下载master分支,也可以下载最新的release版本。将下载的文件解压,得到代码。

重点关注红框目录:

  • crypto目录内是各种加密算法
  • include目录内是各加密算法对外接口的头文件

二、准备环境

新建Visual Studio C++ 控制台项目"md5test",编译选项是:x86\\Debug


三、准备文件

  1. 复制OpenSSL源码中:/crypto/md5文件夹到VS工程代码目录下
  2. 复制OpenSSL源码中:/include/openssl/md5.h文件到VS工程代码目录中md5文件夹内
  3. 复制OpenSSL源码中:/include/crypto/md32_common.h文件到VS工程代码目录中md5文件夹内
  4. 复制完成后,VS工程代码目录md5文件夹内文件如下:

删除目录内的如下本项目中无用文件:

  • asm
  • build.info
  • md5_sha1.c

四、修改代码

修改调用文件

在VS工程中含有main函数的主文件:md5test.cpp中,增加包含md5.h头文件

#include "md5/md5.h"

在main函数中添加如下代码

    const unsigned char Data[5] = "abcd"; //待计算md5的数据
    unsigned char md[MD5_DIGEST_LENGTH] = { 0 }; //md5存储的变量
    unsigned char* P = MD5(Data, strlen((const char*)Data), md);  //计算md5
    for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {  //输出md5
        printf("%x-", *(md + i));
    }

修改后的md5test.cpp代码如下:

#include <iostream>
#include "md5/md5.h"
int main()
{
    const unsigned char Data[5] = "abcd"; //待计算md5的数据,若要计算文件的md5,则Data为从文件中读取的数据。
    unsigned char md[MD5_DIGEST_LENGTH] = { 0 }; //md5存储的变量
    unsigned char* P = MD5(Data, strlen((const char*)Data), md);  //计算md5
    for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {  //输出md5
        printf("%02x-", *(md + i));
    }
}

修改md5.h

删除条件编译 OPENSSL_MD5_H

删除条件编译 OPENSSL_NO_DEPRECATED_3_0

删除条件编译 OPENSSL_NO_DEPRECATED_3_0

删除条件编译 OPENSSL_NO_MD5

删除头文件# include <openssl/macros.h>

删除头文件# include <openssl/opensslconf.h>

删除头文件# include <openssl/e_os2.h>

删除函数类型宏OSSL_DEPRECATEDIN_3_0

修改或删除后的文件如下:

# pragma once
#  include <stddef.h>
#  ifdef  __cplusplus
extern "C" {
#  endif

#  define MD5_DIGEST_LENGTH 16

/*
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * ! MD5_LONG has to be at least 32 bits wide.                     !
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 */
#   define MD5_LONG unsigned int
#   define MD5_CBLOCK      64
#   define MD5_LBLOCK      (MD5_CBLOCK/4)

typedef struct MD5state_st {
    MD5_LONG A, B, C, D;
    MD5_LONG Nl, Nh;
    MD5_LONG data[MD5_LBLOCK];
    unsigned int num;
} MD5_CTX;

int MD5_Init(MD5_CTX *c);
int MD5_Update(MD5_CTX *c, const void *data, size_t len);
int MD5_Final(unsigned char *md, MD5_CTX *c);
unsigned char *MD5(const unsigned char *d, size_t n,
                   unsigned char *md);
void MD5_Transform(MD5_CTX *c, const unsigned char *b);

#  ifdef  __cplusplus
}
#  endif

修改md5_dgst.c

删除头文件# include "internal/deprecated.h"

删除头文件# include <openssl/opensslv.h>

修改或删除后的文件如下:

#include <stdio.h>
#include "md5_local.h"

/*
 * Implemented from RFC1321 The MD5 Message-Digest Algorithm
 */

#define INIT_DATA_A (unsigned long)0x67452301L
#define INIT_DATA_B (unsigned long)0xefcdab89L
#define INIT_DATA_C (unsigned long)0x98badcfeL
#define INIT_DATA_D (unsigned long)0x10325476L

int MD5_Init(MD5_CTX *c)
{
    memset(c, 0, sizeof(*c));
    c->A = INIT_DATA_A;
    c->B = INIT_DATA_B;
    c->C = INIT_DATA_C;
    c->D = INIT_DATA_D;
    return 1;
}

#ifndef md5_block_data_order
# ifdef X
#  undef X
# endif
void md5_block_data_order(MD5_CTX *c, const void *data_, size_t num)
{
    const unsigned char *data = data_;
    register unsigned MD32_REG_T A, B, C, D, l;
# ifndef MD32_XARRAY
    /* See comment in crypto/sha/sha_local.h for details. */
    unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
        XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15;
#  define X(i)   XX##i
# else
    MD5_LONG XX[MD5_LBLOCK];
#  define X(i)   XX[i]
# endif

    A = c->A;
    B = c->B;
    C = c->C;
    D = c->D;

    for (; num--;) {
        (void)HOST_c2l(data, l);
        X(0) = l;
        (void)HOST_c2l(data, l);
        X(1) = l;
        /* Round 0 */
        R0(A, B, C, D, X(0), 7, 0xd76aa478L);
        (void)HOST_c2l(data, l);
        X(2) = l;
        R0(D, A, B, C, X(1), 12, 0xe8c7b756L);
        (void)HOST_c2l(data, l);
        X(3) = l;
        R0(C, D, A, B, X(2), 17, 0x242070dbL);
        (void)HOST_c2l(data, l);
        X(4) = l;
        R0(B, C, D, A, X(3), 22, 0xc1bdceeeL);
        (void)HOST_c2l(data, l);
        X(5) = l;
        R0(A, B, C, D, X(4), 7, 0xf57c0fafL);
        (void)HOST_c2l(data, l);
        X(6) = l;
        R0(D, A, B, C, X(5), 12, 0x4787c62aL);
        (void)HOST_c2l(data, l);
        X(7) = l;
        R0(C, D, A, B, X(6), 17, 0xa8304613L);
        (void)HOST_c2l(data, l);
        X(8) = l;
        R0(B, C, D, A, X(7), 22, 0xfd469501L);
        (void)HOST_c2l(data, l);
        X(9) = l;
        R0(A, B, C, D, X(8), 7, 0x698098d8L);
        (void)HOST_c2l(data, l);
        X(10) = l;
        R0(D, A, B, C, X(9), 12, 0x8b44f7afL);
        (void)HOST_c2l(data, l);
        X(11) = l;
        R0(C, D, A, B, X(10), 17, 0xffff5bb1L);
        (void)HOST_c2l(data, l);
        X(12) = l;
        R0(B, C, D, A, X(11), 22, 0x895cd7beL);
        (void)HOST_c2l(data, l);
        X(13) = l;
        R0(A, B, C, D, X(12), 7, 0x6b901122L);
        (void)HOST_c2l(data, l);
        X(14) = l;
        R0(D, A, B, C, X(13), 12, 0xfd987193L);
        (void)HOST_c2l(data, l);
        X(15) = l;
        R0(C, D, A, B, X(14), 17, 0xa679438eL);
        R0(B, C, D, A, X(15), 22, 0x49b40821L);
        /* Round 1 */
        R1(A, B, C, D, X(1), 5, 0xf61e2562L);
        R1(D, A, B, C, X(6), 9, 0xc040b340L);
        R1(C, D, A, B, X(11), 14, 0x265e5a51L);
        R1(B, C, D, A, X(0), 20, 0xe9b6c7aaL);
        R1(A, B, C, D, X(5), 5, 0xd62f105dL);
        R1(D, A, B, C, X(10), 9, 0x02441453L);
        R1(C, D, A, B, X(15), 14, 0xd8a1e681L);
        R1(B, C, D, A, X(4), 20, 0xe7d3fbc8L);
        R1(A, B, C, D, X(9), 5, 0x21e1cde6L);
        R1(D, A, B, C, X(14), 9, 0xc33707d6L);
        R1(C, D, A, B, X(3), 14, 0xf4d50d87L);
        R1(B, C, D, A, X(8), 20, 0x455a14edL);
        R1(A, B, C, D, X(13), 5, 0xa9e3e905L);
        R1(D, A, B, C, X(2), 9, 0xfcefa3f8L);
        R1(C, D, A, B, X(7), 14, 0x676f02d9L);
        R1(B, C, D, A, X(12), 20, 0x8d2a4c8aL);
        /* Round 2 */
        R2(A, B, C, D, X(5), 4, 0xfffa3942L);
        R2(D, A, B, C, X(8), 11, 0x8771f681L);
        R2(C, D, A, B, X(11), 16, 0x6d9d6122L);
        R2(B, C, D, A, X(14), 23, 0xfde5380cL);
        R2(A, B, C, D, X(1), 4, 0xa4beea44L);
        R2(D, A, B, C, X(4), 11, 0x4bdecfa9L);
        R2(C, D, A, B, X(7), 16, 0xf6bb4b60L);
        R2(B, C, D, A, X(10), 23, 0xbebfbc70L);
        R2(A, B, C, D, X(13), 4, 0x289b7ec6L);
        R2(D, A, B, C, X(0), 11, 0xeaa127faL);
        R2(C, D, A, B, X(3), 16, 0xd4ef3085L);
        R2(B, C, D, A, X(6), 23, 0x04881d05L);
        R2(A, B, C, D, X(9), 4, 0xd9d4d039L);
        R2(D, A, B, C, X(12), 11, 0xe6db99e5L);
        R2(C, D, A, B, X(15以上是关于从OpenSSL库中分离算法-MD5算法的主要内容,如果未能解决你的问题,请参考以下文章

hashlib库:Python的加密算法实践

openssl evp 哈希算法(md5,sha1,sha256)

火山中文编程 -- MD5算法和SHA算法

md5 加密算法和升级

OpenSSL之摘要MD5用法

MacOS下使用OpenSSL(LibreSSL)