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;
}
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;
}
#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;
}
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);