文章目录
MD算法家族
MD家族有很多算法,今天我们只认识一下MD5算法。MD5算法最终会产生一个128位(16字节)的散列值。
MD5Test
import static org.junit.Assert.assertArrayEquals;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.Charsets;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.util.DigestFactory;
import org.junit.Test;
/**
* MD5 算法测试
*
* @author shaozuo
* @date 2018/06/29
*/
public class MD5Test {
private static final int MD5_HASH_BYTE_LENGTH = 16;//16*8=128
private static String key = "Java加密与解密的艺术";
@Test
public void tesJdkMd5() throws NoSuchAlgorithmException {
byte[] data1 = jdkMd5(key);
byte[] data2 = jdkMd5(key);
System.out.println(Hex.encodeHexString(data1));
assertArrayEquals(data1, data2);
assertEquals(MD5_HASH_BYTE_LENGTH, data1.length);
}
@Test
public void testCodecMd5() {
byte[] data1 = codecMd5(key);
byte[] data2 = codecMd5(key);
System.out.println(Hex.encodeHexString(data1));
assertArrayEquals(data1, data2);
assertEquals(MD5_HASH_BYTE_LENGTH, data1.length);
}
@Test
public void testMd5() {
byte[] data1 = bouncyCastleMd5(key);
byte[] data2 = bouncyCastleMd5(key);
System.out.println(Hex.encodeHexString(data1));
assertArrayEquals(data1, data2);
assertEquals(MD5_HASH_BYTE_LENGTH, data1.length);
}
/**
* codec 实现MD5加密
*/
private static byte[] codecMd5(String key) {
return DigestUtils.getMd5Digest().digest(key.getBytes(Charsets.UTF_8));
}
/**
* Bouncy Castle实现MD5加密
*/
private static byte[] bouncyCastleMd5(String key) {
Digest digest = DigestFactory.createMD5();
digest.update(key.getBytes(Charsets.UTF_8), 0, key.getBytes().length);
byte[] md5Bytes = new byte[digest.getDigestSize()];
digest.doFinal(md5Bytes, 0);
return md5Bytes;
}
private static byte[] jdkMd5(String key) throws NoSuchAlgorithmException {
MessageDigest md5 = MessageDigest.getInstance("MD5");
return md5.digest(key.getBytes(Charsets.UTF_8));
}
}
SHA算法家族
与MD算法相比,SHA算法的摘要长度更长,安全性更高。
不同的消息,产生的消息摘要差异性概率更高。
SHACoder
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
/**
* SHA 算法组件
*
* @author shaozuo
* @date 2018/08/03
*/
public final class SHACoder {
private SHACoder() {
}
/**
* SHA-1 消息摘要算法 <br>
* 摘要长度 160位
*
*
* @param data
* @return
* @throws GeneralSecurityException
*/
public static byte[] encodeSHA(byte[] data) throws GeneralSecurityException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
return md.digest(data);
}
/**
* SHA-256 消息摘要算法
*
* @param data
* @return
* @throws GeneralSecurityException
*/
public static byte[] encodeSHA256(byte[] data) throws GeneralSecurityException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
return md.digest(data);
}
/**
* SHA-384 消息摘要算法
*
* @param data
* @return
* @throws GeneralSecurityException
*/
public static byte[] encodeSHA384(byte[] data) throws GeneralSecurityException {
MessageDigest md = MessageDigest.getInstance("SHA-384");
return md.digest(data);
}
/**
* SHA-512 消息摘要算法
*
* @param data
* @return
* @throws GeneralSecurityException
*/
public static byte[] encodeSHA512(byte[] data) throws GeneralSecurityException {
MessageDigest md = MessageDigest.getInstance("SHA-512");
return md.digest(data);
}
}
SHACoderTest
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.security.GeneralSecurityException;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;
public class SHACoderTest {
String input = "SHA 算法测试";
@Test
public void test() throws GeneralSecurityException {
byte[] data1 = SHACoder.encodeSHA(input.getBytes());
byte[] data2 = SHACoder.encodeSHA(input.getBytes());
System.out.println(Hex.toHexString(data1));
assertArrayEquals(data1, data2);
assertEquals(20, data1.length);
}
@Test
public void testSHA512() throws GeneralSecurityException {
byte[] data1 = SHACoder.encodeSHA512(input.getBytes());
byte[] data2 = SHACoder.encodeSHA512(input.getBytes());
System.out.println(Hex.toHexString(data1));
assertArrayEquals(data1, data2);
assertEquals(64, data1.length);
}
}
MAC算法家族
MAC(Message Authentication Code,消息认证码)是含有密钥的消息摘要算法,兼容了MD和SHA算法的特性。MD系列的算法有HmacMD2、HmacMD4和HmacMD5三种算法;SHA系列算法有HmacSHA1、HmacSHA224、HmacSHA256、HmacSHA384和HmacSHA512五种算法。MAC计算后的消息摘要长度与参与实现的算法相关。
MACCoder
只是使用HmacMD5和HmacSHA512两种,其他算法类似。
import java.security.GeneralSecurityException;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* MAC 算法组件
*
* @author shaozuo
* @date 2018/08/06
*/
public final class MACCoder {
private static final String HMAC_MD5 = "HmacMD5";
private static final String HMAC_SHA512 = "HmacSHA512";
private MACCoder() {
}
/**
* 初始化HmacMD5密钥
*
* @return
* @throws Exception
*/
public static byte[] initHmacMD5Key() throws GeneralSecurityException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(HMAC_MD5);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
}
/**
* HmacMD5 消息摘要
*
* @param data
* 待做消息摘要数据
* @param key
* 密钥
* @return byte[] 消息摘要
* @throws Exception
*/
public static byte[] encodeHmacMD5(byte[] data, byte[] key) throws GeneralSecurityException {
SecretKey secretKey = new SecretKeySpec(key, HMAC_MD5);
Mac mac = Mac.getInstance(HMAC_MD5);
mac.init(secretKey);
return mac.doFinal(data);
}
/**
* 初始化HmacSHA512密钥
*
* @return
* @throws Exception
*/
public static byte[] initHmacSHA512Key() throws GeneralSecurityException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(HMAC_SHA512);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
}
/**
* HmacSHA512 消息摘要
*
* @param data
* 待做消息摘要数据
* @param key
* 密钥
* @return byte[] 消息摘要
* @throws Exception
*/
public static byte[] encodeHmacSHA512(byte[] data, byte[] key) throws GeneralSecurityException {
SecretKey secretKey = new SecretKeySpec(key, HMAC_SHA512);
Mac mac = Mac.getInstance(HMAC_SHA512);
mac.init(secretKey);
return mac.doFinal(data);
}
}
MACCoderTest
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.security.GeneralSecurityException;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;
public class MACCoderTest {
String input = "MAC 算法测试";
@Test
public void test() throws GeneralSecurityException {
byte[] key = MACCoder.initHmacMD5Key();
byte[] data1 = MACCoder.encodeHmacMD5(input.getBytes(), key);
byte[] data2 = MACCoder.encodeHmacMD5(input.getBytes(), key);
System.out.println(Hex.toHexString(data1));
assertArrayEquals(data1, data2);
assertEquals(16, data1.length);
}
@Test
public void testMAC512() throws GeneralSecurityException {
byte[] key = MACCoder.initHmacSHA512Key();
byte[] data1 = MACCoder.encodeHmacSHA512(input.getBytes(), key);
byte[] data2 = MACCoder.encodeHmacSHA512(input.getBytes(), key);
System.out.println(Hex.toHexString(data1));
assertArrayEquals(data1, data2);
assertEquals(64, data1.length);
}
}