消息摘要算法

   博客分类: 学习笔记 文章类型: 原创

消息摘要算法

本文字数为 5075 字, 预计读完大约需要 15 分钟

消息摘要算法

这里介绍了三种消息摘要算法(MD、SHA、MAC),以及他们的使用方法(包括JDK,Commons Codec和Bouncy Castle的三种使用方法)

[TOC]

消息摘要算法:

验证数据的完整性 数字签名核心算法

消息摘要算法–MD

算法 摘要长度 实现方
MD2 128 JDK
MD4 128 Bouncy Castle(JDK没有提供实现)
MD5 128 JDK

MD算法应用

用户注册 –> 对密码进行摘要处理 –> 存到数据库 –> (用户名明文,密码摘要处理)

###例子程序

要进行加密的字符串

String src = "I'm Learing MD"

JDK

/**
 * jdk实现MD5加密
 * 实现MD2加密只需要将getInstance("MD5")改为getInstance("MD2")即可
 */
public static void jdkMD5() {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] md5Bytes = md.digest(src.getBytes());//通过digest进行加密
        //需要将byte数组转换成16进制
        System.out.println("JDK Md5:"+ Hex.encodeHexString(md5Bytes));
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

Bouncy Castle

/**
 * bc实现MD4加密
 * 实现MD5加密只需要将
 * Digest digest = new MD4Digest()改为
 * Digest digest = new MD5Digest()即可
 */
public static void bcMD4() {
    Digest digest = new MD4Digest();
    digest.update(src.getBytes(), 0, src.getBytes().length);
    byte[] md4Bytes = new byte[digest.getDigestSize()];
    digest.doFinal(md4Bytes, 0);
    //将bytes数组转换为16进制
    System.out.println("bcMD4:" + org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
}

利用jdk提供的addProvider方法来为jdk动态添加MD4的实现

/**
 * 利用JDK提供的addProvider方法为JDK提供MD4算法
 * 为JDK动态添加bc的Provider
 */
public static void bcMD4FromProvider() {
    Security.addProvider(new BouncyCastleProvider());//添加Provider,来支持算法
    try {
        MessageDigest md = MessageDigest.getInstance("MD4");//这时候就可以使用MD4了
        byte[] md4Bytes = md.digest(src.getBytes());//通过digest进行加密
        //需要将byte数组转换成16进制
        System.out.println("bc Md4:"+ org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

Commons Codec

/**
 * cc实现MD5加密
 * cc其实还是利用了JDK来实现的加密,只是简化了操作,因此它也没有提供MD4的加密算法
 */
public static void ccMD5() {
    byte[] md5Bytes = DigestUtils.getMd5Digest().digest(src.getBytes());
    System.out.println("cc MD5:" + Hex.encodeHexString(md5Bytes));
}

消息摘要算法–SHA(安全散列算法)

算法 摘要长度 实现方
SHA-1 160 JDK
SHA-224 224 Bouncy Castle
SHA-256 256 JDK
SHA-384 384 JDK
SHA-512 512 JDK

SHA应用:

浏览器–>设置–>证书–>指纹就是使用SHA进行加密的 发送方–> 公布消息摘要算法 –> 对待发布的消息进行摘要处理 –> 发布摘要消息 –> 发送消息 –> 接收方 –> 消息鉴别

例子程序:

要进行加密的字符串

final String src = "I'm Learning SHA";

jdk

/**
 * JDK 实现SHA1加密
 * 例如:利用JDK实现SHA-384进行加密就是
 * MessageDigest.getInstance("SHA-384");
 */
void jdkSHA1() {
    MessageDigest digest = MessageDigest.getInstance("SHA");
    digest.update(src.getBytes());
    byte[] sha1Bytes = digest.digest();
    String sha1Str = Hex.encodeHexString(sha1Bytes);
    System.out.println("JDKSHA1Str:" + sha1Str);

}

Bouncy Castle

/**
 * 利用bc实现SHA1加密
 * 例如:实现SHA-512加密就是new SHA512Digest();
 */
void bcSHA1() {
    Digest digest = new SHA1Digest();
    digest.update(src.getBytes(), 0, src.getBytes().length);
    byte[] sha1Bytes = new byte[digest.getDigestSize()];
    digest.doFinal(sha1Bytes,0);
    System.out.println("bcSHA1Str:" + org.bouncycastle.util.encoders.Hex.toHexString(sha1Bytes));
}

利用jdk提供的addProvider为jdk动态添加SHA224的实现

/**
 * 因为jdk没有提供SHA224的实现因此我们可以 通过addProvider为JDK添加SHA224的实现
 */
public static void jdkSHA224FromBC() {
    Security.addProvider(new BouncyCastleProvider());
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-224");
        byte[] sha224Bytes = digest.digest(src.getBytes());
        String sha224Str = Hex.encodeHexString(sha224Bytes);
        System.out.println("jdkSHA224FromBCStr:" + sha224Str);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

Commons Codec

/**
 * 利用cc进行sha1加密
 */
public static void ccSHA1() {
    System.out.println("ccSHA1Str:" + DigestUtils.sha1Hex(src.getBytes()));
    System.out.println("ccSHA1Str:" + DigestUtils.sha1Hex(src));
}

消息摘要算法–MAC

实现

|算法 | 摘要长度 | 实现方| |—-|————–|——–| |HmacMD2| 128 | Bouncy Castle| |HmacMD4| 128 | Bouncy Castle| |HmacMD5| 128 | JDK| |HmacSHA1| 160 | JDK| |HmacSHA224| 224 | Bouncy Castle| |HmacSHA256| 256 | JDK| |HmacSHA384| 384 | JDK| |HmacSHA512| 512 | JDK|

应用:

**发送方 –> 公布消息摘要算法 –> 构建密钥 –> 发送密钥 –> 对待发送的消息进行摘要处理 –> 发送消息摘要 –> 发送消息 –> 接收方 –> 消息鉴别 **

例子

要进行加密的字符串

String src = "I'm Learning MAC";

Bouncy Castle

/**
 * bc实现HMacMD5加密
 */
public static void bcHmacMD5() {
    HMac hmac = new HMac(new MD5Digest());
    hmac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex.decode("aaaaaaaaaa")));//密钥
    hmac.update(src.getBytes(), 0, src.getBytes().length);

    byte[] hmacBytes = new byte[hmac.getMacSize()];
    hmac.doFinal(hmacBytes, 0);
    System.out.println("bcHmacMD4Str:" + org.bouncycastle.util.encoders.Hex.toHexString(hmacBytes));
}

jdk

/**
 * jdk实现Hmac算法
 */
public static void jdkHmacMD5() {
    try {
//			KeyGenerator generator = KeyGenerator.getInstance("HmacMD5");//初始化KeyGrnerator
//			SecretKey generateKey = generator.generateKey();//产生密钥
//			byte[] key = generateKey.getEncoded();//获得密钥

        byte[] key = null;//密钥
        try {
            key = Hex.decodeHex(new char[]{'a','a','a','a','a','a','a','a','a','a'});
        } catch (DecoderException e) {
            e.printStackTrace();
        }

        //还原密钥:
        SecretKey restoreSecreKt = new SecretKeySpec(key, "HmacMD5");
        Mac mac = Mac.getInstance(restoreSecreKt.getAlgorithm());
        //初始化mac
        mac.init(restoreSecreKt);
        byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());//执行摘要
        System.out.println("jdkHmacMd5Str:" + Hex.encodeHexString(hmacMD5Bytes));

    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
        e.printStackTrace();
    }
}

其他的一些消息摘要算法: