(一)加密算法分为:
(1)对称加密算法:
- DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法,AES算法。
(2)非对称加密算法 :
- RSA、Elgamal、背包算法、Rabin、D-H、ECC。
(3)哈希算法 :
- MD2、MD4、MD5 和 SHA-1
(二) 区别及特点:
对称加密算法:
- 秘钥只有一个,通过该秘钥可以对加密过后的数据进行解密。加密解密速度相对快,安全性低一点。解密加密都用同一个秘钥所以叫对称加密算法。
非对称加密算法 :
- 一般分为两个秘钥 一个加密秘钥一个解密秘钥, 称为公钥和秘钥。
公钥进行加密,可以公开。秘钥进行解密不公开。加密解密速度较慢一点。安全性高。两个秘钥不一样所以叫非对称加密算法 。
哈希算法 :
- 目的是将任意长输入通过算法变为固定长输出,且保证输入变化一点输出都不同,且不能反向解密。
(三) 举例
对称加密算法 (AES):
/**
* Created by linving on 2016/11/10.
*/
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
* 编码工具类
* 1.将byte[]转为各种进制的字符串
* 2.base 64 encode
* 3.base 64 decode
* 4.获取byte[]的md5值
* 5.获取字符串md5值
* 6.结合base64实现md5加密
* 7.AES加密
* 8.AES加密为base 64 code
* 9.AES解密
* 10.将base 64 code AES解密
*
* @author uikoo9
* @version 0.0.7.20140601
*/
public class AESUtil {
/**
* 将byte[]转为各种进制的字符串
*
* @param bytes byte[]
* @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
* @return 转换后的字符串
*/
public static String binary(byte[] bytes, int radix) {
return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
}
/**
* base 64 encode
*
* @param bytes 待编码的byte[]
* @return 编码后的base 64 code
*/
public static String base64Encode(byte[] bytes) {
return new BASE64Encoder().encode(bytes);
}
/**
* base 64 decode
*
* @param base64Code 待解码的base 64 code
* @return 解码后的byte[]
* @throws Exception
*/
public static byte[] base64Decode(String base64Code) throws Exception {
return new BASE64Decoder().decodeBuffer(base64Code);
}
/**
* 获取byte[]的md5值
*
* @param bytes byte[]
* @return md5
* @throws Exception
*/
public static byte[] md5(byte[] bytes) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytes);
return md.digest();
}
/**
* 获取字符串md5值
*
* @param msg
* @return md5
* @throws Exception
*/
public static byte[] md5(String msg) throws Exception {
return md5(msg.getBytes());
}
/**
* 结合base64实现md5加密
*
* @param msg 待加密字符串
* @return 获取md5后转为base64
* @throws Exception
*/
public static String md5Encrypt(String msg) throws Exception {
return base64Encode(md5(msg));
}
/**
* AES加密
*
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的byte[]
* @throws Exception
*/
public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(encryptKey.getBytes()));
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
return cipher.doFinal(content.getBytes("utf-8"));
}
/**
* AES加密为base 64 code
*
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的base 64 code
* @throws Exception
*/
public static String aesEncrypt(String content, String encryptKey) {
try {
return base64Encode(aesEncryptToBytes(content, encryptKey));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* AES解密
*
* @param encryptBytes 待解密的byte[]
* @param decryptKey 解密密钥
* @return 解密后的String
* @throws Exception
*/
public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(decryptKey.getBytes()));
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
/**
* 将base 64 code AES解密
*
* @param encryptStr 待解密的base 64 code
* @param decryptKey 解密密钥
* @return 解密后的string
* @throws Exception
*/
public static String aesDecrypt(String encryptStr, String decryptKey) {
try {
return aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
非对称加密算法(RSA)
/**
* Created by linving on 2016/11/10.
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* RSA算法,实现数据的加密解密。
* @author ShaoJiang
*
*/
public class RSAUtil {
private static Cipher cipher;
static{
try {
cipher = Cipher.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}
/**
* 生成密钥对
* @return
*/
public static Map<String,String> generateKeyPair(){
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 密钥位数
keyPairGen.initialize(1024);
// 密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
PublicKey publicKey = keyPair.getPublic();
// 私钥
PrivateKey privateKey = keyPair.getPrivate();
//得到公钥字符串
String publicKeyString = getKeyString(publicKey);
//得到私钥字符串
String privateKeyString = getKeyString(privateKey);
//将生成的密钥对返回
Map<String,String> map = new HashMap<>();
map.put("publicKey",publicKeyString);
map.put("privateKey",privateKeyString);
return map;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 得到公钥
*
* @param key
* 密钥字符串(经过base64编码)
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* 得到私钥
*
* @param key
* 密钥字符串(经过base64编码)
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 得到密钥字符串(经过base64编码)
*
* @return
*/
public static String getKeyString(Key key) throws Exception {
byte[] keyBytes = key.getEncoded();
String s = (new BASE64Encoder()).encode(keyBytes);
return s;
}
/**
* 使用公钥对明文进行加密,返回BASE64编码的字符串
* @param publicKey
* @param plainText
* @return
*/
public static String encrypt(PublicKey publicKey,String plainText){
try {
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] enBytes = cipher.doFinal(plainText.getBytes());
return (new BASE64Encoder()).encode(enBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 使用keystore对明文进行加密
* @param
* @param plainText 明文
* @return
*/
public static String encrypt(String publicKey,String plainText){
try {
cipher.init(Cipher.ENCRYPT_MODE,getPublicKey(publicKey));
byte[] enBytes = cipher.doFinal(plainText.getBytes());
return (new BASE64Encoder()).encode(enBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 使用私钥对明文密文进行 解密
* @param privateKey
* @param enStr
* @return
*/
public static String decrypt(PrivateKey privateKey,String enStr){
try {
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] deBytes = cipher.doFinal((new BASE64Decoder()).decodeBuffer(enStr));
return new String(deBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 使用keystore对密文进行解密
* @param enStr 密文
* @return
*/
public static String decrypt(String privateKey,String enStr){
try {
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
byte[] deBytes = cipher.doFinal((new BASE64Decoder()).decodeBuffer(enStr));
return new String(deBytes);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
散列算法 /哈希算法(MD5 )
import java.io.IOException;
import java.io.StringReader;
public class HexDump {
class HexTablifier {
private int m_row = 8;
private String m_pre = "";
private String m_post = "\n";
public HexTablifier() {
}
public HexTablifier(int row) {
this(row, "", "\n");
}
public HexTablifier(int row, String pre) {
this(row, pre, "\n");
}
public HexTablifier(int row, String pre, String post) {
m_row = row;
m_pre = pre;
m_post = post;
}
public String format(String hex) {
StringReader reader = new StringReader(hex);
StringBuilder builder = new StringBuilder(hex.length() * 2);
try {
while (getHexLine(builder, reader)) {
}
} catch (IOException e) {
// 不应该有异常出现。
}
return builder.toString();
}
private boolean getHexLine(StringBuilder builder, StringReader reader)
throws IOException {
StringBuilder lineBuilder = new StringBuilder();
boolean result = true;
for (int i = 0; i < m_row; i++) {
result = getHexByte(lineBuilder, reader);
if (result == false)
break;
}
if (lineBuilder.length() > 0) {
builder.append(m_pre);
builder.append(lineBuilder);
builder.append(m_post);
}
return result;
}
private boolean getHexByte(StringBuilder builder, StringReader reader)
throws IOException {
char[] hexByte = new char[4];
int bytesRead = reader.read(hexByte);
if (bytesRead == -1)
return false;
builder.append(hexByte, 0, bytesRead);
builder.append(" ");
return bytesRead == 4;
}
}
private static final char m_hexCodes[] = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
private static final int m_shifts[] = { 60, 56, 52, 48, 44, 40, 36, 32, 28,
24, 20, 16, 12, 8, 4, 0 };
public static String tablify(byte[] bytes) {
return (new HexDump()).new HexTablifier().format(HexDump.toHex(bytes));
}
public static String tablify(byte[] bytes, int row) {
return (new HexDump()).new HexTablifier(row).format(HexDump
.toHex(bytes));
}
public static String tablify(byte[] bytes, int row, String pre) {
return (new HexDump()).new HexTablifier(row, pre).format(HexDump
.toHex(bytes));
}
public static String tablify(String hex, int row, String pre, String post) {
return (new HexDump()).new HexTablifier(row, pre, post).format(hex);
}
private static String toHex(final long value, final int digitNum) {
StringBuilder result = new StringBuilder(digitNum);
for (int j = 0; j < digitNum; j++) {
int index = (int) ((value >> m_shifts[j + (16 - digitNum)]) & 15);
result.append(m_hexCodes[index]);
}
return result.toString();
}
public static String toHex(final byte value) {
return toHex(value, 2);
}
public static String toHex(final short value) {
return toHex(value, 4);
}
public static String toHex(final int value) {
return toHex(value, 8);
}
public static String toHex(final long value) {
return toHex(value, 16);
}
public static String toHex(final byte[] value) {
return toHex(value, 0, value.length);
}
public static String toHex(final byte[] value, final int offset,
final int length) {
StringBuilder retVal = new StringBuilder();
int end = offset + length;
for (int x = offset; x < end; x++)
retVal.append(toHex(value[x]));
return retVal.toString();
}
public static byte[] restoreBytes(String hex) {
byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < bytes.length; ++i) {
int c1 = charToNumber(hex.charAt(2 * i));
int c2 = charToNumber(hex.charAt(2 * i + 1));
if (c1 == -1 || c2 == -1) {
return null;
}
bytes[i] = (byte) ((c1 << 4) + c2);
}
return bytes;
}
private static int charToNumber(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'a' && c <= 'f') {
return c - 'a' + 0xa;
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 0xA;
} else {
return -1;
}
}
}
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
/**
* Created by linving on 2016/11/12.
*/
public class MD5Util {
public static String getStringMD5(String value) {
if (value == null || value.trim().length() < 1) {
return null;
}
try {
return getMD5(value.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public static String getMD5(byte[] source) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
return HexDump.toHex(md5.digest(source));
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
Test :
import java.util.Map;
/**
* Created by linving on 2016/11/10.
*/
public class Test {
public static void main(String[] args) {
testRSA();
testAES();
tetsMD5();
}
private static void testAES() {
String data = "adcb";
System.out.println("AES加密前:" + data);
String key = "123456";
System.out.println("AES加密密钥和解密密钥:" + key);
String encrypt = AESUtil.aesEncrypt(data, key);
System.out.println("AES加密后:" + encrypt);
String decrypt = AESUtil.aesDecrypt(encrypt, key);
System.out.println("AES解密后:" + decrypt);
}
private static void testRSA() {
String data = "adsbc";
String publicKey = "";
String privateKey = "";
System.out.println("RSA原始数据: " + data);
Map<String, String> keyPair = RSAUtil.generateKeyPair();
publicKey = keyPair.get("publicKey");
privateKey = keyPair.get("privateKey");
System.out.println("RSA公钥: " + publicKey);
System.out.println("RSA私钥: " + privateKey);
String encryptData = RSAUtil.encrypt(publicKey, data);
System.out.println("RSA加密数据: " + encryptData);
String decryptData = RSAUtil.decrypt(privateKey, encryptData);
System.out.println("RSA解密数据: " + decryptData);
}
private static void tetsMD5() {
String data = "adsbc";
System.out.println("MD5原始数据: " + data);
String encryptData = MD5Util.getStringMD5(data);
System.out.println("MD5 加密数据: " + encryptData);
}
}
结果:
RSA原始数据: adsbc
RSA公钥: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUnEo/9+NI8GJbQtwl6X7MuALqe7YzuDNEeGn
3zEuiktxbXj53duJoYtGqO+rY+Vae7Ypt7UwolgnFtfJbfSmoBJc7wuBPOdTFkpsb7nYZXTvNoFI
fYdjT2mQgcOnZGSoz7alApPQ1sxXkkZ2tx+H+hsSaHxTBHW1Pq6Eyqi8LQIDAQAB
RSA私钥: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALBScSj/340jwYltC3CXpfsy4Aup
7tjO4M0R4affMS6KS3FtePnd24mhi0ao76tj5Vp7tim3tTCiWCcW18lt9KagElzvC4E851MWSmxv
udhldO82gUh9h2NPaZCBw6dkZKjPtqUCk9DWzFeSRna3H4f6GxJofFMEdbU+roTKqLwtAgMBAAEC
gYEAjAquvfWcRKllihUFxQNtXTpnIFxzy9dkTPwq0f4/PcuxaAGe2DYRrBqWWCTNVr8c5uTjJfc2
/c2zXjiSYvXmHS8EGFglwsJ8Dos+FiPtWTJl0Xo3Qhnbs2+F2z9Idgg0ddzrLK5r2o6l8VWuv/43
vdrjnvc4ArF/Kas/RHKyzzECQQDlVI2aiAqkOjs44sxr2rrRZRcRp5qxz8k/M31yRJnHWEVL6DXx
9IxGtkZNYdaD6fHgfbxd/5Xano7iyxvoJGmjAkEAxNPEh1ZW8SFQaE9mt/AMU6OMDM6F399uunOs
7yzz6vCUxLOIko6oyFj0WiilQEr9Y1wr1EZGkcMHYeJFK1k/7wJANJqtlKnqDvvQg976Vy8oNUoD
/ae9g1YParDr8J8tyx1DYAMXBLY8yyeafruXklDCi+UrpUAwZqKCUiGW+CwKEwJBAMHiTMx3+0qp
41ftJyT3fF0DVJjk8zD1GlDmU6qCoH+EnzcoFtcvWgmIvqL1ONsdQ38Vs0L2OtuovuPoDPTHhNcC
QBkOkrgFhJYnmDDTMUj4TCEO64RIdOyzzpFeQ0TgpjMJ99QOv8Q2kEFpylCw9bYMk1uioCStYSR8
ZOhE+H2N+yg=
RSA加密数据: Olsmy/qEigtaXIhlY8g41ktk1pXo/Kr098hA0keGM718yc6vnS2Mzc0YFXCQUMnpYS3ZEa7mm0Lg
CBIQNaPC8LPRmVS+giXui5Us9vbtYmejSRC0aDqnFqlONaoQidxHGSow65vpvgPTTfm3Hec/xOnC
6iEaslW4bsaEQcTHm6k=
RSA解密数据: adsbc
AES加密前:adcb
AES加密密钥和解密密钥:123456
AES加密后:F0QsZk5pFhDME01ZT7sQ0Q==
AES解密后:adcb
MD5原始数据: adsbc
MD5 加密数据: 51d84a98aeb971d801a9e1bed8803bd1
Process finished with exit code 0
这就是常用的加密算法了, 通常如果数据比较隐私的话,会采用多重加密算法。比如先经过 RSA 再经过 AES 算法进行加密。
用RSA算法将AES的秘钥和数据绑定在一起,解密后拿到AES的秘钥再解密。
更多精彩内容:
http://jblog.top/