【前言】
本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及使用方法和例子
【最简单的加密】
1.简单的概念
明文:加密前的信息
密文:机密后的信息
算法:加密或解密的算法
密钥:算法使用的钥匙(读作miyao,正确应该是miyue,但是大家都读miyao)
2.简单的例子
将123456每位数字都加1后得到234567,
其中123456就是明文,234567就是密文,加密密钥就是1,加密算法是每位加
3.对称加密和非对称加密
以上为例,
123456-->234567的加密密钥就是1,加密算法是每位+
234567-->123456的解密密钥也是1,解密算法是每位-
其中加密算法(+)和解密算法(-)相对称,这种加密算法就称作对称加密,
同样,如果加密算法和解密算法不对称就称之为非对称加密。
4.算法举例
众多的加密手段大致可以分为单项加密和双向加密。单项加密指通过对数据进行摘要计算生成密文,密文不可逆推还原,比如有Base64、MD5、SHA等;双向加密则相反,指可以把密文逆推还原成明文,其中双向加密又分为对称加密和非对称加密。对称加密是指数据使用者必须拥有同样的密钥才可以进行加密解密,就像大家共同约定了一组暗号一样,对称加密的手段有DES、3DES、AES、IDEA、RC4、RC5等;而非对称加密相对于对称加密而言,无需拥有同一组密钥,它是一种“信息公开的密钥交换协议”。非对称加密需要公开密钥和私有密钥两组密钥,公开密钥和私有密钥是配对起来的,也就是说使用公开密钥进行数据加密,只有对应的私有密钥才能进行解密。此类的加密手段有RSA、DSA等
对称加密算法:DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法,AES算法。
非对称加密算法:RSA、Elgamal、背包算法、Rabin、D-H、ECC。
经典的哈希算法:MD2、MD4、MD5 和 SHA-1(目的是将任意长输入通过算法变为固定长输出,且保证输入变化一点输出都不同,且不能反向解密)
5.经典算法实现
5.1:AES算法
packagecom.meng.study.security;importjava.security.SecureRandom;importjavax.crypto.Cipher;importjavax.crypto.KeyGenerator;importjavax.crypto.SecretKey;importjavax.crypto.spec.SecretKeySpec;public classAESUtil {/*** AES加密
*
*@paramcontent
* 待加密的内容
*@paramencryptKey
* 加密密钥
*@return加密后的byte[]
*@throwsException*/
public static byte[] aesEncryptToBytes(String content, String encryptKey) throwsException {
KeyGenerator kgen= KeyGenerator.getInstance("AES");
SecureRandom random= SecureRandom.getInstance("SHA1PRNG");
random.setSeed(encryptKey.getBytes());
kgen.init(128, random);
SecretKey secretKey= new SecretKeySpec(kgen.generateKey().getEncoded(), "AES");
Cipher cipher= Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);return cipher.doFinal(content.getBytes("UTF-8"));
}/*** AES加密为base 64 code
*
*@paramcontent
* 待加密的内容
*@paramencryptKey
* 加密密钥
*@return加密后的base 64 code
*@throwsException*/
public static String aesEncrypt(String content, String encryptKey) throwsException {returnBASE64Util.base64Encode(aesEncryptToBytes(content, encryptKey));
}/*** AES解密
*
*@paramencryptBytes
* 待解密的byte[]
*@paramdecryptKey
* 解密密钥
*@return解密后的String
*@throwsException*/
public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throwsException {
KeyGenerator kgen= KeyGenerator.getInstance("AES");
SecureRandom random= SecureRandom.getInstance("SHA1PRNG");
random.setSeed(decryptKey.getBytes());
kgen.init(128, random);
SecretKey secretKey= new SecretKeySpec(kgen.generateKey().getEncoded(), "AES");
Cipher cipher= Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);byte[] decryptBytes =cipher.doFinal(encryptBytes);return newString(decryptBytes);
}/*** 将base 64 code AES解密
*
*@paramencryptStr
* 待解密的base 64 code
*@paramdecryptKey
* 解密密钥
*@return解密后的string
*@throwsException*/
public static String aesDecrypt(String encryptStr, String decryptKey) throwsException {returnaesDecryptByBytes(BASE64Util.base64Decode(encryptStr), decryptKey);
}
}
显示代码
5.2:3DES算法
packagecom.meng.study.security;importjava.io.UnsupportedEncodingException;importjavax.crypto.Cipher;importjavax.crypto.SecretKey;importjavax.crypto.spec.SecretKeySpec;importorg.apache.log4j.Logger;importcom.meng.study.cache.GuavaCacheUtil;/***
*@authorzhenbinmeng
**/
public classDESUtil {private static Logger logger = Logger.getLogger(DESUtil.class);//定义加密算法,DESede(即3DES)
private static final String DESede = "DESede";private static final String PASSWORD_CRYPT_KEY = "2015mengzhenbinStudyForSecurity@DESede";/*** 加密方法
*
*@paramsrc
* 源数据的字节数组
*@return
*/
public static byte[] encryptMode(byte[] src) {try{
SecretKey deskey= new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); //生成密钥
Cipher c1 = Cipher.getInstance(DESede); //实例化负责加密/解密的Cipher工具类
c1.init(Cipher.ENCRYPT_MODE, deskey); //初始化为加密模式
returnc1.doFinal(src);
}catch(Exception e) {
logger.error("DesUtil.encryptMode error", e);
e.printStackTrace();
}return null;
}/*** 加密方法(BASE64编码返回)
*
*@paramsrc
* 源数据的字节数组
*@return
*/
public static String encryptModeBase64(byte[] src) {try{
SecretKey deskey= new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); //生成密钥
Cipher c1 = Cipher.getInstance(DESede); //实例化负责加密/解密的Cipher工具类
c1.init(Cipher.ENCRYPT_MODE, deskey); //初始化为加密模式
returnBASE64Util.base64Encode(c1.doFinal(src));
}catch(Exception e) {
logger.error("DesUtil.encryptMode error", e);
e.printStackTrace();
}return null;
}/*** 解密函数
*
*@paramsrc
* 密文的字节数组
*@return
*/
public static byte[] decryptMode(byte[] src) {try{
SecretKey deskey= newSecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede);
Cipher c1=Cipher.getInstance(DESede);
c1.init(Cipher.DECRYPT_MODE, deskey);//初始化为解密模式
returnc1.doFinal(src);
}catch(Exception e) {
logger.error("DesUtil.decryptMode error", e);
e.printStackTrace();
}return null;
}/*** 解密函数(BASE64解码后解密)
*
*@paramsrc
* 密文的字节数组
*@return
*/
public staticString decryptModeBase64(String src) {try{
SecretKey deskey= newSecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede);
Cipher c1=Cipher.getInstance(DESede);
c1.init(Cipher.DECRYPT_MODE, deskey);//初始化为解密模式
return newString(c1.doFinal(BASE64Util.base64Decode(src)));
}catch(Exception e) {
logger.error("DesUtil.decryptMode error", e);
e.printStackTrace();
}return null;
}/** 根据字符串生成密钥字节数组
*
* @param keyStr 密钥字符串
*
* @return
*
* @throws UnsupportedEncodingException*/
public static byte[] build3DesKey(String keyStr) throwsUnsupportedEncodingException {byte[] key = new byte[24]; //声明一个24位的字节数组,默认里面都是0
byte[] temp = keyStr.getBytes("UTF-8"); //将字符串转成字节数组
/** 执行数组拷贝 System.arraycopy(源数组,从源数组哪里开始拷贝,目标数组,拷贝多少位)*/
if (key.length >temp.length) {//如果temp不够24位,则拷贝temp数组整个长度的内容到key数组中
System.arraycopy(temp, 0, key, 0, temp.length);
}else{//如果temp大于24位,则拷贝temp数组24个长度的内容到key数组中
System.arraycopy(temp, 0, key, 0, key.length);
}returnkey;
}
}
显示代码
5.3:MD5算法
packagecom.meng.study.security;importjava.security.MessageDigest;public classMD5Util {/*** 获取byte[]的md5值
*
*@parambytes
* byte[]
*@returnmd5
*@throwsException*/
public static byte[] md5(byte[] bytes) throwsException {
MessageDigest md= MessageDigest.getInstance("MD5");
md.update(bytes);returnmd.digest();
}/*** 获取字符串md5值
*
*@parammsg
*@returnmd5
*@throwsException*/
public static byte[] md5(String msg) throwsException {returnmd5(msg.getBytes());
}/*** 获取字符串md5值
*
*@parammsg
*@returnmd5
*@throwsException*/
public static String md5Hex(String msg) throwsException {byte[] messageDigest =md5(msg.getBytes());//Create Hex String
StringBuffer hexString = newStringBuffer();//字节数组转换为 十六进制 数
for (int i = 0; i < messageDigest.length; i++) {
String shaHex= Integer.toHexString(messageDigest[i] & 0xFF);if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}returnhexString.toString();
}/*** 结合base64实现md5加密
*
*@parammsg
* 待加密字符串
*@return获取md5后转为base64
*@throwsException*/
public static String md5Base64(String msg) throwsException {returnBASE64Util.base64Encode(md5(msg));
}
}
显示代码
5.4:SHA算法
packagecom.meng.study.security;importjava.security.MessageDigest;public classSHAUtil {public staticString SHA1(String decript) {try{
MessageDigest digest= java.security.MessageDigest.getInstance("SHA-1");
digest.update(decript.getBytes());byte messageDigest[] =digest.digest();//Create Hex String
StringBuffer hexString = newStringBuffer();//字节数组转换为 十六进制 数
for (int i = 0; i < messageDigest.length; i++) {
String shaHex= Integer.toHexString(messageDigest[i] & 0xFF);if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}returnhexString.toString();
}catch(Exception e) {
e.printStackTrace();
}return "";
}public staticString SHA(String decript) {try{
MessageDigest digest= java.security.MessageDigest.getInstance("SHA");
digest.update(decript.getBytes());byte messageDigest[] =digest.digest();//Create Hex String
StringBuffer hexString = newStringBuffer();//字节数组转换为 十六进制 数
for (int i = 0; i < messageDigest.length; i++) {
String shaHex= Integer.toHexString(messageDigest[i] & 0xFF);if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}returnhexString.toString();
}catch(Exception e) {
e.printStackTrace();
}return "";
}
}
显示代码
5.5:RSA算法
packagecom.meng.study.security;importjava.math.BigInteger;importjava.security.KeyFactory;importjava.security.KeyPair;importjava.security.KeyPairGenerator;importjava.security.NoSuchAlgorithmException;importjava.security.interfaces.RSAPrivateKey;importjava.security.interfaces.RSAPublicKey;importjava.security.spec.RSAPrivateKeySpec;importjava.security.spec.RSAPublicKeySpec;importjava.util.HashMap;importjavax.crypto.Cipher;public classRSAUtil {/*** 生成公钥和私钥
*
*@throwsNoSuchAlgorithmException
**/
public static HashMap getKeys() throwsNoSuchAlgorithmException {
HashMap map = new HashMap();
KeyPairGenerator keyPairGen= KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
KeyPair keyPair=keyPairGen.generateKeyPair();
RSAPublicKey publicKey=(RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();
map.put("public", publicKey);
map.put("private", privateKey);returnmap;
}/*** 使用模和指数生成RSA公钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
*@parammodulus
* 模
*@paramexponent
* 指数
*@return
*/
public staticRSAPublicKey getPublicKey(String modulus, String exponent) {try{
BigInteger b1= newBigInteger(modulus);
BigInteger b2= newBigInteger(exponent);
KeyFactory keyFactory= KeyFactory.getInstance("RSA");
RSAPublicKeySpec keySpec= newRSAPublicKeySpec(b1, b2);return(RSAPublicKey) keyFactory.generatePublic(keySpec);
}catch(Exception e) {
e.printStackTrace();return null;
}
}/*** 使用模和指数生成RSA私钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
*@parammodulus
* 模
*@paramexponent
* 指数
*@return
*/
public staticRSAPrivateKey getPrivateKey(String modulus, String exponent) {try{
BigInteger b1= newBigInteger(modulus);
BigInteger b2= newBigInteger(exponent);
KeyFactory keyFactory= KeyFactory.getInstance("RSA");
RSAPrivateKeySpec keySpec= newRSAPrivateKeySpec(b1, b2);return(RSAPrivateKey) keyFactory.generatePrivate(keySpec);
}catch(Exception e) {
e.printStackTrace();return null;
}
}/*** 公钥加密
*
*@paramdata
*@parampublicKey
*@return*@throwsException*/
public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throwsException {
Cipher cipher= Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);//模长
int key_len = publicKey.getModulus().bitLength() / 8;//加密数据长度 <= 模长-11
String[] datas = splitString(data, key_len - 11);
String mi= "";//如果明文长度大于模长-11则要分组加密
for(String s : datas) {
mi+=bcd2Str(cipher.doFinal(s.getBytes()));
}returnmi;
}/*** 私钥解密
*
*@paramdata
*@paramprivateKey
*@return*@throwsException*/
public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throwsException {
Cipher cipher= Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);//模长
int key_len = privateKey.getModulus().bitLength() / 8;byte[] bytes =data.getBytes();byte[] bcd =ASCII_To_BCD(bytes, bytes.length);//如果密文长度大于模长则要分组解密
String ming = "";byte[][] arrays =splitArray(bcd, key_len);for (byte[] arr : arrays) {
ming+= newString(cipher.doFinal(arr));
}returnming;
}/*** ASCII码转BCD码
**/
public static byte[] ASCII_To_BCD(byte[] ascii, intasc_len) {byte[] bcd = new byte[asc_len / 2];int j = 0;for (int i = 0; i < (asc_len + 1) / 2; i++) {
bcd[i]= asc_to_bcd(ascii[j++]);
bcd[i]= (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
}returnbcd;
}public static byte asc_to_bcd(byteasc) {bytebcd;if ((asc >= '0') && (asc <= '9'))
bcd= (byte) (asc - '0');else if ((asc >= 'A') && (asc <= 'F'))
bcd= (byte) (asc - 'A' + 10);else if ((asc >= 'a') && (asc <= 'f'))
bcd= (byte) (asc - 'a' + 10);elsebcd= (byte) (asc - 48);returnbcd;
}/*** BCD转字符串*/
public static String bcd2Str(byte[] bytes) {char temp[] = new char[bytes.length * 2], val;for (int i = 0; i < bytes.length; i++) {
val= (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
temp[i* 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
val= (char) (bytes[i] & 0x0f);
temp[i* 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
}return newString(temp);
}/*** 拆分字符串*/
public static String[] splitString(String string, intlen) {int x = string.length() /len;int y = string.length() %len;int z = 0;if (y != 0) {
z= 1;
}
String[] strings= new String[x +z];
String str= "";for (int i = 0; i < x + z; i++) {if (i == x + z - 1 && y != 0) {
str= string.substring(i * len, i * len +y);
}else{
str= string.substring(i * len, i * len +len);
}
strings[i]=str;
}returnstrings;
}/*** 拆分数组*/
public static byte[][] splitArray(byte[] data, intlen) {int x = data.length /len;int y = data.length %len;int z = 0;if (y != 0) {
z= 1;
}byte[][] arrays = new byte[x +z][];byte[] arr;for (int i = 0; i < x + z; i++) {
arr= new byte[len];if (i == x + z - 1 && y != 0) {
System.arraycopy(data, i* len, arr, 0, y);
}else{
System.arraycopy(data, i* len, arr, 0, len);
}
arrays[i]=arr;
}returnarrays;
}
}
显示代码
5.6:Base64算法
packagecom.meng.study.security;importsun.misc.BASE64Decoder;importsun.misc.BASE64Encoder;
@SuppressWarnings("restriction")public classBASE64Util {/*** base 64 encode
*
*@parambytes
* 待编码的byte[]
*@return编码后的base 64 code*/
public static String base64Encode(byte[] bytes) {return newBASE64Encoder().encode(bytes);
}/*** base 64 decode
*
*@parambase64Code
* 待解码的base 64 code
*@return解码后的byte[]
*@throwsException*/
public static byte[] base64Decode(String base64Code) throwsException {return newBASE64Decoder().decodeBuffer(base64Code);
}
}
显示代码
5.7:测试代码
packagecom.meng.study.security;importjava.security.interfaces.RSAPrivateKey;importjava.security.interfaces.RSAPublicKey;importjava.util.HashMap;/*** 编码工具类 1.将byte[]转为各种进制的字符串 2.base 64 encode 3.base 64 decode
*
*@authoruikoo9
*@version0.0.5.20140601*/
public classEncodeUtilTest {public static void main(String[] args) throwsException {
String msg= "我爱你";
System.out.println("转换前:" +msg);//==Base64==
String base64Str =BASE64Util.base64Encode(msg.getBytes());
System.out.println("Base64转换后:" +base64Str);
System.out.println("Base64解码后:" + newString(BASE64Util.base64Decode(base64Str)));//==Md5==
String md5Base64Str =MD5Util.md5Base64(msg);
System.out.println("Md5后Base编码转换后:" +md5Base64Str);//==Des==
byte[] des =DESUtil.encryptMode(msg.getBytes());
System.out.println("【DES加密后】:" + newString(des));byte[] myMsgArr =DESUtil.decryptMode(des);
System.out.println("【DES解密后】:" + newString(myMsgArr));
String desBase64Str=DESUtil.encryptModeBase64(msg.getBytes());
System.out.println("Des后Base64编码转换后:" +desBase64Str);
System.out.println("Base64解码后Des转换后:" + newString(DESUtil.decryptModeBase64(desBase64Str)));//==Aes==
String aesKey = "123456";
String aesEnStr=AESUtil.aesEncrypt(msg,aesKey);
System.out.println("【AES加密Base64编码后】:" +aesEnStr);
String aesDeStr=AESUtil.aesDecrypt(aesEnStr,aesKey);
System.out.println("【Base64解码AES解密后】:" +aesDeStr);//==Rsa==
HashMap keys =RSAUtil.getKeys();
RSAPublicKey publicKey= (RSAPublicKey) keys.get("public");
RSAPrivateKey privateKey= (RSAPrivateKey) keys.get("private");
RSAPublicKey pubKey=RSAUtil.getPublicKey(publicKey.getModulus().toString(), publicKey.getPublicExponent().toString());
RSAPrivateKey priKey=RSAUtil.getPrivateKey(privateKey.getModulus().toString(), privateKey.getPrivateExponent().toString());
String rsaEnStr=RSAUtil.encryptByPublicKey(msg, pubKey);
System.out.println("【RSA公钥加密后】:" +rsaEnStr);
String rsaDeStr=RSAUtil.decryptByPrivateKey(rsaEnStr, priKey);
System.out.println("【RSA私钥解密后】:" +rsaDeStr);
}
}
显示代码