MD5信息摘要算法
(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value)。摘要算法,是一个不可逆过程,就是与数据大小无关,经过算法运算后都是生成固定长度的一组数据,结果为16进制进行显示的128bit的二进制串。通常表示为32个十六进制数连成的字符串。
一、linux md5的应用
1、使用mdsum命令
echo -n “abcdefg” | md5sum |tr a-z A-Z
输出结果:7AC66C0F148DE9519B8BD264312C4D64
2、使用openssl md5
echo -n “abcdefg” | openssl md5 |tr a-z A-Z
输出同样结果:7AC66C0F148DE9519B8BD264312C4D64
注释:
-n 参数,强制去掉echo时回车,不然输出结果是错误的。
|tr a-z A-Z 参数,将输出结果转化为大写字母。
3、使用标准C测试
调用库 #include<openssl/md5.h>
主要用下面几个函数
数据大的话用下面三个函数。
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);
写完代码,编译时需加参数-lcrypto调用openssl动态库,不然会出错
gcc -lcrypto test.c -o test
md5.h库内容显示如下:
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (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
*/
#ifndef HEADER_MD5_H
# define HEADER_MD5_H
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_MD5
# include <openssl/e_os2.h>
# include <stddef.h>
# ifdef __cplusplus
extern "C" {
# endif
/*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* ! 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)
# define MD5_DIGEST_LENGTH 16
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
# endif
#endif
例子:vi md5.c
#include<stdio.h>
#include<string.h>
#include<openssl/md5.h>
void test1()
{
unsigned char *str= "20:35:6E:18:2A:86";
unsigned char md[16];
int i;
char temp[3];
char code[33];
MD5(str,strlen(str),md);
for (i = 0; i < 16; i++){
sprintf(temp,"%2.2X",md[i]);
strcat(code,temp);
}
printf("test1 str to code:%s\n",code);
}
void test2()
{
MD5_CTX ctx;
unsigned char *str= "20:35:6E:18:2A:86";
unsigned char md[16];
int i;
char temp[3];
char code[33];
MD5_Init(&ctx);
MD5_Update(&ctx,str,strlen(str));
MD5_Final(md,&ctx);
for( i=0; i<16; i++ ){
sprintf(temp,"%02X",md[i]);
strcat(code,temp);
}
printf("test2 str to code:%s\n",code);
}
int main( int argc, char **argv )
{
test1();
test2();
return 0;
}
输出结果:
test1 str to code:2C0EC30AA819B957D997343135D5268B
test2 str to code:2C0EC30AA819B957D997343135D5268B
二、实用栗子
自定算法简易描述如下:
1、列出设备网络MAC字符串
2、以某种方式生成一个随机数
3、将生成的随机数按既定方式混入MAC字符串中
4、然后将字符串的头部增加固定字符,尾部增加固定字符,连接生成一个新字符串。
5、将新字符串使用md5算法计算出一组32位hex字符串
6、把32个字符串分解为32个整型数据,依次乘以一个定值,循环累加。
7、将最终的累加值以字符串形式输出。
三、具体代码
下面代码在openEuler环境下用gcc和termux环境下用clang均通过测试,仅供学习参考研究,不作他用。
vi test.c
gcc -lcrypto test.c -o test
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<openssl/md5.h>
//#pragma clang diagnostic ignored "-Wpointer-sign"
//gcc md5.c -o ~/md5 -lcrypto
char *mac_str(char *mac,char *rand)
{
int i,mac_len,rand_len,offset;
char mac_b[50];
char temp[4];
char mac1[19];
char rand1[7];
strcpy(mac1,mac);
strcpy(rand1,rand);
rand_len= strlen(rand);
mac_len = strlen(mac);
mac[mac_len-1] = rand[rand_len-1];
offset = 0;
for (i=0;i<mac_len;i++)
{
if (mac[i] == ':')
{
mac[i] = rand[offset];
offset += 1;
}
}
if (rand[0] == 'C')
{
for (i=0;i<mac_len;i++)
{
sprintf(temp,"%d",mac[i]);
strcat(mac_b,temp);
}
}
return mac;
}
int adb_key(char *rand_s,char *mac_s)
{
char r[7],m[19];
char buf[50];
int i,result;
char p[10];
char str[50];
unsigned char buf_u[50];
unsigned char md_u[16];
strcpy(r,rand_s);
strcpy(m,mac_s);
sprintf(buf,"linux%s@%sHW_openEuler",r,m);
for (i=0;i<strlen(buf);i++)
{
buf_u[i]=(int)buf[i];
}
MD5(buf_u,strlen(buf),md_u);
str[0]='\0';
for (i=0;i<sizeof(md_u);i++)
{
p[0]='\0';
sprintf(p,"%2.2X",md_u[i]);
strcat(str,p);
}
result=0;
for (i=0;i<strlen(str);i++)
{
result=(int)(str[i])+31*result;
}
if (result<0)
result=-result;
return result;
}
int main(int argc, char* argv[])
{
char input_mac[19];
char input_rand[7];
char check[19];
int key;
printf("input mac press enter,for example:04:15:A3:3E:58:8A\n");
scanf("%s",input_mac);
printf("input rand press enter,for example:C78369\n");
scanf("%s",input_rand);
strcpy(check,mac_str(input_mac,input_rand));
key=adb_key(input_rand,check);
printf("Success! key is:\n%d\n",key);
}