MD5、SHA、HMAC这三种加密算法,是非可逆加密,就是不可解密的加密方法。我们通常只把他们作为加密的基础。单纯的以上三种的加密并不可靠。
MD5
MD5 -- message-digest algorithm 5 (信息-摘要算法)缩写,广泛用于加密和解密技术,常用于文件校验。校验?不管文件多大,经过MD5后都能生成唯一的MD5值。好比现在的ISO校验,都是MD5校验。怎么用?当然是把ISO经过MD5后产生MD5的值。一般下载linux-ISO的朋友都见过下载链接旁边放着MD5的串。就是用来验证文 件是否一致的。
Java实现代码jdk版本的
import sun.misc.BASE64Encoder; import java.security.MessageDigest; public class Test { public static void main(String[] args) throws Exception{ encryptMD5("HELLO".getBytes()); System.out.println(new BASE64Encoder().encode(encryptMD5("HELLO".getBytes()))); } public static byte[] encryptMD5(byte[] data) throws Exception { MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(data); return md5.digest(); } }
通常我们不直接使用上述MD5加密。通常将MD5产生的字节数组交给BASE64再加密一把,得到相应的字符串。
spring也提供了 封装类:
DigestUtils.md5DigestAsHex(password.getBytes())
SHA
SHA(Secure Hash Algorithm,安全散列算法),数字签名等密码学应用中重要的工具,被广泛地应用于电子商务等信息安全领域。虽然,SHA与MD5通过碰撞法都被破解了, 但是SHA仍然是公认的安全加密算法,较之MD5更为安全。
java 实现SHA加密jdk版
/** * 利用java原生的摘要实现SHA256加密 * @param str 加密后的报文 * @return */ public static String getSHA256StrJava(String str){ MessageDigest messageDigest; String encodeStr = ""; try { messageDigest = MessageDigest.getInstance("SHA-256"); messageDigest.update(str.getBytes("UTF-8")); encodeStr = byte2Hex(messageDigest.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return encodeStr; } /** * 将byte转为16进制 * @param bytes * @return */ private static String byte2Hex(byte[] bytes){ StringBuffer stringBuffer = new StringBuffer(); String temp = null; for (int i=0;i<bytes.length;i++){ temp = Integer.toHexString(bytes[i] & 0xFF); if (temp.length()==1){ //1得到一位的进行补0操作 stringBuffer.append("0"); } stringBuffer.append(temp); } return stringBuffer.toString(); }
Apache实现的:
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>${common-codec.version}</version> </dependency>
import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; public class Test { /** * Apache SHA */ public static String getSHA256Str(String str){ MessageDigest messageDigest; String encdeStr = ""; try { messageDigest = DigestUtils.getSha256Digest(); byte[] hash=DigestUtils.digest(messageDigest,str.getBytes("UTF-8")); encdeStr = Hex.encodeHexString(hash); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return encdeStr; } }
HMAC
HMAC(Hash Message Authentication Code,散列消息鉴别码,基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,用这个 标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证 等。
Java实现hmac
import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class Test { public static void main(String[] args) throws Exception{ String secrekey=initMacKey(); System.out.println(new String(encryptHMAC("hello".getBytes(),secrekey))); } /** * 初始化HMAC密钥 * @return * @throws Exception */ public static String initMacKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacSHA256"); SecretKey secretKey = keyGenerator.generateKey(); return new BASE64Encoder().encode(secretKey.getEncoded()); } /** * HMAC加密 * @param data * @param key * @return * @throws Exception */ public static byte[] encryptHMAC(byte[] data, String key) throws Exception { SecretKey secretKey = new SecretKeySpec(new BASE64Decoder().decodeBuffer(key), "HmacSHA256"); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); return mac.doFinal(data); } }
apache 实现的工具类
同样还是commons-codec包
具体可以参看包里的org.apache.commons.codec.digest.HmacUtils类
下面给出一个自封装的HmacUtils工具类
import org.apache.commons.codec.binary.Base64; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * @Describe: Hmac加密工具类 */ public class HmacUtils { /** * 加密生成签名 * @param data 签名的格式 * @param key 秘钥 * @return */ public static byte[] hmacSHA512(byte[] data, String key) { try { SecretKey secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA512"); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); return mac.doFinal(data); } catch (Exception e) { return null; } } /** * base64编码的变体,由于base64中的=、/和+不适合Url传递, * 因此需要将这三个符号替换掉,规则是去掉=,+替换为-,/替换为_ * @param stringBytes hmac(hmacSHA512) * @return */ public static String base64Url(byte[] stringBytes) { try { String base64Str = Base64.encodeBase64String(stringBytes); base64Str = base64Str.replace("=", ""); base64Str = base64Str.replace("+", "-"); base64Str = base64Str.replace("/", "_"); return base64Str; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } /** * SHA512 加密 * @param strText (用户密码明文 + salt) * @return */ public static byte[] sha512(final String strText) { // 是否是有效字符串 if (strText != null && strText.length() > 0) { try { // SHA 加密开始 // 创建加密对象 并指定加密类型 MessageDigest messageDigest = MessageDigest .getInstance("SHA-512"); // 传入要加密的字符串 messageDigest.update(strText.getBytes("UTF-8")); // 得到 byte 数组 return messageDigest.digest(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return null; } /** * Base64加密 * @param stringbytes * @return */ public static String base64(byte[] stringbytes) { try { String base64Str = Base64.encodeBase64String(stringbytes); return base64Str; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } }
以上就是这三种单向加密的介绍。