public static byte[] getMD5(String content) throws Exception
{
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = md.digest(content.getBytes("utf8"));
return bytes;
}
//MD5 Message Digest Algorithm 5(128位) 返回String的一中实现 ,也可以用Base64
public static String testMD5(String content) throws Exception
{
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = md.digest(content.getBytes("utf8"));
return bytes_String16(bytes);
}
//SHA Secure Hash Algorithm (160位)
public static String testSHA1(String content) throws Exception
{
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] bytes = md.digest(content.getBytes("utf8"));
return byte2hex(bytes);
}
/**
* byte[] 转16进制字符串
* @param b
* @return
*/
public static String bytes_String16(byte[] b) {
char[] _16 = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i<b.length;i++) {
sb.append(_16[b[i]>>4&0xf])
.append(_16[b[i]&0xf]);
}
return sb.toString();
}
//字节数组转成16进制
private static String byte2hex(byte[] bytes)
{
StringBuilder hex = new StringBuilder();
for(int i=0;i<bytes.length;i++)
{
byte b = bytes[i];
boolean negative = false;
if(b<0) negative = true;
int inte = Math.abs(b);
if(negative) inte = inte | 0x80;
String temp = Integer.toHexString(inte & 0xFF);
if(temp.length()==1)
{
hex.append("0");
}
hex.append(temp.toLowerCase());
}
return hex.toString();
}
//16进制转成字节数组
private static byte[] hex2bytes(String hex)
{
byte[] bytes = new byte[hex.length()/2];
for(int i=0;i<hex.length();i=i+2)
{
String subStr = hex.substring(i,i+2);
boolean negative = false;
int inte = Integer.parseInt(subStr,16);
if(inte>127) negative = true;
if(inte == 128)
{
inte = -128;
}
else if(negative)
{
inte = 0-(inte & 0x7F);
}
byte b = (byte)inte;
bytes[i/2] = b;
}
return bytes;
}
//Base64 编码 是一种基于64个可打印字符来表示二进制数据的方法
private static String byte2base64(byte[] bytes)
{
BASE64Encoder base64Encoder = new BASE64Encoder();
return base64Encoder.encode(bytes);
}
private static byte[] base642byte(String base64) throws IOException
{
BASE64Decoder base64Decoder = new BASE64Decoder();
return base64Decoder.decodeBuffer(base64);
}
/**
* 对称加密算法 常用的对称加密算法 有 DES,3DES,AES
* DES: 明文按64位进行分组,密钥长64位 实际上只有56位参与运算
* 3DES:是DES向AES过度的加密算法 使用3条56位的密钥对数据进行3次加密 是DES的一个更安全的变形
*/
//生成DES密钥 并且编码成base64字符串
public static String genKeyDES() throws Exception
{
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
keyGen.init(56);
SecretKey key = keyGen.generateKey();
String base64Str = byte2base64(key.getEncoded());
return base64Str;
}
//base64字符串展开成真实的16进制密钥
public static SecretKey loadKeyDES(String base64Key) throws Exception
{
byte[] bytes = base642byte(base64Key);
SecretKey key = new SecretKeySpec(bytes, "DES");
return key;
}
//加密函数
/**
*
* @param 要加密的字节数组
* @param 16进制形式的密钥
* @return 加密完成的字节数组
* @throws Exception
*/
public static byte[] encryptDES(byte[] source,SecretKey key) throws Exception
{
Cipher cipher = Cipher.getInstance("DES");
cipher.init(cipher.ENCRYPT_MODE, key); //和下面的模式是不一样
byte[] bytes = cipher.doFinal(source);
return bytes;
}
/**
*
* @param 要解密的字节数组
* @param 16进制加密的密钥
* @return 解密后的字节数组
* @throws Exception
*/
public static byte[] decryptDES(byte[] source,SecretKey key) throws Exception
{
Cipher cipher = Cipher.getInstance("DES");
cipher.init(cipher.DECRYPT_MODE, key);
byte[] bytes = cipher.doFinal(source);
return bytes;
}
/**
* AES Advanced Encryption Standard 这个标准用来取代原先的DES算法,是最为流行算法之一
* 设计有三个密钥长度(128,192,256位)比DES算法加密强度更高,更为安全
*
*/
//产生一个base64编码的密钥
public static String genKeyAES() throws Exception
{
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); //普通的128位可以使用 192,256位会报错
//https://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters
//local_policy.jar US_export_policy.jar 覆盖掉 C:\Program Files\Java\jre1.8.0_111\lib\security
SecretKey key = keyGen.generateKey();
String base64Str = byte2base64(key.getEncoded());
return base64Str;
}
//base64编码的转换成真实的16进制密钥
public static SecretKey loadKeyAES(String base64Key) throws Exception
{
byte[] bytes = base642byte(base64Key);
SecretKey key = new SecretKeySpec(bytes, "AES");
return key;
}
//加密
public static byte[] encryptAES(byte[] source,SecretKey key) throws Exception
{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(cipher.ENCRYPT_MODE, key);
byte[] bytes = cipher.doFinal(source);
return bytes;
}
//解密
public static byte[] decryptAES(byte[] source,SecretKey key) throws Exception
{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(cipher.DECRYPT_MODE, key);
byte[] bytes = cipher.doFinal(source);
return bytes;
}
/**
* 非对称加密算法 又称公开密钥加密算法,有两个密钥 一个是公钥(publickey) 另一个是私钥(privatekey)
* 公钥和私钥要配对使用,如果公钥对数据加密,只有用对应的私钥解密,而如果用私钥对数据加密,只能用对应的公钥进行解密
* 基本过程 甲方生成一对密钥 并将其中一把作为公钥向其他人公开,得到公钥的乙方使用该密钥对信息进行加密后在发送给甲方,甲方使用
* 自己的私钥进行解密
* 非对称加密算法能够保证 即使获知公钥,加密算法,加密算法源代码的情况下也无法获得 公钥对应的私钥,也无法对密文进行解密
* 缺点:速度慢 对称加密较长的文件,然后用非对称机密算法给文件密钥加密
* 最广泛的非对称加密算法 是RSA
* RAS 基于数论:将两个大素数相乘容易,对乘积进行因式分解十分困难,乘积公开作为加密密钥
*
*/
//获得乘积因子
public static KeyPair getKeyPair() throws Exception
{
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
}
//公钥base64编码
public static String getPublicKey(KeyPair keyPair)
{
PublicKey publicKey = keyPair.getPublic();
byte[] bytes = publicKey.getEncoded();
return byte2base64(bytes);
}
//私钥base64编码
public static String getPrivateKey(KeyPair keyPair)
{
PrivateKey privateKey = keyPair.getPrivate();
byte[] bytes = privateKey.getEncoded();
return byte2base64(bytes);
}
//base64类型转换成PublicKey
public static PublicKey string2PublicKey(String pubStr) throws Exception
{
byte[] keyBytes = base642byte(pubStr);
/**
* This class represents the ASN.1 encoding of a public key,
* encoded accroding to the ASN.1 type
* 此类表示公钥的ASN.1编码,根据ASN.1类型进行编码
*/
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
//base64生成PrivateKey
public static PrivateKey string2PrivateKey(String priStr) throws Exception
{
byte[] keyBytes = base642byte(priStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
//使用公钥加密字节数组
public static byte[] publicEncrypt(byte[] content,PublicKey publicKey) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(cipher.ENCRYPT_MODE, publicKey);
byte[] bytes = cipher.doFinal(content);
return bytes;
}
//使用私钥加密字节数组
public static byte[] privateEncrypt(byte[] content,PrivateKey privateKey) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(cipher.ENCRYPT_MODE, privateKey);
byte[] bytes = cipher.doFinal(content);
return bytes;
}
//使用私钥解密字节数组
public static byte[] privateDecrypt(byte[] content,PrivateKey privateKey) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(cipher.DECRYPT_MODE, privateKey);
byte[] bytes = cipher.doFinal(content);
return bytes;
}
//使用公钥解密字节数组
public static byte[] publicDecrypt(byte[] content,PublicKey publicKey) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(cipher.DECRYPT_MODE, publicKey);
byte[] bytes = cipher.doFinal(content);
return bytes;
}
/**
* 数字签名是非对称加密算法与数字摘要技术的综合应用,通信内容的摘要信息使用发送者的私钥进行加密,然后将密文与原文一起传输给信息的接受者
* 接受者通过使用与发送者相同的摘要算法解密被加密的摘要信息,然后对通信内容采用相同的hash算法得到摘要串,在和解密的比较
* 相同证明中途没有被改 常见的数字签名算法有
* MD5withRSA,SHA1withRSA
*
*/
//MD5withRSA
private static byte[] sign(byte[] content,PrivateKey privateKey) throws Exception
{
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = md.digest(content);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(cipher.ENCRYPT_MODE, privateKey);
byte[] encryptBytes = cipher.doFinal(bytes);
return encryptBytes;
}
//认证
private static boolean verify(byte[] content,byte[] sign,PublicKey publicKey) throws Exception
{
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = md.digest(content);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(cipher.DECRYPT_MODE, publicKey);
byte[] decryptBytes = cipher.doFinal(sign);
if(byte2base64(decryptBytes).equals(byte2base64(bytes)))
{
return true;
}
else
{
return false;
}
}
//java 自带的API
private static byte[] signApi(byte[] content,PrivateKey privateKey) throws Exception
{
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(privateKey);
signature.update(content);
return signature.sign();
}
//
private static boolean verifyApi(byte[] content,byte[] sign,PublicKey publicKey) throws Exception
{
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(publicKey);
signature.update(content);
return signature.verify(sign);
}
/**
* SHA1withRSA和上面的类似 ,改下参数就可以了
*
*/
/**
* 摘要认证的实现
* 请求参数->参数排序->将参数串接起来加上secret 生成带摘要字符串->使用MD5算法生成摘要串
*/
private static String getDigest(Map<String, String> params) throws Exception
{
String secret = "abcdefjijklmn";
Set<String> keySet = params.keySet();
//使用Treeset排序
TreeSet<String> sortSet = new TreeSet<String>();
sortSet.addAll(keySet);
String keyvalueStr = "";
Iterator<String> it = sortSet.iterator();
while(it.hasNext())
{
String key = it.next();
String value = params.get(key);
keyvalueStr += key + value;
}
keyvalueStr += secret;
String base64Str = byte2base64(getMD5(keyvalueStr));
return base64Str;
}
//java服务端参数摘要校验
private static boolean validate(Map params,String digest) throws Exception
{
String secret = "abcdefjijklmn";
Set<String> keySet = params.keySet();
//treeset sort
TreeSet<String> sortSet = new TreeSet<String>();
sortSet.addAll(keySet);
String keyvalueStr = "";
Iterator<String> it = sortSet.iterator();
while(it.hasNext())
{
String key = it.next();
String values = (String) params.get(key);
keyvalueStr += key + values;
}
keyvalueStr += secret;
String base64Str = byte2base64(getMD5(keyvalueStr));
if(base64Str.equals(digest))
{
return true;
}
else
{
return false;
}
}
函数的测试
String str = "大时代撒多撒多撒多撒多撒多";
String bufferMD5 = testMD5(str);
String bufferSHA1 = testSHA1(str);
System.out.println(bufferMD5); //4C82B120D0926916A9F4E3554DE555B2
System.out.println(bufferSHA1);//1A11F3E193C78A9073C872FFCAB455CD24AFC2FB
//DES加密
String strbase64DES = genKeyDES();
System.out.println("v+P+bsJeq48="); //v+P+bsJeq48=
SecretKey keyDES = loadKeyDES("v+P+bsJeq48=");
//将str 转成字节数组(以utf-8的形式)
byte[] byte_UTF = str.getBytes("UTF-8");
System.out.println(Arrays.toString(byte_UTF)); //[-26, -99, -88, -27, -80, -111, -27, -82, -66]
//加密
byte[] byte_DES = encryptDES(byte_UTF, keyDES);
System.out.println(Arrays.toString(byte_DES)); //[-104, 114, 21, -67, -31, 34, -89, 13, -120, -4, 1, -82, 55, 86, 122, -102]
//密文用base64编码
String str_BASE = byte2base64(byte_DES); //mHIVveEipw2I/AGuN1Z6mg==
System.out.println(str_BASE);
//base64解码
byte[] byte_EDES = base642byte(str_BASE); // [-104, 114, 21, -67, -31, 34, -89, 13, -120, -4, 1, -82, 55, 86, 122, -102]
System.out.println(Arrays.toString(byte_EDES));
//解密
byte[] byte_EUTF = decryptDES(byte_DES, keyDES);
System.out.println(Arrays.toString(byte_EUTF)); //[-26, -99, -88, -27, -80, -111, -27, -82, -66]
//byte 转换成string
String str_E = new String(byte_EUTF,"UTF-8");
System.out.println(str_E);
AES测试
//AES加密
String strbase64AES = genKeyAES();
System.out.println(strbase64AES); //6ZNeCtWgEyiyKXYrc6R3OA== 128位
// Zbn02vN5nsZ0qoUmJq+H6GJehQozq5pw 192位
// BOoz7HVmZVBrS7OHVdZ2HHFfb6FRxyNmCWhXnefKv0M= 256位
SecretKey keyAES = loadKeyAES(strbase64AES);
//将str 转成字节数组(以utf-8的形式)
byte[] byte_UTF = str.getBytes("UTF-8");
System.out.println(Arrays.toString(byte_UTF)); //[-26, -99, -88, -27, -80, -111, -27, -82, -66]
//加密
byte[] byte_AES = encryptAES(byte_UTF, keyAES);
System.out.println(Arrays.toString(byte_AES)); //[73, -22, -3, -10, -115, -95, 107, -103, 117, 45, 60, 9, 81, -74, 13, -80]
//密文用base64编码
String str_BASE = byte2base64(byte_AES); //Ser99o2ha5l1LTwJUbYNsA==
System.out.println(str_BASE);
//base64解码
byte[] byte_EAES = base642byte(str_BASE); // [73, -22, -3, -10, -115, -95, 107, -103, 117, 45, 60, 9, 81, -74, 13, -80]
System.out.println(Arrays.toString(byte_EAES));
//解密
byte[] byte_EUTF = decryptAES(byte_EAES, keyAES);
System.out.println(Arrays.toString(byte_EUTF)); //[-26, -99, -88, -27, -80, -111, -27, -82, -66]
//byte 转换成string
String str_E = new String(byte_EUTF,"UTF-8");
System.out.println(str_E);
RSA测试
//RSA 加密
KeyPair keyPair = getKeyPair();
String strbase64RSA_public = getPublicKey(keyPair);
System.out.println(strbase64RSA_public); //MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALC2WJe6+0pPLkuttnxGnDGGTJ2MNLz1dFZh0GrkoZrC
//QwQF5lflatfj5TtGJTufm4hMQE5tuqa69N99jSUeciUCAwEAAQ== 768位
String strbase64RSA_private = getPrivateKey(keyPair);
System.out.println(strbase64RSA_private); //MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAsLZYl7r7Sk8uS622fEacMYZMnYw0
// vPV0VmHQauShmsJDBAXmV+Vq1+PlO0YlO5+biExATm26prr0332NJR5yJQIDAQABAkAOrzhxc2JK
// bIYGV+sgLKXyH5ziQrJnOWZvfzVYjKM5PuQDKTsHJxhu+RRSAx200qdg6vVijnTMpv5itztUQIXB
// AiEA2WjxujvzguNPeR+Bq4jF08l0kdyRBc401l6vHGTb0PkCIQDQFBw/pWM2XByuhmfihu3jyCJQ
// dCA9HSnvyrgoMk5hjQIgTtEz6S84zbe4pRGeAeDYzznWj9aloLQsBZdX5nROGIkCH3+b1bcytqWf
// 1/cwdoV2Om53TpQIo7zXJeDpcgc00t0CIQCEtxfeZCk4aciKiNubjYOdFKX7stFKfqFlLlwxfs3b
// yQ==
// //获取public 和 private 对象
PublicKey publicKey = string2PublicKey(strbase64RSA_public);
PrivateKey privateKey = string2PrivateKey(strbase64RSA_private);
//将str 转成字节数组(以utf-8的形式)
byte[] byte_UTF = str.getBytes("UTF-8"); //512位 RSA 最多加密字节数:512/8-11=53 字节 1024位 117字节 2048位 245字节
System.out.println(Arrays.toString(byte_UTF)); //[-26, -99, -88, -27, -80, -111, -27, -82, -66]
//公钥加密
//byte[] byte_RSA = publicEncrypt(byte_UTF, publicKey);
//私钥加密
byte[] byte_RSA = privateEncrypt(byte_UTF, privateKey);
System.out.println(Arrays.toString(byte_RSA)); //[11, 7, -64, 21, -106, -28, -3, -24, 102, 84, -58, -43, -126, -119, 103, -102, 79, 65, -118, -27, -4, -35, 120, 54, 114, 30, -32, -89, -60, -59, 81, 86, 84, 94, 119, -6, -104, 81, 124, -32, 92, -3, 123, -89, 38, -112, 123, -16, 106, 20, 14, -74, -58, -12, 60, 101, -86, -7, 22, -26, 23, 10, -62, -73]
//密文用base64编码
String str_BASE = byte2base64(byte_RSA); //CwfAFZbk/ehmVMbVgolnmk9BiuX83Xg2ch7gp8TFUVZUXnf6mFF84Fz9e6cmkHvwahQOtsb0PGWq
// +RbmFwrCtw== 密文不随明文长度变化 528位
System.out.println(str_BASE);
//base64解码
byte[] byte_ERSA = base642byte(str_BASE); // [73, -22, -3, -10, -115, -95, 107, -103, 117, 45, 60, 9, 81, -74, 13, -80]
System.out.println(Arrays.toString(byte_ERSA));
//私钥解密
//byte[] byte_EUTF = privateDecrypt(byte_ERSA, privateKey);
//公钥解密
byte[] byte_EUTF = publicDecrypt(byte_ERSA, publicKey);
System.out.println(Arrays.toString(byte_EUTF)); //[-26, -99, -88, -27, -80, -111, -27, -82, -66]
//byte 转换成string
String str_E = new String(byte_EUTF,"UTF-8");
System.out.println(str_E);
MD5withRSA测试
//MD5withRSA验证
KeyPair keyPair = getKeyPair();
String strbase64RSA_public = getPublicKey(keyPair);
System.out.println(strbase64RSA_public);
String strbase64RSA_private = getPrivateKey(keyPair);
System.out.println(strbase64RSA_private);
PublicKey publicKey = string2PublicKey(strbase64RSA_public);
PrivateKey privateKey = string2PrivateKey(strbase64RSA_private);
byte[] byte_UTF = str.getBytes("UTF-8");
System.out.println(Arrays.toString(byte_UTF));
//摘要加密
//byte[] byteMD5withRSA = sign(byte_UTF, privateKey);
//APi
byte[] byteMD5withRSA = signApi(byte_UTF, privateKey);
System.out.println(Arrays.toString(byteMD5withRSA));
//API
//boolean flag = verify(byte_UTF, byteMD5withRSA, publicKey);
boolean flag = verifyApi(byte_UTF, byteMD5withRSA, publicKey);
System.out.println(flag);
客户端参数摘要
Map<String, String> params = new HashMap<String,String>();
params.put("controller", "Home");
params.put("Action", "Index");
params.put("Id", "454");
params.put("Name", "张三");
String str_params = getDigest(params);
System.out.println(str_params);
boolean flag = validate(params, str_params);
System.out.println(flag);
需要导入的jar包
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.MacSpi;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import sun.security.rsa.RSASignature.MD5withRSA;
有什么问题欢迎指正!!