在JSP中如何实现MD5加密的方法
在各种应用系统的开发中,经常需要存储用户信息,很多地方都要存储用户密码,而将用户密码直接存储在服务器上显然是不安全的,本文简要介绍在JSP中如何实现MD5加密的方法,希望能抛砖引玉。
(一)消息摘要简介
一个消息摘要就是一个数据块的数字指纹。即对一个任意长度的一个数据块进行计算,产生一个唯一指印(对于SHA1是产生一个20字节的二进制数组)。消息摘要是一种与消息认证码结合使用以确保消息完整性的技术。主要使用单向散列函数算法,可用于检验消息的完整性,和通过散列密码直接以文本形式保存等,目前广泛使用的算法有MD4、MD5、SHA-1。
消息摘要有两个基本属性:
两个不同的报文难以生成相同的摘要
难以对指定的摘要生成一个报文,而可以由该报文反推算出该指定的摘要。
Java源码
importjava.security.MessageDigest; importjava.security.NoSuchAlgorithmException; publicclassMD5Digest { privateMessageDigest__md5=null; privateStringBuffer__digestBuffer=null; publicMD5Digest() throwsNoSuchAlgorithmException { __md5=MessageDigest.getInstance("MD5"); __digestBuffer=newStringBuffer(); } publicStringmd5crypt(Strings) { __digestBuffer.setLength(0); byteabyte0[]=__md5.digest(s.getBytes()); for(inti=0;i<abyte0.length;i++) __digestBuffer.append(toHex(abyte0[i])); return__digestBuffer.toString(); } publicStringtoHex(byteone){ StringHEX="0123456789ABCDEF"; char[]result=newchar[2]; result[0]=HEX.charAt((one&0xf0)>>4); result[1]=HEX.charAt(one&0x0f); Stringmm=newString(result); returnmm; } }
-------------------------------------------------------------------------------
/************************************************ MD5算法的JavaBean @author:TopcatTuppin LastModified:10,Mar,2001 *************************************************/ packagebeartool; importjava.lang.reflect.*; /************************************************* md5类实现了RSADataSecurity,Inc.在提交给IETF 的RFC1321中的MD5message-digest算法。 *************************************************/ publicclassMD5{ /*下面这些S11-S44实际上是一个4*4的矩阵,在原始的C实现中是用#define实现的, 这里把它们实现成为staticfinal是表示了只读,切能在同一个进程空间内的多个 Instance间共享*/ staticfinalintS11=7; staticfinalintS12=12; staticfinalintS13=17; staticfinalintS14=22; staticfinalintS21=5; staticfinalintS22=9; staticfinalintS23=14; staticfinalintS24=20; staticfinalintS31=4; staticfinalintS32=11; staticfinalintS33=16; staticfinalintS34=23; staticfinalintS41=6; staticfinalintS42=10; staticfinalintS43=15; staticfinalintS44=21; staticfinalbyte[]PADDING={-128,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /*下面的三个成员是MD5计算过程中用到的3个核心数据,在原始的C实现中 被定义到MD5_CTX结构中 */ privatelong[]state=newlong[4];//state(ABCD) privatelong[]count=newlong[2];//numberofbits,modulo2^64(lsbfirst) privatebyte[]buffer=newbyte[64];//inputbuffer /*digestHexStr是MD5的唯一一个公共成员,是最新一次计算结果的 16进制ASCII表示. */ publicStringdigestHexStr; /*digest,是最新一次计算结果的2进制内部表示,表示128bit的MD5值. */ privatebyte[]digest=newbyte[16]; /* getMD5ofStr是类MD5最主要的公共方法,入口参数是你想要进行MD5变换的字符串 返回的是变换完的结果,这个结果是从公共成员digestHexStr取得的. */ publicStringgetMD5ofStr(Stringinbuf){ md5Init(); md5Update(inbuf.getBytes(),inbuf.length()); md5Final(); digestHexStr=""; for(inti=0;i<16;i++){ digestHexStr+=byteHEX(digest[i]); } returndigestHexStr; } //这是MD5这个类的标准构造函数,JavaBean要求有一个public的并且没有参数的构造函数 publicMD5(){ md5Init(); return; } /*md5Init是一个初始化函数,初始化核心变量,装入标准的幻数*/ privatevoidmd5Init(){ count[0]=0L; count[1]=0L; ///*Loadmagicinitializationconstants. state[0]=0x67452301L; state[1]=0xefcdab89L; state[2]=0x98badcfeL; state[3]=0x10325476L; return; } /*F,G,H,I是4个基本的MD5函数,在原始的MD5的C实现中,由于它们是 简单的位运算,可能出于效率的考虑把它们实现成了宏,在java中,我们把它们 实现成了private方法,名字保持了原来C中的。*/ privatelongF(longx,longy,longz){ return(x&y)|((~x)&z); } privatelongG(longx,longy,longz){ return(x&z)|(y&(~z)); } privatelongH(longx,longy,longz){ returnx^y^z; } privatelongI(longx,longy,longz){ returny^(x|(~z)); } /* FF,GG,HH和II将调用F,G,H,I进行近一步变换 FF,GG,HH,andIItransformationsforrounds1,2,3,and4. Rotationisseparatefromadditiontopreventrecomputation. */ privatelongFF(longa,longb,longc,longd,longx,longs, longac){ a+=F(b,c,d)+x+ac; a=((int)a<<s)|((int)a>>>(32-s)); a+=b; returna; } privatelongGG(longa,longb,longc,longd,longx,longs, longac){ a+=G(b,c,d)+x+ac; a=((int)a<<s)|((int)a>>>(32-s)); a+=b; returna; } privatelongHH(longa,longb,longc,longd,longx,longs, longac){ a+=H(b,c,d)+x+ac; a=((int)a<<s)|((int)a>>>(32-s)); a+=b; returna; } privatelongII(longa,longb,longc,longd,longx,longs, longac){ a+=I(b,c,d)+x+ac; a=((int)a<<s)|((int)a>>>(32-s)); a+=b; returna; } /* md5Update是MD5的主计算过程,inbuf是要变换的字节串,inputlen是长度,这个 函数由getMD5ofStr调用,调用之前需要调用md5init,因此把它设计成private的 */ privatevoidmd5Update(byte[]inbuf,intinputLen){ inti,index,partLen; byte[]block=newbyte[64]; index=(int)(count[0]>>>3)&0x3F; ///*Updatenumberofbits*/ if((count[0]+=(inputLen<<3))<(inputLen<<3)) count[1]++; count[1]+=(inputLen>>>29); partLen=64-index; //Transformasmanytimesaspossible. if(inputLen>=partLen){ md5Memcpy(buffer,inbuf,index,0,partLen); md5Transform(buffer); for(i=partLen;i+63<inputLen;i+=64){ md5Memcpy(block,inbuf,0,i,64); md5Transform(block); } index=0; }else i=0; ///*Bufferremaininginput*/ md5Memcpy(buffer,inbuf,index,i,inputLen-i); } /* md5Final整理和填写输出结果 */ privatevoidmd5Final(){ byte[]bits=newbyte[8]; intindex,padLen; ///*Savenumberofbits*/ Encode(bits,count,8); ///*Padoutto56mod64. index=(int)(count[0]>>>3)&0x3f; padLen=(index<56)?(56-index):(120-index); md5Update(PADDING,padLen); ///*Appendlength(beforepadding)*/ md5Update(bits,8); ///*Storestateindigest*/ Encode(digest,state,16); } /*md5Memcpy是一个内部使用的byte数组的块拷贝函数,从input的inpos开始把len长度的 字节拷贝到output的outpos位置开始 */ privatevoidmd5Memcpy(byte[]output,byte[]input, intoutpos,intinpos,intlen) { inti; for(i=0;i<len;i++) output[outpos+i]=input[inpos+i]; } /* md5Transform是MD5核心变换程序,有md5Update调用,block是分块的原始字节 */ privatevoidmd5Transform(byteblock[]){ longa=state[0],b=state[1],c=state[2],d=state[3]; long[]x=newlong[16]; Decode(x,block,64); /*Round1*/ a=FF(a,b,c,d,x[0],S11,0xd76aa478L);/*1*/ d=FF(d,a,b,c,x[1],S12,0xe8c7b756L);/*2*/ c=FF(c,d,a,b,x[2],S13,0x242070dbL);/*3*/ b=FF(b,c,d,a,x[3],S14,0xc1bdceeeL);/*4*/ a=FF(a,b,c,d,x[4],S11,0xf57c0fafL);/*5*/ d=FF(d,a,b,c,x[5],S12,0x4787c62aL);/*6*/ c=FF(c,d,a,b,x[6],S13,0xa8304613L);/*7*/ b=FF(b,c,d,a,x[7],S14,0xfd469501L);/*8*/ a=FF(a,b,c,d,x[8],S11,0x698098d8L);/*9*/ d=FF(d,a,b,c,x[9],S12,0x8b44f7afL);/*10*/ c=FF(c,d,a,b,x[10],S13,0xffff5bb1L);/*11*/ b=FF(b,c,d,a,x[11],S14,0x895cd7beL);/*12*/ a=FF(a,b,c,d,x[12],S11,0x6b901122L);/*13*/ d=FF(d,a,b,c,x[13],S12,0xfd987193L);/*14*/ c=FF(c,d,a,b,x[14],S13,0xa679438eL);/*15*/ b=FF(b,c,d,a,x[15],S14,0x49b40821L);/*16*/ /*Round2*/ a=GG(a,b,c,d,x[1],S21,0xf61e2562L);/*17*/ d=GG(d,a,b,c,x[6],S22,0xc040b340L);/*18*/ c=GG(c,d,a,b,x[11],S23,0x265e5a51L);/*19*/ b=GG(b,c,d,a,x[0],S24,0xe9b6c7aaL);/*20*/ a=GG(a,b,c,d,x[5],S21,0xd62f105dL);/*21*/ d=GG(d,a,b,c,x[10],S22,0x2441453L);/*22*/ c=GG(c,d,a,b,x[15],S23,0xd8a1e681L);/*23*/ b=GG(b,c,d,a,x[4],S24,0xe7d3fbc8L);/*24*/ a=GG(a,b,c,d,x[9],S21,0x21e1cde6L);/*25*/ d=GG(d,a,b,c,x[14],S22,0xc33707d6L);/*26*/ c=GG(c,d,a,b,x[3],S23,0xf4d50d87L);/*27*/ b=GG(b,c,d,a,x[8],S24,0x455a14edL);/*28*/ a=GG(a,b,c,d,x[13],S21,0xa9e3e905L);/*29*/ d=GG(d,a,b,c,x[2],S22,0xfcefa3f8L);/*30*/ c=GG(c,d,a,b,x[7],S23,0x676f02d9L);/*31*/ b=GG(b,c,d,a,x[12],S24,0x8d2a4c8aL);/*32*/ /*Round3*/ a=HH(a,b,c,d,x[5],S31,0xfffa3942L);/*33*/ d=HH(d,a,b,c,x[8],S32,0x8771f681L);/*34*/ c=HH(c,d,a,b,x[11],S33,0x6d9d6122L);/*35*/ b=HH(b,c,d,a,x[14],S34,0xfde5380cL);/*36*/ a=HH(a,b,c,d,x[1],S31,0xa4beea44L);/*37*/ d=HH(d,a,b,c,x[4],S32,0x4bdecfa9L);/*38*/ c=HH(c,d,a,b,x[7],S33,0xf6bb4b60L);/*39*/ b=HH(b,c,d,a,x[10],S34,0xbebfbc70L);/*40*/ a=HH(a,b,c,d,x[13],S31,0x289b7ec6L);/*41*/ d=HH(d,a,b,c,x[0],S32,0xeaa127faL);/*42*/ c=HH(c,d,a,b,x[3],S33,0xd4ef3085L);/*43*/ b=HH(b,c,d,a,x[6],S34,0x4881d05L);/*44*/ a=HH(a,b,c,d,x[9],S31,0xd9d4d039L);/*45*/ d=HH(d,a,b,c,x[12],S32,0xe6db99e5L);/*46*/ c=HH(c,d,a,b,x[15],S33,0x1fa27cf8L);/*47*/ b=HH(b,c,d,a,x[2],S34,0xc4ac5665L);/*48*/ /*Round4*/ a=II(a,b,c,d,x[0],S41,0xf4292244L);/*49*/ d=II(d,a,b,c,x[7],S42,0x432aff97L);/*50*/ c=II(c,d,a,b,x[14],S43,0xab9423a7L);/*51*/ b=II(b,c,d,a,x[5],S44,0xfc93a039L);/*52*/ a=II(a,b,c,d,x[12],S41,0x655b59c3L);/*53*/ d=II(d,a,b,c,x[3],S42,0x8f0ccc92L);/*54*/ c=II(c,d,a,b,x[10],S43,0xffeff47dL);/*55*/ b=II(b,c,d,a,x[1],S44,0x85845dd1L);/*56*/ a=II(a,b,c,d,x[8],S41,0x6fa87e4fL);/*57*/ d=II(d,a,b,c,x[15],S42,0xfe2ce6e0L);/*58*/ c=II(c,d,a,b,x[6],S43,0xa3014314L);/*59*/ b=II(b,c,d,a,x[13],S44,0x4e0811a1L);/*60*/ a=II(a,b,c,d,x[4],S41,0xf7537e82L);/*61*/ d=II(d,a,b,c,x[11],S42,0xbd3af235L);/*62*/ c=II(c,d,a,b,x[2],S43,0x2ad7d2bbL);/*63*/ b=II(b,c,d,a,x[9],S44,0xeb86d391L);/*64*/ state[0]+=a; state[1]+=b; state[2]+=c; state[3]+=d; } /*Encode把long数组按顺序拆成byte数组,因为java的long类型是64bit的, 只拆低32bit,以适应原始C实现的用途 */ privatevoidEncode(byte[]output,long[]input,intlen){ inti,j; for(i=0,j=0;j<len;i++,j+=4){ output[j]=(byte)(input[i]&0xffL); output[j+1]=(byte)((input[i]>>>8)&0xffL); output[j+2]=(byte)((input[i]>>>16)&0xffL); output[j+3]=(byte)((input[i]>>>24)&0xffL); } } /*Decode把byte数组按顺序合成成long数组,因为java的long类型是64bit的, 只合成低32bit,高32bit清零,以适应原始C实现的用途 */ privatevoidDecode(long[]output,byte[]input,intlen){ inti,j; for(i=0,j=0;j<len;i++,j+=4) output[i]=b2iu(input[j])| (b2iu(input[j+1])<<8)| (b2iu(input[j+2])<<16)| (b2iu(input[j+3])<<24); return; } /* b2iu是我写的一个把byte按照不考虑正负号的原则的"升位"程序,因为java没有unsigned运算 */ publicstaticlongb2iu(byteb){ returnb<0?b&0x7F+128:b; } /*byteHEX(),用来把一个byte类型的数转换成十六进制的ASCII表示, 因为java中的byte的toString无法实现这一点,我们又没有C语言中的 sprintf(outbuf,"%02X",ib) */ publicstaticStringbyteHEX(byteib){ char[]Digit={'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F'}; char[]ob=newchar[2]; ob[0]=Digit[(ib>>>4)&0X0F]; ob[1]=Digit[ib&0X0F]; Strings=newString(ob); returns; } publicstaticvoidmain(Stringargs[]){ MD5m=newMD5(); if(Array.getLength(args)==0){//如果没有参数,执行标准的TestSuite System.out.println("MD5Testsuite:"); System.out.println("MD5(\"\"):"+m.getMD5ofStr("")); System.out.println("MD5(\"a\"):"+m.getMD5ofStr("a")); System.out.println("MD5(\"abc\"):"+m.getMD5ofStr("abc")); System.out.println("MD5(\"messagedigest\"):"+m.getMD5ofStr("messagedigest")); System.out.println("MD5(\"abcdefghijklmnopqrstuvwxyz\"):"+ m.getMD5ofStr("abcdefghijklmnopqrstuvwxyz")); System.out.println("MD5(\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"):"+ m.getMD5ofStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")); } else System.out.println("MD5("+args[0]+")="+m.getMD5ofStr(args[0])); } }
JSP中的使用方法
-------------------------------------------------------------------------------
<%@pagelanguage='java'%> <jsp:useBeanid='oMD5'scope='request'class='beartool.MD5'/> <%@pageimport='java.util.*'%> <%@pageimport='java.sql.*'%> <html> <body> <% Stringuserid=request.getParameter("UserID");//获取用户输入UserID Stringpassword=request.getParameter("Password");//获取用户输入的Password Stringpwdmd5=oMD5.getMD5ofStr(password);//计算MD5的值 PrintWriterrp=response.getWriter(); Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connectioncon=DriverManager.getConnection("jdbc:odbc:community","",""); Statementstmt=con.createStatement(); ResultSetrs=stmt.executeQuery("select*fromuserswhereuserID='"+userid+"'andpwdmd5='"+pwdmd5+"'"); if(rs.next()) { rp.print("LoginOK"); } else { rp.print("LoginFail"); } stmt.close(); con.close(); %> </body> </html>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。