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

相关文章

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

Python通过模块化开发优化代码的技巧分享

《Python通过模块化开发优化代码的技巧分享》模块化开发就是把代码拆成一个个“零件”,该封装封装,该拆分拆分,下面小编就来和大家简单聊聊python如何用模块化开发进行代码优化吧... 目录什么是模块化开发如何拆分代码改进版:拆分成模块让模块更强大:使用 __init__.py你一定会遇到的问题模www.

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Python解析器安装指南分享(Mac/Windows/Linux)

《Python解析器安装指南分享(Mac/Windows/Linux)》:本文主要介绍Python解析器安装指南(Mac/Windows/Linux),具有很好的参考价值,希望对大家有所帮助,如有... 目NMNkN录1js. 安装包下载1.1 python 下载官网2.核心安装方式3. MACOS 系统安

Java实现MD5加密的四种方式

《Java实现MD5加密的四种方式》MD5是一种广泛使用的哈希算法,其输出结果是一个128位的二进制数,通常以32位十六进制数的形式表示,MD5的底层实现涉及多个复杂的步骤和算法,本文给大家介绍了Ja... 目录MD5介绍Java 中实现 MD5 加密方式方法一:使用 MessageDigest方法二:使用

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

Java嵌套for循环优化方案分享

《Java嵌套for循环优化方案分享》介绍了Java中嵌套for循环的优化方法,包括减少循环次数、合并循环、使用更高效的数据结构、并行处理、预处理和缓存、算法优化、尽量减少对象创建以及本地变量优化,通... 目录Java 嵌套 for 循环优化方案1. 减少循环次数2. 合并循环3. 使用更高效的数据结构4

Python中常用的四种取整方式分享

《Python中常用的四种取整方式分享》在数据处理和数值计算中,取整操作是非常常见的需求,Python提供了多种取整方式,本文为大家整理了四种常用的方法,希望对大家有所帮助... 目录引言向零取整(Truncate)向下取整(Floor)向上取整(Ceil)四舍五入(Round)四种取整方式的对比综合示例应