1、为什么要用加密
网站中有很多类似金钱、密码等重要业务数据,一旦被监听、拦截,可能会造成严重的损失。
比如下图:
我们可以很容易的看到某个请求的相关参数数据
2、应用场景
加密算法有很多种应用场景,最常见的是用户登录、身份验证、验签等等。目的在于通过算法,将明文转换为密文。将明文转换为密文只是第一步,更深一步的做法是结合sessionId、随机数、token或者https等,最大限度的防止信息被盗取。
3、类型
加密算法通常分为对称性加密算法和非对称性加密算法。
3.1 对称性加密
只存在一把钥匙key,如果A想要与B通讯,那么A使用钥匙进行加密,B接收到密文的钥匙后,使用钥匙解密,获得明文信息。
优缺点:
效率高、使用维护简单,缺点就是密码一旦泄露,通讯信息就会暴露。
常用加密算法:
DES、三重DES、AES等,稍后会以AES为例,介绍具体用法。
3.2 非对称加密
非对称加密有两把钥匙:私钥和公钥。
这里有几个原则和前提需要先说明:
1)公钥和私钥是成对出现的。
2)公开的是公钥,私钥只有自己知道。
3)用公钥加密的信息,只能用对应的私钥进行解密。
A、B各有一对密钥,A的密钥包括:公钥01、私钥02,B的密钥包括:公钥03、私钥04。其中,A拥有B的公钥03,同样的,B也拥有A的公钥01。
当A要与B通讯时,A使用B的公钥03加密,当B拿到密文后,拿自己的私钥04解密。
优缺点:
非对称加密的优缺点正好与对称加密相反,可参照上面。
常用加密算法:
RSA,DSA,ECC
除了上面两种主要类型的加密算法,还有一大类是线性散列算法,也叫签名算法。常用算法有:MD5,SHA1,HMAC。这类算法可以生成一长串不可逆的密文,经常用在校验数据在传输过程中是否经过修改。
4、实例
场景:用户登录,使用res加密,前端js加密,后端解密。
4.1 js文件
//加密key
var key =CryptoJS.enc.Utf8.parse("*******");
//pwd为加密信息
var srcs = CryptoJS.enc.Utf8.parse(pwd);
var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
4.2 后台解密
/**
* 密钥,要与加密时的密钥保持一致
*/
private static final String KEY = "*******";
/**
* 算法
*/
private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
/**
* aes解密
*
* @param encrypt
* 内容
* @return
* @throws Exception
*/
public static String aesDecrypt(String encrypt) throws Exception {
return aesDecrypt(encrypt, KEY);
}
/**
* aes加密
*
* @param content
* @return
* @throws Exception
*/
public static String aesEncrypt(String content) throws Exception {
return aesEncrypt(content, KEY);
}
/**
* 将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 Base64.encodeBase64String(bytes);
}
/**
* base 64 decode
*
* @param base64Code
* 待解码的base 64 code
* @return 解码后的byte[]
* @throws Exception
*/
public static byte[] base64Decode(String base64Code) throws Exception{
return StringUtil.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);
}
/**
* 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);
Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.ENCRYPT_MODE,
new SecretKeySpec(encryptKey.getBytes(), "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)
throws Exception {
return base64Encode(aesEncryptToBytes(content, encryptKey));
}
/**
* AES解密
*
* @param encryptBytes
* 待解密的byte[]
* @param decryptKey
* 解密密钥
* @return 解密后的String
* @throws Exception
*/
public static String aesDecryptByBytes(byte[] encryptBytes,
String decryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
cipher.init(Cipher.DECRYPT_MODE,
new SecretKeySpec(decryptKey.getBytes(), "AES"));
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes);
}
/**
* 将base 64 code AES解密
*
* @param encryptStr
* 待解密的base 64 code
* @param decryptKey
* 解密密钥
* @return 解密后的string
* @throws Exception
*/
public static String aesDecrypt(String encryptStr, String decryptKey)
throws Exception {
return StringUtil.isEmpty(encryptStr) ? null : aesDecryptByBytes(
base64Decode(encryptStr), decryptKey);
}
public static void main(String[] args) throws Exception {
String content = "123456";
System.out.println("加密前:" + content);
String encrypt = aesEncrypt(content, KEY);
System.out.println("加密后:" + encrypt);
String decrypt = aesDecrypt(encrypt, KEY);
System.out.println("解密后:" + decrypt);
}
5、小结
上面说到对称加密和非对称加密各有优缺点,前者效率高,但密钥不安全;后者安全但加密解密时间较长。
实践中比较常用的做法是,采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据,这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。