http://blog.csdn.net/qq_26685493/article/details/51179378
目前数据加密技术根据加密密钥类型可分为公私钥加密(对称加密)和公钥加密(非对称加密)两种。
1 对称加密(AES为例)
对称加密是通信双方在加/解密过程中使用它们共享的单一密钥,算法简单和加密速度快,是目前主流的密码体制之一。
最常用的对称加密算法是DES(数据加密标准)算法,但由于DES密钥长度较短,现在由AES(对称高级数据加密标准)取代。
AES的加密算法的数据处理单位是字节,128位的比特信息被分成16个字节,按顺序复制到一个4*4的矩阵中,成为状态,AES的所有变换都是基于状态
矩阵的变换。
DES加密解密步骤:
- 生成一个长度至少大于8位的字符串作为工作密钥,会使用该密钥作为加密和解密的操作
DESKeySpec keySpec = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("des");
SecretKey secretKey = keyFactory.generateSecret(keySpec);
- 加密
Cipher cipher = Cipher.getInstance("des");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new SecureRandom());
byte[] cipherData = cipher.doFinal(plainText.getBytes());
- 解密
cipher.init(Cipher.DECRYPT_MODE, secretKey, new SecureRandom());
byte[] plainData = cipher.doFinal(cipherData);
String plainText = new String(plainData);
2 非对称加密(RSA为例)
非对称加密是加/解密钥不同(公钥加密、私钥解密),密钥管理简单,RSA是非对称加密最著名的公钥密码算法。
RSA算法是基于大质数的因数分解的公钥体系,简单讲,就是两个很大的质数,一个作为公钥,另一个作为私钥,如用其中一个加密,则用另一个解密。
密钥长度从40到2048位可变,密钥越长,加密效果越好,但加密解密的开销也大
RSA加密解密步骤:
-
服务器发送数据给客户端时使用私钥加密,并且使用加密之后的数据和私钥生成数字签名并发送给客户端
-
客户端接收到服务器发送的数据会使用公钥对数据进行解密,并且根据加密数据和公钥验证数字签名的有效性,防止加密数据在传输过程中被
第三方进行修改 -
客户端发送数据给服务器使用公钥进行加密,服务器接收到加密数据之后使用私钥进行解密
创建密钥:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("rsa");
keyPairGenerator.initialize(1024); // 密钥推荐长度2014位
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic(); // 公钥
PrivateKey privatekey = keyPair.getPrivate(); // 私钥
// 服务器使用私钥加密
Cipher cipher = Cipher.getInstance("rsa");
cipher.init(Cipher.ENCRYPT_MODE, privateKey, new SecureRandom());
byte[] cipherData = cipher.doFinal(plainText.getBytes());
// 客户端公钥解密
cipher.init(Cipher.DECRYPT_MODE, publicKey, new SecureRandom());
byte[] plainData = cipher.doFinal(cipherData);
// 服务器根据私钥加密数据生成数字签名
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(privateKey);
signature.update(cipherData);
byte[] signData = signature.sign();
// 客户端根据公钥、加密数据验证是否被修改过
signature.initVerify(publicKey);
signature.update(cipherData);
boolean status = signature.verify(signData);
3 md5加密算法
md5加密算法是一种单向加密算法,只能加密,无法解密。
md5加密步骤:
-
将其中的每个字节转成十六进制:byye类型的数据最高位是符号位,通过和0xff进行与操作,转换为int类型的正整数
-
如果该正数小于16(长度为1个字符),前面拼接0占位;确保最后生成的是32为字符串
String plainText = "Hello world";
MessageDigest md5 = MessageDigest.getInstance("md5");
byte[] cipherData = md5.digest(plainText.getBytes());
StringBuilder builder = new StringBuilder();
for (byte cipher : ciperData) {
String toHexStr = Integer.toHexString(cipher & 0xff);
builder.append(toHexStr.length() == 1 ? "0" + toHexStr : toHexStr);
}
System.out.println(builder.toString());
4 base64
使用base64算法通常用作对二进制数据进行加密,加密之后的数据不易被肉眼识别。严格来说,经过base64加密的数据其实没有安全性可保密,因为它的加密解密算法都是公开的。经过标准的base64算法加密后的数据,通常包含/、+、=等特殊符号,不适合作为url参数传递。
base64加密解密步骤:
- 加密
BASE64Encoder encoder = new BASE64Encoder();
String cipherText = encoder.encode(plainText.getBytes()); // 加密
- 解密
BASE64Decoder decoder = new BASE64Decoder();
plainText = new String(decoder.decodeBuffer(cipherText));
工具类
package com.excelsoft.common.crypto;
import java.io.IOException;
import java.security.Key;
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.SecureRandom;
import java.security.Signature;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* 功能简述: 加密解密工具类,对MD5/BASE64/DES/RSA等算法提供了包装.
* @author Nick Xu
* @version 1.0
*/
public class EncryptUtil {
private static Log logger = LogFactory.getLog(EncryptUtil.class);
private static final int KEY_SIZE = 1024;
private static final String MD5_ALGORITHM= "md5";
private static final String DES_ALGORITHM= "des";
private static final String RSA_ALGORITHM= "rsa";
private static final String SIGNATURE_ALGORITHM= "MD5withRSA";
private static MessageDigest md5;
private static BASE64Encoder encoder;
private static BASE64Decoder decoder;
private static SecureRandom random;
private static KeyPair keyPair;
private EncryptUtil() {
}
static {
try {
md5 = MessageDigest.getInstance(MD5_ALGORITHM);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
keyPair = keyPairGenerator.generateKeyPair();
}
catch (NoSuchAlgorithmException e) {
// Exception handler
logger.error(e);
}
encoder = new BASE64Encoder();
decoder = new BASE64Decoder();
random = new SecureRandom();
}
/**
* 功能简述: 使用md5进行单向加密.
*/
public static String encryptMD5(String plainText) {
byte[] cipherData = md5.digest(plainText.getBytes());
StringBuilder builder = new StringBuilder();
for(byte cipher : cipherData) {
String toHexStr = Integer.toHexString(cipher & 0xff);
builder.append(toHexStr.length() == 1 ? "0" + toHexStr : toHexStr);
}
return builder.toString();
}
/**
* 功能简述: 使用BASE64进行加密.
* @param plainData 明文数据
* @return 加密之后的文本内容
*/
public static String encryptBASE64(byte[] plainData) {
return encoder.encode(plainData);
}
/**
* 功能简述: 使用BASE64进行解密.
* @param cipherText 密文文本
* @return 解密之后的数据
*/
public static byte[] decryptBASE64(String cipherText) {
byte[] plainData = null;
try {
plainData = decoder.decodeBuffer(cipherText);
}
catch (IOException e) {
// Exception handler
logger.error(e);
}
return plainData;
}
/**
* 功能简述: 使用DES算法进行加密.
* @param plainData 明文数据
* @param key 加密密钥
* @return
*/
public static byte[] encryptDES(byte[] plainData, String key) {
return processCipher(plainData, createSecretKey(key), Cipher.ENCRYPT_MODE, DES_ALGORITHM);
}
/**
* 功能简述: 使用DES算法进行解密.
* @param cipherData 密文数据
* @param key 解密密钥
* @return
*/
public static byte[] decryptDES(byte[] cipherData, String key) {
return processCipher(cipherData, createSecretKey(key), Cipher.DECRYPT_MODE, DES_ALGORITHM);
}
/**
* 功能简述: 根据key创建密钥SecretKey.
* @param key
* @return
*/
private static SecretKey createSecretKey(String key) {
SecretKey secretKey = null;
try {
DESKeySpec keySpec = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM);
secretKey = keyFactory.generateSecret(keySpec);
}
catch (Exception e) {
// Exception handler
logger.error(e);
}
return secretKey;
}
/**
* 功能简述: 加密/解密处理流程.
* @param processData 待处理的数据
* @param key 提供的密钥
* @param opsMode 工作模式
* @param algorithm 使用的算法
* @return
*/
private static byte[] processCipher(byte[] processData, Key key, int opsMode, String algorithm) {
try{
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(opsMode, key, random);
return cipher.doFinal(processData);
}
catch (Exception e) {
// Exception handler
logger.error(e);
}
return null;
}
/**
* 功能简述: 创建私钥,用于RSA非对称加密.
* @return
*/
public static PrivateKey createPrivateKey() {
return keyPair.getPrivate();
}
/**
* 功能简述: 创建公钥,用于RSA非对称加密.
* @return
*/
public static PublicKey createPublicKey() {
return keyPair.getPublic();
}
/**
* 功能简述: 使用RSA算法加密.
* @param plainData 明文数据
* @param key 密钥
* @return
*/
public static byte[] encryptRSA(byte[] plainData, Key key) {
return processCipher(plainData, key, Cipher.ENCRYPT_MODE, RSA_ALGORITHM);
}
/**
* 功能简述: 使用RSA算法解密.
* @param cipherData 密文数据
* @param key 密钥
* @return
*/
public static byte[] decryptRSA(byte[] cipherData, Key key) {
return processCipher(cipherData, key, Cipher.DECRYPT_MODE, RSA_ALGORITHM);
}
/**
* 功能简述: 使用私钥对加密数据创建数字签名.
* @param cipherData 已经加密过的数据
* @param privateKey 私钥
* @return
*/
public static byte[] createSignature(byte[] cipherData, PrivateKey privateKey) {
try {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateKey);
signature.update(cipherData);
return signature.sign();
}
catch (Exception e) {
// Exception handler
logger.error(e);
}
return null;
}
/**
* 功能简述: 使用公钥对数字签名进行验证.
* @param signData 数字签名
* @param publicKey 公钥
* @return
*/
public static boolean verifySignature(byte[] cipherData, byte[] signData, PublicKey publicKey) {
try {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicKey);
signature.update(cipherData);
return signature.verify(signData);
}
catch (Exception e) {
// Exception handler
logger.error(e);
}
return false;
}
}