Java加解密-MD算法
消息摘要算法加密
消息摘要算法主要分为3类:MD(Message Digest)、SHA(Secure Hash Algorithm)、MAC(Message Authentication Code),以上3类算法的主要作用是验证数据的完整性——是数字签名的核心算法。
消息摘要算法——MD
MD算法家族有3类MD2、MD4、MD5,MD家族生成的都是128位的信息摘要。
算法 | 摘要长度 | 实现方 |
MD2 | 128 | JDK |
MD4 | 128 | Bouncy Castle |
MD5 | 128 | JDK |
信息摘要算法由于使用的是一种单向函数,所以理论上是不可破解的(山东大学的王晓云教授已经破解了MD5和SHA,所以消息摘要是可以伪造的,只不过难度比较大)。所有MD算法进行摘要的结果都是128为位(32位16进制的数字,因为1位16进制数代表4位二进制数)。
JDK本身提供了MD2和MD5的实现,apache的Commons Codec在JDK的基础上进行了改良,使用Commons Codec提供接口进行MD2和MD5加密将会简单很多。JDK本省并没有提供MD4算法的实现,但是我们可以通过动态添加provider的方式让jdk支持MD4
Bouncy Castle提供了MD2、MD4和MD5的实现,对消息摘要算法的支持比较完善,但是API还是没有Apache的Commons Codec友善。因此,如果我们要进行MD2和MD4实现,最好选用Commons Codec。
MD算法的应用
注册时:
应用程序服务器将用户提交的密码进行MD5即:数据库中存放的用户名是明文,而密码是密文(16进制字符串)摘要算法,得到32位的16进制字符串(密文)。把用户名(明文)和密码(密文)进行信息持久化存储到数据库中,返回注册结果。
登录时:
应用程序服务器同样对密码进行MD5摘要,然后将用户提交的用户名和密码的摘要信息和数据库中存储的信息进行比对,返回登录结果。
============================================================================MD加密工具类:
import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Security; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.MD2Digest; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class SecurityMd { /** * MD5加密,方式1 * @param pwd * @return */ public static String commonsCodecMd5(String pwd) { return DigestUtils.md5Hex(pwd.getBytes()); } public static String commonsCodecMd2(String pwd) { return DigestUtils.md2Hex(pwd.getBytes()); } /** * MD5加密,方式2 * * @param pwd * @return */ public static String jdkMd5(String pwd) { byte[] message = null; message = pwd.getBytes(); MessageDigest md = null; try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] encrypwd = md.digest(message); String md5code = new BigInteger(1, encrypwd).toString(16); for (int i = 0; i < 32 - md5code.length(); i++) { md5code = "0" + md5code; } return md5code; } public static String jdkMd2(String pwd) { byte[] message = null; message = pwd.getBytes(); MessageDigest md = null; try { md = MessageDigest.getInstance("md2"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] encrypwd = md.digest(message); String md5code = Hex.encodeHexString(encrypwd); for (int i = 0; i < 32 - md5code.length(); i++) { md5code = "0" + md5code; } return md5code; } /** * Bouncy Castle实现MD4加密 */ public static String bouncyCastleMD4(String src) { /*通过这种方式给JDK动态添加一个provider,就可以通过这种方式获得JDK本身不支持的MD4了*/ Security.addProvider(new BouncyCastleProvider()); MessageDigest md = null; try { md = MessageDigest.getInstance("md4"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] md4Bytes = md.digest(src.getBytes()); return new String(org.bouncycastle.util.encoders.Hex.encode(md4Bytes)); } /** * Bouncy Castle实现MD5加密 */ public static String bouncyCastleMD5(String src){ Digest digest = new MD5Digest(); digest.update(src.getBytes(), 0, src.getBytes().length); byte[]md5Bytes = new byte[digest.getDigestSize()]; digest.doFinal(md5Bytes, 0); return new String(org.bouncycastle.util.encoders.Hex.encode(md5Bytes)); } /** * Bouncy Castle实现MD2加密 */ public static String bouncyCastleMD2(String src){ Digest digest = new MD2Digest(); digest.update(src.getBytes(), 0, src.getBytes().length); byte[]md2Bytes = new byte[digest.getDigestSize()]; digest.doFinal(md2Bytes, 0); return new String(org.bouncycastle.util.encoders.Hex.encode(md2Bytes)); } /** * 可逆的加密算法 * @param inStr * @return */ public static String KL(String inStr) { char[] a = inStr.toCharArray(); for (int i = 0; i < a.length; i++) { a[i] = (char) (a[i] ^ 't'); } String s = new String(a); return s; } /** * 加密后解密 * @param inStr * @return */ public static String JM(String inStr) { char[] a = inStr.toCharArray(); for (int i = 0; i < a.length; i++) { a[i] = (char) (a[i] ^ 't'); } String k = new String(a); return k; } }
============================================================================MD加密工具测试类:
/** * MD5加密,且无法解密 */ @Test public void test_md() { String inStr = "000000"; System.out.println("原始字符串:"+inStr); System.out.println("MD2加密:" + SecurityMd.jdkMd2(inStr)); System.out.println("MD2加密:" + SecurityMd.commonsCodecMd2(inStr)); System.out.println("MD2加密:" + SecurityMd.bouncyCastleMD2(inStr)); //670b14728ad9902aecba32e22fa4f6bd 32位 System.out.println("MD4加密:" + SecurityMd.bouncyCastleMD4(inStr)); //bf85aaf547303397450fbc8ede0ec3a5 32位 System.out.println("MD5加密:" + SecurityMd.jdkMd5(inStr)); System.out.println("MD5加密:" + SecurityMd.commonsCodecMd5(inStr)); System.out.println("MD5加密:" + SecurityMd.bouncyCastleMD5(inStr)); //670b14728ad9902aecba32e22fa4f6bd 32位 String encrypMode = SecurityMd.jdkMd5(inStr); System.out.println("MD5后再加密:" + SecurityMd.KL(encrypMode)); System.out.println("解密为MD5后的:" + SecurityMd.JM(SecurityMd.KL(encrypMode))); }