openssl中的MD5加密

零、介绍

MD5(Message Digest Algorithm 5)是一种常用的哈希函数,用于将任意长度的数据映射为固定长度的哈希值。它广泛应用于密码学和数据完整性验证等领域。

MD5加密的特点如下:

1.固定长度输出:MD5生成的哈希值是固定长度的,通常为128位(16个字节)。无论输入数据的长度是多少,都会得到一个固定长度的哈希值。

2.单向性:MD5是单向哈希函数,意味着可以将数据转换为哈希值,但无法从哈希值还原出原始数据。这使得MD5在存储密码等敏感信息时非常有用,因为即使哈希值被泄露,攻击者也难以从中获取原始数据。

3.高效性:MD5的计算速度相对较快,适用于对大量数据进行哈希计算。

4.均匀分布:MD5的哈希值在理想情况下具有均匀分布的特性,即输入数据的微小变化会导致输出哈希值的明显变化,这增加了哈希冲突的概率。

由于MD5的一些安全性缺陷,它已经不再适用于安全敏感的应用场景。由于其较短的输出长度和易受到碰撞攻击(Collision Attack)的特性,MD5已被广泛认为是不安全的。因此,在安全相关的应用中,建议使用更强大和安全性更高的哈希函数,如SHA-256、SHA-512等。MD5仍然在某些非安全性关键的应用中有其用途,例如简单数据完整性验证、快速校验和一致性检查等。

一、简单示例

需要注意的是 MD5 接口函数是线程不安全的,需要自己根据其实现

#include 
#include 
#include 
#include 

int main() {
    char input[] = "Hello, World!";  // 要进行MD5加密的输入数据

    unsigned char digest[MD5_DIGEST_LENGTH];  // 存储MD5结果的缓冲区
    printf("%d\n",MD5_DIGEST_LENGTH);
    //MD5((const unsigned char*)input, strlen(input), digest);  // 进行MD5计算
    MD5((const unsigned char*)input, strlen(input), digest);

    for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { // 将MD5结果以十六进制形式打印输出
        printf("%02x", digest[i]);
    }
    printf("\n");

    return 0;
}

二、MD5 接口API源码实现

3.0里增加了弃用注释,但并没有编译告警或者完善线程不安全的问题

/*
 * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

/*
 * MD5 low level APIs are deprecated for public use, but still ok for
 * internal use.
 */
#include "internal/deprecated.h"

#include 
#include 
#include 
#include 

#ifdef CHARSET_EBCDIC
# include 
#endif

unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md)
{
    MD5_CTX c;
    static unsigned char m[MD5_DIGEST_LENGTH];

    if (md == NULL)
        md = m;
    if (!MD5_Init(&c))
        return NULL;
#ifndef CHARSET_EBCDIC
    MD5_Update(&c, d, n);
#else
    {
        char temp[1024];
        unsigned long chunk;

        while (n > 0) {
            chunk = (n > sizeof(temp)) ? sizeof(temp) : n;
            ebcdic2ascii(temp, d, chunk);
            MD5_Update(&c, temp, chunk);
            n -= chunk;
            d += chunk;
        }
    }
#endif
    MD5_Final(md, &c);
    OPENSSL_cleanse(&c, sizeof(c)); /* security consideration */
    return md;
}

三、自己修改 MD5 接口的实现

#include 
#include 
#include 
#include 
#include 

typedef struct MD5RESULT{
    unsigned char data[MD5_DIGEST_LENGTH];
    int result;
}MD5_RESULT;

MD5_RESULT MD5jn(const unsigned char *d, size_t n)
{
    MD5_CTX c;
    MD5_RESULT md5res{{0},-1};

    if (!MD5_Init(&c))
        return md5res;
#ifndef CHARSET_EBCDIC
    MD5_Update(&c, d, n);
#else
    {
        char temp[1024];
        unsigned long chunk;

        while (n > 0) {
            chunk = (n > sizeof(temp)) ? sizeof(temp) : n;
            ebcdic2ascii(temp, d, chunk);
            MD5_Update(&c, temp, chunk);
            n -= chunk;
            d += chunk;
        }
    }
#endif
    MD5_Final(md5res.data, &c);
    OPENSSL_cleanse(&c, sizeof(c)); /* security consideration */

    md5res.result = 0;
    return md5res;
}

/* compile : g++ -std=c++11 -I./include -L./lib -lssl -lcrypto md5.cpp -lrt  -Wl,-rpath=./ */
int main() {
    char input[] = "Hello, World!";  // 要进行MD5加密的输入数据

    unsigned char digest[MD5_DIGEST_LENGTH];  // 存储MD5结果的缓冲区
    printf("%d\n",MD5_DIGEST_LENGTH);
    //MD5((const unsigned char*)input, strlen(input), digest);  // 进行MD5计算,线程不安全
    MD5_RESULT res = MD5jn((const unsigned char*)input, strlen(input));

    if (res.result >= 0) {
        for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
            printf("%02x", res.data[i]);
        }
        printf("\n");
    }

    return 0;
}

四、相关API

MD5_Init、MD5_Update、MD5_Final为基本API
需要注意的是 MD5 为上述三个接口的封装,但不可重入

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

你可能感兴趣的:(算法)