我是 Web 开发的新手,目前,我在构建登录页面时遇到了困难。
我写了一个 PHP 脚本,在输入时获取用户名和密码。然后将密码作为参数发送到我编写的 C 程序,该程序只是对密码 (MD5) 进行哈希处理。这是使用以下代码完成的:
$username = $_POST['uname'];
$password = $_POST['passwd'];
$hashvalue = shell_exec("md5.exe $password");
现在,当我在登录表单中输入密码 1234 时,我得到的输出是 f7d4cef3bfacebfc49d5574e7d9c1d6f
但是,当我在单独运行 C 程序时使用 1234 作为输入时,我得到了不同的输出 81dc9bdb52d04dc20036dbd8313ed055。这也是我实际应该得到的输出。当我检查各种在线 MD5 散列程序时,它们给出了相同的输出。
在C 程序中,我使用gets()
获取输入并使用printf
显示输出。另外,我使用了 MySQL 数据库 (phpMyAdmin)。
C程序代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
typedef union uwb {
unsigned w;
unsigned char b[4];
} MD5union;
typedef unsigned DigestArray[4];
unsigned func0( unsigned abcd[] ){
return ( abcd[1] & abcd[2]) | (~abcd[1] & abcd[3]);}
unsigned func1( unsigned abcd[] ){
return ( abcd[3] & abcd[1]) | (~abcd[3] & abcd[2]);}
unsigned func2( unsigned abcd[] ){
return abcd[1] ^ abcd[2] ^ abcd[3];}
unsigned func3( unsigned abcd[] ){
return abcd[2] ^ (abcd[1] |~ abcd[3]);}
typedef unsigned (*DgstFctn)(unsigned a[]);
unsigned *calctable( unsigned *k)
{
double s, pwr;
int i;
pwr = pow( 2, 32);
for (i=0; i<64; i++) {
s = fabs(sin(1+i));
k[i] = (unsigned)( s * pwr );
}
return k;
}
unsigned rol( unsigned r, short N )
{
unsigned mask1 = (1<<N) -1;
return ((r>>(32-N)) & mask1) | ((r<<N) & ~mask1);
}
unsigned *md5( const char *msg, int mlen)
{
/*Initialize Digest Array as A , B, C, D */
static DigestArray h0 = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 };
static DgstFctn ff[] = { &func0, &func1, &func2, &func3 };
static short M[] = { 1, 5, 3, 7 };
static short O[] = { 0, 1, 5, 0 };
static short rot0[] = { 7,12,17,22};
static short rot1[] = { 5, 9,14,20};
static short rot2[] = { 4,11,16,23};
static short rot3[] = { 6,10,15,21};
static short *rots[] = {rot0, rot1, rot2, rot3 };
static unsigned kspace[64];
static unsigned *k;
static DigestArray h;
DigestArray abcd;
DgstFctn fctn;
short m, o, g;
unsigned f;
short *rotn;
union {
unsigned w[16];
char b[64];
}mm;
int os = 0;
int grp, grps, q, p;
unsigned char *msg2;
if (k==NULL) k= calctable(kspace);
for (q=0; q<4; q++) h[q] = h0[q]; // initialize
{
grps = 1 + (mlen+8)/64;
msg2 = malloc( 64*grps);
memcpy( msg2, msg, mlen);
msg2[mlen] = (unsigned char)0x80;
q = mlen + 1;
while (q < 64*grps){ msg2[q] = 0; q++ ; }
{
MD5union u;
u.w = 8*mlen;
q -= 8;
memcpy(msg2+q, &u.w, 4 );
}
}
for (grp=0; grp<grps; grp++)
{
memcpy( mm.b, msg2+os, 64);
for(q=0;q<4;q++) abcd[q] = h[q];
for (p = 0; p<4; p++) {
fctn = ff[p];
rotn = rots[p];
m = M[p]; o= O[p];
for (q=0; q<16; q++) {
g = (m*q + o) % 16;
f = abcd[1] + rol( abcd[0]+ fctn(abcd) + k[q+16*p] + mm.w[g], rotn[q%4]);
abcd[0] = abcd[3];
abcd[3] = abcd[2];
abcd[2] = abcd[1];
abcd[1] = f;
}
}
for (p=0; p<4; p++)
h[p] += abcd[p];
os += 64;
}
return h;
}
int main( int argc, char *argv[] )
{
int j,k;
char msg[500];
gets(msg);
unsigned *d = md5(msg, strlen(msg));
MD5union u;
for (j=0;j<4; j++){
u.w = d[j];
for (k=0;k<4;k++)
printf("%02x",u.b[k]);
}
return 0;
}
我做错了什么?
我读过许多内置函数,如 bcrypt、scrypt 等。但这只是为了练习目的,因此想使用我自己的代码。
谢谢
最佳答案
在您的 C 程序中,假设它是 MD5 正确散列输入字符串,那么它实际上可能没问题。
问题可能根本不是问题,您的 MD5 哈希值在两个过程中都是正确的。 (尽管它们看起来完全不同,但它们可以“保持”相同的值“1234”
)只是堆栈的内容不同从一个实例到另一个实例,并且您的一些字符串在 null 之后来自堆栈。
发生的事情是,在一个实例中,C 函数正在散列这个字符串
'1234__________________'
(其中 _ 是空值或\0 字符
并且另一个实例正在散列这个字符串
'1234_some_random_values'
。
两个字符串都包含 1234
和 null
字符,但 null 之后的字符不同。
尝试用所有空值预填充您的临时字符串,然后复制您的密码,以便您确定字符串缓冲区的其余部分在 MD5 哈希之前为“空”。
(如果你想验证我是正确的,你可以通过 unMD5 散列来确认这一点。从维基百科,你可以看到散列算法采用数据“ block ”并且不关心 NULL 字符在哪里:
MD5 processes a variable-length message into a fixed-length output of 128 bits. The input message is broken up into chunks of 512-bit blocks (sixteen 32-bit words); the message is padded so that its length is divisible by 512.
从这里https://en.wikipedia.org/wiki/MD5 同样根据此解释,如果您的密码长度恰好是(16 个 32 位字)4 倍 16 = 64 个字符长,那么无论空字符之后的字符数组中的内容如何,MD5 哈希值都应该相同,因为算法将不要在 64 字符边界之后寻找更多字符。 )
尝试添加
memset(msg,0,500);
在您的获取
之前。
(我无视所有安全问题:))
关于php - 使用 shell_exec() 从 PHP 脚本调用 C 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47083781/