crammd5 php,[原创]cram-md5、hmac-md5算法分享

2023-10-30 11:59

本文主要是介绍crammd5 php,[原创]cram-md5、hmac-md5算法分享,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

关键字:md5、cram-md5、hmac-md5、postfixadmin

今天跟大家分享一下算法,前段时间在服务器上安装postfixadmin,发现设置的密码是cram-md5加密的。

然后呢,又无法修改密码,这就让人头大了,后来看到postfixadmin是用的命令生产的cram-md5加密值。

网上关于cram-md5算法的详细介绍非常少,而且有不少人想知道这个算法的细节。

这里通过开源项目里面dump出来的代码(非常之难找到),然后阅读其算法细节,给大家分享一下。

在说cram-md5之前,先要说说hmac-md5

1、hmac-md5是有一个key,然后对数据进行hash。只有正确的key,才能对相同的数据进行hash得到的hash值相同。

key会生产(简单的异或算法、填充)2个64字节,分别给2个md5 context进行初步md5_update,这样就分别得到2组MD5的a、b、c、d(不知道abcd是啥的看一下md5算法),这2组

a、b、c、d后面cram-md5会说到。

5a551d0ef40fce87edb8ed89900f9045.png

2、然后hmac-md5再输入要hash的数据,其实就是md5_update。

79f225ac92f553bbbf855f261badec09.png

3、最终hmac-md5算法,需要把第一个md5 context的结果当作第二个md5 context的一次数据进行md5-update

6a975b013b1d8a407b56f7001f9eba57.png

细细理解一下,hmac-md5是不是很简单,其实就是md5算法,加一个key混合在一起,得出一个跟key相关的数据hash。

下面开始说cram-md5算法

你看完hmac-md5,其实cram-md5算法就非常容易理解了。

cram-md5相当于半成品的hmac-md5,也就是hmac-md5的第一个步骤得到的2组md5的

a、b、c、d

,这2组一起8个dword,32个字节,正好就是cram-md5的结果了。

53c0bd1d681af22543168e2510295c70.png

我们用key拿到cram-md5的结果之后,下次用相同的key计算一些数据的hmac-md5,把2组

a、b、c、d

恢复回去就可以继续计算了,压根不用知道key的明文啦。

4114f292a7f01ae0bcab73ecbd42e4bc.png

好了算法介绍完了,下面给出完整的代码了。

// cram-md5.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include "md5.h"

#include 

#include 

#include 

/

#define CRAM_MD5_CONTEXTLEN 32

struct hmac_md5_context {

struct md5_context ctx, ctxo;

};

void hmac_md5_init(struct hmac_md5_context *ctx,

const unsigned char *key, size_t key_len);

void hmac_md5_final(struct hmac_md5_context *ctx,

unsigned char digest[MD5_RESULTLEN]);

void hmac_md5_get_cram_context(struct hmac_md5_context *ctx,

unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);

void hmac_md5_set_cram_context(struct hmac_md5_context *ctx,

const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);

static inline void

hmac_md5_update(struct hmac_md5_context *ctx, const void *data, size_t size)

{

md5_update(&ctx->ctx, data, size);

}

void hmac_md5_init(struct hmac_md5_context *ctx,

const unsigned char *key, size_t key_len)

{

int i;

unsigned char md5key[16];

unsigned char k_ipad[64];

unsigned char k_opad[64];

if (key_len > 64) {

md5_get_digest(key, key_len, md5key);

key = md5key;

key_len = 16;

}

memcpy(k_ipad, key, key_len);

memset(k_ipad + key_len, 0, 64 - key_len);

memcpy(k_opad, k_ipad, 64);

for (i = 0; i 

k_ipad[i] ^= 0x36;

k_opad[i] ^= 0x5c;

}

md5_init(&ctx->ctx);

md5_update(&ctx->ctx, k_ipad, 64);

md5_init(&ctx->ctxo);

md5_update(&ctx->ctxo, k_opad, 64);

memset(k_ipad, 0, 64);

memset(k_opad, 0, 64);

}

void hmac_md5_final(struct hmac_md5_context *ctx, unsigned char *digest)

{

md5_final(&ctx->ctx, digest);

md5_update(&ctx->ctxo, digest, 16);

md5_final(&ctx->ctxo, digest);

}

void hmac_md5_get_cram_context(struct hmac_md5_context *ctx,

unsigned char context_digest[CRAM_MD5_CONTEXTLEN])

{

unsigned char *cdp;

#define CDPUT(p, c) {   \

*(p)++ = (c)& 0xff;       \

*(p)++ = (c) >> 8 & 0xff;  \

*(p)++ = (c) >> 16 & 0xff; \

*(p)++ = (c) >> 24 & 0xff; \

}

cdp = context_digest;

CDPUT(cdp, ctx->ctxo.a);

CDPUT(cdp, ctx->ctxo.b);

CDPUT(cdp, ctx->ctxo.c);

CDPUT(cdp, ctx->ctxo.d);

CDPUT(cdp, ctx->ctx.a);

CDPUT(cdp, ctx->ctx.b);

CDPUT(cdp, ctx->ctx.c);

CDPUT(cdp, ctx->ctx.d);

}

void hmac_md5_set_cram_context(struct hmac_md5_context *ctx,

const unsigned char context_digest[CRAM_MD5_CONTEXTLEN])

{

const unsigned char *cdp;

#define CDGET(p, c) { \

(c) = (*p++);           \

(c) += (*p++ <

(c) += (*p++ <

(c) += (*p++ <

}

cdp = context_digest;

CDGET(cdp, ctx->ctxo.a);

CDGET(cdp, ctx->ctxo.b);

CDGET(cdp, ctx->ctxo.c);

CDGET(cdp, ctx->ctxo.d);

CDGET(cdp, ctx->ctx.a);

CDGET(cdp, ctx->ctx.b);

CDGET(cdp, ctx->ctx.c);

CDGET(cdp, ctx->ctx.d);

ctx->ctxo.lo = ctx->ctx.lo = 64;

ctx->ctxo.hi = ctx->ctx.hi = 0;

}

int _tmain(int argc, _TCHAR* argv[])

{

unsigned char hmac[CRAM_MD5_CONTEXTLEN] = { 0 };

hmac_md5_context ctx;

hmac_md5_init(&ctx, (const unsigned char *)"123", 3);

hmac_md5_get_cram_context(&ctx, hmac);

return 0;

}

最后于 2019-6-18 13:32

被tongzeyu编辑

,原因:

这篇关于crammd5 php,[原创]cram-md5、hmac-md5算法分享的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/307784

相关文章

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

Python虚拟环境与Conda使用指南分享

《Python虚拟环境与Conda使用指南分享》:本文主要介绍Python虚拟环境与Conda使用指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、python 虚拟环境概述1.1 什么是虚拟环境1.2 为什么需要虚拟环境二、Python 内置的虚拟环境工具

Python处理大量Excel文件的十个技巧分享

《Python处理大量Excel文件的十个技巧分享》每天被大量Excel文件折磨的你看过来!这是一份Python程序员整理的实用技巧,不说废话,直接上干货,文章通过代码示例讲解的非常详细,需要的朋友可... 目录一、批量读取多个Excel文件二、选择性读取工作表和列三、自动调整格式和样式四、智能数据清洗五、

JDK9到JDK21中值得掌握的29个实用特性分享

《JDK9到JDK21中值得掌握的29个实用特性分享》Java的演进节奏从JDK9开始显著加快,每半年一个新版本的发布节奏为Java带来了大量的新特性,本文整理了29个JDK9到JDK21中值得掌握的... 目录JDK 9 模块化与API增强1. 集合工厂方法:一行代码创建不可变集合2. 私有接口方法:接口

电脑系统Hosts文件原理和应用分享

《电脑系统Hosts文件原理和应用分享》Hosts是一个没有扩展名的系统文件,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应... Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应

Java如何将文件内容转换为MD5哈希值

《Java如何将文件内容转换为MD5哈希值》:本文主要介绍Java如何将文件内容转换为MD5哈希值的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java文件内容转换为MD5哈希值一个完整的Java示例代码代码解释注意事项总结Java文件内容转换为MD5

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Springboot实现推荐系统的协同过滤算法

《Springboot实现推荐系统的协同过滤算法》协同过滤算法是一种在推荐系统中广泛使用的算法,用于预测用户对物品(如商品、电影、音乐等)的偏好,从而实现个性化推荐,下面给大家介绍Springboot... 目录前言基本原理 算法分类 计算方法应用场景 代码实现 前言协同过滤算法(Collaborativ