📄 cram_md5.c
字号:
#include <stdlib.h>
//#include "md5.c"
#include "Cram_md5.h"
/* $Cambridge: exim/exim-src/src/auths/md5.c,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2007 */
/* See the file NOTICE for conditions of use and distribution. */
#if 0
typedef struct md5
{
unsigned int length;
unsigned int abcd[4];
}md5;
#endif
/*************************************************
* Start off a new MD5 computation. *
*************************************************/
/*
Argument: pointer to md5 storage structure
Returns: nothing
*/
void
md5_start(md5 *base)
{
base->abcd[0] = 0x67452301;
base->abcd[1] = 0xefcdab89;
base->abcd[2] = 0x98badcfe;
base->abcd[3] = 0x10325476;
base->length = 0;
}
/*************************************************
* Process another 64-byte block *
*************************************************/
/* This function implements central part of the algorithm which is described
in RFC 1321.
Arguments:
base pointer to md5 storage structure
text pointer to next 64 bytes of subject text
Returns: nothing
*/
void
md5_mid(md5 *base, const unsigned char *text)
{
register unsigned int a = base->abcd[0];
register unsigned int b = base->abcd[1];
register unsigned int c = base->abcd[2];
register unsigned int d = base->abcd[3];
int i;
unsigned int X[16];
base->length += 64;
/* Load the 64 bytes into a set of working integers, treating them as 32-bit
numbers in little-endian order. */
for (i = 0; i < 16; i++)
{
X[i] = (unsigned int)(text[0]) |
((unsigned int)(text[1]) << 8) |
((unsigned int)(text[2]) << 16) |
((unsigned int)(text[3]) << 24);
text += 4;
}
/* For each round of processing there is a function to be applied. We define it
as a macro each time round. */
/***********************************************
* Round 1 *
* F(X,Y,Z) = XY v not(X) Z *
* a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) *
***********************************************/
#define OP(a, b, c, d, k, s, ti) \
a += ((b & c) | (~b & d)) + X[k] + (unsigned int)ti; \
a = b + ((a << s) | (a >> (32 - s)))
OP(a, b, c, d, 0, 7, 0xd76aa478);
OP(d, a, b, c, 1, 12, 0xe8c7b756);
OP(c, d, a, b, 2, 17, 0x242070db);
OP(b, c, d, a, 3, 22, 0xc1bdceee);
OP(a, b, c, d, 4, 7, 0xf57c0faf);
OP(d, a, b, c, 5, 12, 0x4787c62a);
OP(c, d, a, b, 6, 17, 0xa8304613);
OP(b, c, d, a, 7, 22, 0xfd469501);
OP(a, b, c, d, 8, 7, 0x698098d8);
OP(d, a, b, c, 9, 12, 0x8b44f7af);
OP(c, d, a, b, 10, 17, 0xffff5bb1);
OP(b, c, d, a, 11, 22, 0x895cd7be);
OP(a, b, c, d, 12, 7, 0x6b901122);
OP(d, a, b, c, 13, 12, 0xfd987193);
OP(c, d, a, b, 14, 17, 0xa679438e);
OP(b, c, d, a, 15, 22, 0x49b40821);
#undef OP
/***********************************************
* Round 2 *
* F(X,Y,Z) = XZ v Y not(Z) *
* a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) *
***********************************************/
#define OP(a, b, c, d, k, s, ti) \
a += ((b & d) | (c & ~d)) + X[k] + (unsigned int)ti; \
a = b + ((a << s) | (a >> (32 - s)))
OP(a, b, c, d, 1, 5, 0xf61e2562);
OP(d, a, b, c, 6, 9, 0xc040b340);
OP(c, d, a, b, 11, 14, 0x265e5a51);
OP(b, c, d, a, 0, 20, 0xe9b6c7aa);
OP(a, b, c, d, 5, 5, 0xd62f105d);
OP(d, a, b, c, 10, 9, 0x02441453);
OP(c, d, a, b, 15, 14, 0xd8a1e681);
OP(b, c, d, a, 4, 20, 0xe7d3fbc8);
OP(a, b, c, d, 9, 5, 0x21e1cde6);
OP(d, a, b, c, 14, 9, 0xc33707d6);
OP(c, d, a, b, 3, 14, 0xf4d50d87);
OP(b, c, d, a, 8, 20, 0x455a14ed);
OP(a, b, c, d, 13, 5, 0xa9e3e905);
OP(d, a, b, c, 2, 9, 0xfcefa3f8);
OP(c, d, a, b, 7, 14, 0x676f02d9);
OP(b, c, d, a, 12, 20, 0x8d2a4c8a);
#undef OP
/***********************************************
* Round 3 *
* F(X,Y,Z) = X xor Y xor Z *
* a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) *
***********************************************/
#define OP(a, b, c, d, k, s, ti) \
a += (b ^ c ^ d) + X[k] + (unsigned int)ti; \
a = b + ((a << s) | (a >> (32 - s)))
OP(a, b, c, d, 5, 4, 0xfffa3942);
OP(d, a, b, c, 8, 11, 0x8771f681);
OP(c, d, a, b, 11, 16, 0x6d9d6122);
OP(b, c, d, a, 14, 23, 0xfde5380c);
OP(a, b, c, d, 1, 4, 0xa4beea44);
OP(d, a, b, c, 4, 11, 0x4bdecfa9);
OP(c, d, a, b, 7, 16, 0xf6bb4b60);
OP(b, c, d, a, 10, 23, 0xbebfbc70);
OP(a, b, c, d, 13, 4, 0x289b7ec6);
OP(d, a, b, c, 0, 11, 0xeaa127fa);
OP(c, d, a, b, 3, 16, 0xd4ef3085);
OP(b, c, d, a, 6, 23, 0x04881d05);
OP(a, b, c, d, 9, 4, 0xd9d4d039);
OP(d, a, b, c, 12, 11, 0xe6db99e5);
OP(c, d, a, b, 15, 16, 0x1fa27cf8);
OP(b, c, d, a, 2, 23, 0xc4ac5665);
#undef OP
/***********************************************
* Round 4 *
* F(X,Y,Z) = Y xor (X v not(Z)) *
* a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) *
***********************************************/
#define OP(a, b, c, d, k, s, ti) \
a += (c ^ (b | ~d)) + X[k] + (unsigned int)ti; \
a = b + ((a << s) | (a >> (32 - s)))
OP(a, b, c, d, 0, 6, 0xf4292244);
OP(d, a, b, c, 7, 10, 0x432aff97);
OP(c, d, a, b, 14, 15, 0xab9423a7);
OP(b, c, d, a, 5, 21, 0xfc93a039);
OP(a, b, c, d, 12, 6, 0x655b59c3);
OP(d, a, b, c, 3, 10, 0x8f0ccc92);
OP(c, d, a, b, 10, 15, 0xffeff47d);
OP(b, c, d, a, 1, 21, 0x85845dd1);
OP(a, b, c, d, 8, 6, 0x6fa87e4f);
OP(d, a, b, c, 15, 10, 0xfe2ce6e0);
OP(c, d, a, b, 6, 15, 0xa3014314);
OP(b, c, d, a, 13, 21, 0x4e0811a1);
OP(a, b, c, d, 4, 6, 0xf7537e82);
OP(d, a, b, c, 11, 10, 0xbd3af235);
OP(c, d, a, b, 2, 15, 0x2ad7d2bb);
OP(b, c, d, a, 9, 21, 0xeb86d391);
#undef OP
/* Add the new values back into the accumulators. */
base->abcd[0] += a;
base->abcd[1] += b;
base->abcd[2] += c;
base->abcd[3] += d;
}
/*************************************************
* Process the final text string *
*************************************************/
/* The string may be of any length. It is padded out according to the rules
for computing MD5 digests. The final result is then converted to text form
and returned.
Arguments:
base pointer to the md5 storage structure
text pointer to the final text vector
length length of the final text vector
digest points to 16 bytes in which to place the result
Returns: nothing
*/
void
md5_end(md5 *base, const unsigned char *text, int length, unsigned char *digest)
{
int i;
unsigned char work[64];
/* Process in chunks of 64 until we have less than 64 bytes left. */
while (length >= 64)
{
md5_mid(base, text);
text += 64;
length -= 64;
}
/* If the remaining string contains more than 55 bytes, we must pad it
out to 64, process it, and then set up the final chunk as 56 bytes of
padding. If it has less than 56 bytes, we pad it out to 56 bytes as the
final chunk. */
memcpy(work, text, length);
work[length] = 0x80;
if (length > 55)
{
memset(work+length+1, 0, 63-length);
md5_mid(base, work);
base->length -= 64;
memset(work, 0, 56);
}
else
{
memset(work+length+1, 0, 55-length);
}
/* The final 8 bytes of the final chunk are a 64-bit representation of the
length of the input string *bits*, before padding, low order word first, and
low order bytes first in each word. This implementation is designed for short
strings, and so operates with a single int counter only. */
length += base->length; /* Total length in bytes */
length <<= 3; /* Total length in bits */
work[56] = length & 0xff;
work[57] = (length >> 8) & 0xff;
work[58] = (length >> 16) & 0xff;
work[59] = (length >> 24) & 0xff;
memset(work+60, 0, 4);
/* Process the final 64-byte chunk */
md5_mid(base, work);
/* Pass back the result, low-order byte first in each word. */
for (i = 0; i < 4; i++)
{
register int x = base->abcd[i];
*digest++ = x & 0xff;
*digest++ = (x >> 8) & 0xff;
*digest++ = (x >> 16) & 0xff;
*digest++ = (x >> 24) & 0xff;
}
}
/* End of md5.c */
/*
2007.6.9 程序摘自开源项目exim-4.67的同名文件cram_md5.c. 原文件还提供了SMTP验证需要的更多代码.
参数secret应该是指公共密钥,即从服务端对Auth命令的回应,花生壳的通信验证方式采用类似SMTP的验证协议.
*/
/*************************************************
* Peform the CRAM-MD5 algorithm *
*************************************************/
/* The CRAM-MD5 algorithm is described in RFC 2195. It computes
MD5((secret XOR opad), MD5((secret XOR ipad), challenge))
where secret is padded out to 64 characters (after being reduced to an MD5
digest if longer than 64) and ipad and opad are 64-byte strings of 0x36 and
0x5c respectively, and comma means concatenation.
Arguments:
secret the shared secret
challenge the challenge text
digest 16-byte slot to put the answer in
Returns: nothing
*/
void compute_cram_md5(unsigned char *secret, unsigned char *challenge, unsigned char *digestptr)
{
md5 base;
int i;
int len = strlen(secret);
unsigned char isecret[64];
unsigned char osecret[64];
unsigned char md5secret[16];
/* If the secret is longer than 64 characters, we compute its MD5 digest
and use that. */
if (len > 64)
{
md5_start(&base);
md5_end(&base, (unsigned char *)secret, len, md5secret);
secret = (unsigned char *)md5secret;
len = 16;
}
/* The key length is now known to be <= 64. Set up the padded and xor'ed
versions. */
memcpy(isecret, secret, len);
memset(isecret+len, 0, 64-len);
memcpy(osecret, isecret, 64);
for (i = 0; i < 64; i++)
{
isecret[i] ^= 0x36;
osecret[i] ^= 0x5c;
}
/* Compute the inner MD5 digest */
md5_start(&base);
md5_mid(&base, isecret);
md5_end(&base, (unsigned char *)challenge, strlen(challenge), md5secret);
/* Compute the outer MD5 digest */
md5_start(&base);
md5_mid(&base, osecret);
md5_end(&base, md5secret, 16, digestptr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -