详见:https://blog.csdn.net/it_beecoder/article/details/71480770

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。本文给大家分享java常用的几种加密算法,需要的朋友可以参考下

对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。

简单的java加密算法有:

BASE 严格地说,属于编码格式,而非加密算法
MD(Message Digest algorithm ,信息摘要算法)
SHA(Secure Hash Algorithm,安全散列算法)
HMAC(Hash Message Authentication Code,散列消息鉴别码)

一.Base64

Base是网络上最常见的用于传输Bit字节代码的编码方式之一,大家可以查看RFC~RFC,上面有MIME的详细规范。Base编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base来将一个较长的唯一标识符(一般为-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。(来源百度百科)

package com.my.test.encryption;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder; /*
BASE的加密解密是双向的,可以求反解.
BASEEncoder和BASEDecoder是非官方JDK实现类。虽然可以在JDK里能找到并使用,但是在API里查不到。
JRE 中 sun 和 com.sun 开头包的类都是未被文档化的,他们属于 java, javax 类库的基础,其中的实现大多数与底层平台有关,
一般来说是不推荐使用的。
BASE 严格地说,属于编码格式,而非加密算法
主要就是BASEEncoder、BASEDecoder两个类,我们只需要知道使用对应的方法即可。
另,BASE加密后产生的字节位数是的倍数,如果不够位数以=符号填充。
BASE
按照RFC的定义,Base被定义为:Base内容传送编码被设计用来把任意序列的位字节描述为一种不易被人直接识别的形式。
(The Base Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)
常见于邮件、http加密,截取http信息,你就会发现登录操作的用户名、密码字段通过BASE加密的。
*/ public class TestBase64 { public static void main(String[] args) {
// TODO Auto-generated method stub String str = "ASD123@我的你的"; try {
String encryptionSting = encryptBASE(str.getBytes());
System.out.println(encryptionSting); byte[] bs = decryptBASE(encryptionSting); String password = new String(bs);
System.out.println(password);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } /**
* BASE解密
*
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
} /**
* BASE加密
*
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE(byte[] key) throws Exception {
return (new BASE64Encoder()).encodeBuffer(key);
} } 

解决Eclipse中无法直接使用sun.misc.BASE64Encoder及sun.misc.BASE64Decoder的问题:

详见:eclipse报错排解 问题16

 第二种. MD

MD即Message-Digest Algorithm (信息-摘要算法),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD的前身有MD、MD和MD。广泛用于加密和解密技术,常用于文件校验。校验?不管文件多大,经过MD后都能生成唯一的MD值。好比现在的ISO校验,都是MD校验。怎么用?当然是把ISO经过MD后产生MD的值。一般下载linux-ISO的朋友都见过下载链接旁边放着MD的串。就是用来验证文件是否一致的。

MessageDigest.getInstance("MD5") 有几种参数?写一个方法来获取

public static String[] getCryptoImpls(String serviceType) {
Set result = new HashSet(); // All all providers
Provider[] providers = Security.getProviders();
for (int i=0; i<providers.length; i++) {
// Get services provided by each provider
Set keys = providers[i].keySet();
for (Iterator it=keys.iterator(); it.hasNext(); ) {
String key = (String)it.next();
key = key.split(" ")[0]; if (key.startsWith(serviceType+".")) {
result.add(key.substring(serviceType.length()+1));
} else if (key.startsWith("Alg.Alias."+serviceType+".")) {
// This is an alias
result.add(key.substring(serviceType.length()+11));
}
}
}
return (String[])result.toArray(new String[result.size()]);
}

调用方法如下:
String[] names = getCryptoImpls("MessageDigest");

然后就会返回支持的加密算法

SHA-1
SHA1
SHA-384
OID.1.3.14.3.2.26
2.16.840.1.101.3.4.2.2
SHA
2.16.840.1.101.3.4.2.1
2.16.840.1.101.3.4.2.4
2.16.840.1.101.3.4.2.3
OID.2.16.840.1.101.3.4.2.4
OID.2.16.840.1.101.3.4.2.3
OID.2.16.840.1.101.3.4.2.2
1.3.14.3.2.26
OID.2.16.840.1.101.3.4.2.1
SHA-224
SHA-256
MD2
SHA-512
MD5
package com.my.test.encryption;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
//单向加密
/*
MD(Message Digest algorithm ,信息摘要算法)
通常我们不直接使用上述MD加密。通常将MD产生的字节数组交给BASE再加密一把,得到相应的字符串
Digest:汇编
*/
public class TestMD {
public static void main(String[] args) {
System.out.println(getResult("12344567gyjtyity")); } public static final String KEY_MD = "MD2";
public static String getResult(String inputStr){
System.out.println("=======加密前的数据:"+inputStr);
BigInteger bigInteger=null;
try {
MessageDigest md = MessageDigest.getInstance(KEY_MD);
byte[] inputData = inputStr.getBytes();
md.update(inputData);
bigInteger = new BigInteger(md.digest());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String result = bigInteger.toString();
System.out.println("MD加密后:" + result);
System.out.println(result.length());
return result;
} }

MD算法具有以下特点:

、压缩性:任意长度的数据,算出的MD值长度都是固定的。
、容易计算:从原数据计算出MD值很容易。
、抗修改性:对原数据进行任何改动,哪怕只修改个字节,所得到的MD值都有很大区别。
、弱抗碰撞:已知原数据和其MD值,想找到一个具有相同MD值的数据(即伪造数据)是非常困难的。
、强抗碰撞:想找到两个不同的数据,使它们具有相同的MD值,是非常困难的。

MD的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。除了MD以外,其中比较有名的还有sha-、RIPEMD以及Haval等。

三.SHA

package com.my.test.encryption;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
//单向加密
/*
SHA(Secure Hash Algorithm,安全散列算法),数字签名等密码学应用中重要的工具,
被广泛地应用于电子商务等信息安全领域。虽然,SHA与MD通过碰撞法都被破解了,
但是SHA仍然是公认的安全加密算法,较之MD更为安全*/
public class TestSHA {
public static void main(String[] args) {
getResult("12344567gyjtyity"); } public static final String KEY_MD = "SHA1";
public static String getResult(String inputStr){
System.out.println("=======加密前的数据:"+inputStr);
BigInteger bigInteger=null;
try {
MessageDigest md = MessageDigest.getInstance(KEY_MD);
byte[] inputData = inputStr.getBytes();
md.update(inputData);
bigInteger = new BigInteger(md.digest());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String result = bigInteger.toString();
System.out.println("MD加密后:" + result);
System.out.println(result.length());
return result;
} }

第四种.HMAC

HMAC(Hash Message Authentication Code,散列消息鉴别码,基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。

DESede
SunTls12KeyMaterial
HmacSHA512
1.2.840.113549.2.11
OID.1.2.840.113549.2.11
Rijndael
HmacMD5
1.2.840.113549.2.10
HmacSHA256
HmacSHA1
SunTlsMasterSecret
TripleDES
SunTls12Prf
SunTls12MasterSecret
SunTls12RsaPremasterSecret
1.2.840.113549.2.8
RC2
1.2.840.113549.2.9
RC4
SunTlsKeyMaterial
OID.1.2.840.113549.2.9
OID.1.2.840.113549.2.8
ARCFOUR
OID.1.2.840.113549.2.7
AES
1.2.840.113549.2.7
SunTlsPrf
HmacSHA224
DES
HmacSHA384
Blowfish

mac(Message Authentication Code,消息认证码算法)是含有密钥散列函数算法,基于散列函数的消息认证码,它需要一个加密用散列函数(表示为H,可以是MD5或者SHA-1)和一个密钥K用以计算消息认证码,兼容了MD和SHA算法的特性,并在此基础上加上了密钥。因此MAC算法也经常被称作HMAC算法。关于hmac算法的详情可以参看RFC 2104(http://www.ietf.org/rfc/rfc2104.txt),这里包含了HmacMD5算法的C语言实现。
  这里需要说明的是经过mac算法得到的摘要值也可以使用十六进制编码表示,其摘要值的长度与实现算法的摘要值长度相同。例如 HmacSHA算法得到的摘要长度就是SHA1算法得到的摘要长度,都是160位二进制数,换算成十六进制的编码为40位。

二、模型分析
甲乙双方进行数据交换可以采取如下流程完成
1、甲方向乙方公布摘要算法(就是指定要使用的摘要算法名)
2、甲乙双方按照约定构造密钥,双方拥有相同的密钥(一般是一方构造密钥后通知另外一方,此过程不需要通过程序实现,就是双方约定个字符串,但是这个字符串可不是随便设定的,也是通过相关算法获取的)
3、甲方使用密钥对消息做摘要处理,然后将消息和生成的摘要消息一同发送给乙方
4、乙方收到消息后,使用甲方已经公布的摘要算法+约定好的密钥 对收到的消息进行摘要处理。然后比对自己的摘要消息和甲方发过来的摘要消息。甄别消息是否是甲方发送过来的

/**
* 初始化HMAC密钥
* 展示了一个生成指定算法密钥的过程 初始化HMAC密钥
*
* @return
* @throws Exception
*/
public static String initMacKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance(KEY_MAC);
SecretKey secretKey = kg.generateKey();
return TestBase64.encryptBASE(secretKey.getEncoded());
} /**
* HMAC加密 :主要方法
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
System.out.println("=====Mac明码:"+TestBase64.decryptBASE(key));
SecretKey secretKey = new SecretKeySpec(key.getBytes(), KEY_MAC);
Mac mac = Mac.getInstance(KEY_MAC);
mac.init(secretKey);
return mac.doFinal(data);
}

完整代码:包含三种对 结果的处理和参数的查询方法:

package com.my.test.encryption;

import java.math.BigInteger;
import java.security.Provider;
import java.security.Security;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec; import sun.misc.BASE64Decoder; //单向加密
/*
HMAC
HMAC(Hash Message Authentication Code,散列消息鉴别码,基于密钥的Hash算法的认证协议。
消息鉴别码实现鉴别的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。
使用一个密钥生成一个固定大小的小数据块,
即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。*/
public class TestHMAC {
public static final String KEY_MAC = "HmacMD5"; /**
* 全局数组
*/
private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
"e", "f" }; public static void main(String[] args) {
// TODO Auto-generated method stub
String inputStr = "Thisisatest";
try {
System.out.println("=====加密前的数据 : " + inputStr);
// String key = initMacKey();//每次产生一个不同的key String key = "6666"; System.out.println("=====Mac密钥:" + key);
byte[] data = inputStr.getBytes(); byte[] results = encryptHMAC(data, key);
BigInteger bigInteger = new BigInteger(results);
System.out.println(" ===" + byte2hex(results));
System.out.println("==== " + byteArrayToHexString(results));
System.out.println(bigInteger);
System.out.println(bigInteger.toString(16)); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } /**
* 初始化HMAC密钥 展示了一个生成指定算法密钥的过程 初始化HMAC密钥
*
* @return
* @throws Exception
*/
//
// public static String initMacKey() throws Exception {
// KeyGenerator kg = KeyGenerator.getInstance(KEY_MAC);
// SecretKey secretKey = kg.generateKey();
// return TestBase64.encryptBASE(secretKey.getEncoded());
// }
//
/**
* HMAC加密 :主要方法
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
System.out.println("=====Mac明码:" + TestBase64.decryptBASE(key));
SecretKey secretKey = new SecretKeySpec(key.getBytes(), KEY_MAC);
Mac mac = Mac.getInstance(KEY_MAC);
mac.init(secretKey);
return mac.doFinal(data);
} // 获取 KeyGenerator所支持的所有参数
public static String[] getCryptoImpls(String serviceType) {
Set result = new HashSet(); // All all providers
Provider[] providers = Security.getProviders();
for (int i = 0; i < providers.length; i++) {
// Get services provided by each provider
Set keys = providers[i].keySet();
for (Iterator it = keys.iterator(); it.hasNext();) {
String key = (String) it.next();
key = key.split(" ")[0]; if (key.startsWith(serviceType + ".")) {
result.add(key.substring(serviceType.length() + 1));
} else if (key.startsWith("Alg.Alias." + serviceType + ".")) {
// This is an alias
result.add(key.substring(serviceType.length() + 11));
}
}
}
return (String[]) result.toArray(new String[result.size()]);
} // 二行制转字符串
public static String byte2hex(byte[] b) {
StringBuilder hs = new StringBuilder();
String stmp;
for (int n = 0; b != null && n < b.length; n++) {
stmp = Integer.toHexString(b[n] & 0XFF);
if (stmp.length() == 1)
hs.append('0');
hs.append(stmp);
}
return hs.toString().toUpperCase();
} /**
* 将一个字节转化成十六进制形式的字符串
*
* @param b
* 字节数组
* @return 字符串
*/
private static String byteToHexString(byte b) {
int ret = b;
// System.out.println("ret = " + ret);
if (ret < 0) {
ret += 256;
}
int m = ret / 16;
int n = ret % 16;
return hexDigits[m] + hexDigits[n];
} /**
* 转换字节数组为十六进制字符串
*
* @param bytes
* 字节数组
* @return 十六进制字符串
*/
private static String byteArrayToHexString(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
sb.append(byteToHexString(bytes[i]));
}
return sb.toString();
} }
05-28 10:02