1. 对称加密算法概述
对称加密算法是应用较早的加密算法, 技术成熟. 在对称加密算法中, 数据发信方将明文和加密密钥一起经过特殊加密算法处理后, 使其变成复杂的加密密文发送出去. 收信方收到密文后, 若想解读原文, 则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密, 才能使其恢复成可读明文.
在对称加密算法中, 使用的密钥只有一个, 发收信双方都使用这个密钥对数据进行加密和解密, 这就要求解密方事先必须知道加密密钥.
对称加密算法的特点是算法公开, 计算量小, 加密速度快, 加密效率高.
不足之处是, 交易双方都使用同样钥匙, 安全性得不到保证.
在计算机系统中广泛使用的对称加密算法有 DES 和 IDEA 等. 因为 DES 近年来屡屡被破解, 所以, 美国国家标准局倡导的 AES 即将作为新标准取代 DES.
2. 对称加密算法 - DES
DES 算法为密码体制中的对称密码体制, 又被称为美国数据加密标准, 是 1972 年美国 IBM 公司研制的对称密码体制加密算法.
明文按 64 位进行分组, 密钥长 64 位, 密钥事实上是 56 位参与 DES 运算 (第 8,16,24,32,40,48,56,64 位是校验位, 使得每个密钥都有奇数个 1) 分组后的明文组和 56 位的密钥按位替代或交换的方法形成密文组的加密方法.
引入 Bouncy Castle 依赖:
- org.bouncycastle
- bcprov-jdk15
- 1.46
引入 Commons Codec 依赖:
- commons-codec
- commons-codec
- 1.10
Java 代码实现:
- import java.security.Key;
- import java.security.Security;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import javax.crypto.SecretKeyFactory;
- import javax.crypto.spec.DESKeySpec;
- import org.apache.commons.codec.binary.Hex;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- public class DES {
- public static final String src = "des test";
- public static void main(String[] args) {
- jdkDES();
- bcDES();
- }
- // 用 jdk 实现:
- public static void jdkDES() {
- try {
- // 生成 KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
- keyGenerator.init(56);
- // 产生密钥
- SecretKey secretKey = keyGenerator.generateKey();
- // 获取密钥
- byte[] bytesKey = secretKey.getEncoded();
- // KEY 转换
- DESKeySpec desKeySpec = new DESKeySpec(bytesKey);
- SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
- Key convertSecretKey = factory.generateSecret(desKeySpec);
- // 加密
- Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("jdk des encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
- result = cipher.doFinal(result);
- System.out.println("jdk des decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- // 用 bouncy castle 实现:
- public static void bcDES() {
- try {
- Security.addProvider(new BouncyCastleProvider());
- // 生成 KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("DES", "BC");
- keyGenerator.getProvider();
- keyGenerator.init(56);
- // 产生密钥
- SecretKey secretKey = keyGenerator.generateKey();
- // 获取密钥
- byte[] bytesKey = secretKey.getEncoded();
- // KEY 转换
- DESKeySpec desKeySpec = new DESKeySpec(bytesKey);
- SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
- Key convertSecretKey = factory.generateSecret(desKeySpec);
- // 加密
- Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("bc des encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
- result = cipher.doFinal(result);
- System.out.println("bc des decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
应用例子:
3. 对称加密算法 - 3DES
密码学中, 三重数据加密算法 (英语: Triple Data Encryption Algorithm, 缩写为 TDEA,Triple DEA), 或称 3DES(Triple DES), 是一种对称密钥加密块密码, 相当于是对每个数据块应用三次数据加密标准(DES) 算法. 由于计算机运算能力的增强, 原版 DES 密码的密钥长度变得容易被暴力破解; 3DES 即是设计用来提供一种相对简单的方法, 即通过增加 DES 的密钥长度来避免类似的攻击, 而不是设计一种全新的块密码算法.
Java 代码实现:
- import java.security.Key;
- import java.security.SecureRandom;
- import java.security.Security;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import javax.crypto.SecretKeyFactory;
- import javax.crypto.spec.DESedeKeySpec;
- import org.apache.commons.codec.binary.Hex;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- public class DES3 {
- public static final String src = "3des test";
- public static void main(String[] args) {
- jdk3DES();
- bc3DES();
- }
- // 用 jdk 实现:
- public static void jdk3DES() {
- try {
- // 生成 KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
- // 必须长度是: 112 或 168
- // keyGenerator.init(168);
- keyGenerator.init(new SecureRandom());
- // 产生密钥
- SecretKey secretKey = keyGenerator.generateKey();
- // 获取密钥
- byte[] bytesKey = secretKey.getEncoded();
- // KEY 转换
- DESedeKeySpec desKeySpec = new DESedeKeySpec(bytesKey);
- SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
- Key convertSecretKey = factory.generateSecret(desKeySpec);
- // 加密
- Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("jdk 3des encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
- result = cipher.doFinal(result);
- System.out.println("jdk 3des decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- // 用 bouncy castle 实现:
- public static void bc3DES() {
- try {
- Security.addProvider(new BouncyCastleProvider());
- // 生成 KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede", "BC");
- keyGenerator.getProvider();
- keyGenerator.init(168);
- // 产生密钥
- SecretKey secretKey = keyGenerator.generateKey();
- // 获取密钥
- byte[] bytesKey = secretKey.getEncoded();
- // KEY 转换
- DESedeKeySpec desKeySpec = new DESedeKeySpec(bytesKey);
- SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
- Key convertSecretKey = factory.generateSecret(desKeySpec);
- // 加密
- Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("bc 3des encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
- result = cipher.doFinal(result);
- System.out.println("bc 3des decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
4. 对称加密算法 - AES
高级加密标准 (英语: Advanced Encryption Standard, 缩写: AES), 在密码学中又称 Rijndael 加密法, 是美国联邦政府采用的一种区块加密标准. 这个标准用来替代原先的 DES, 已经被多方分析且广为全世界所使用. 经过五年的甄选流程, 高级加密标准由美国国家标准与技术研究院(NIST) 于 2001 年 11 月 26 日发布于 FIPS PUB 197, 并在 2002 年 5 月 26 日成为有效的标准. 2006 年, 高级加密标准已然成为对称密钥加密中最流行的算法之一.
该算法为比利时密码学家 Joan Daemen 和 Vincent Rijmen 所设计, 结合两位作者的名字, 以 Rijndael 为名投稿高级加密标准的甄选流程.(Rijndael 的发音近于 "Rhine doll")
Java 代码实现:
- import java.security.Key;
- import java.security.Security;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.SecretKeySpec;
- import org.apache.commons.codec.binary.Hex;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- public class AES {
- public static final String src = "aes test";
- public static void main(String[] args) {
- jdkAES();
- bcAES();
- }
- // 用 jdk 实现:
- public static void jdkAES() {
- try {
- // 生成 KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
- keyGenerator.init(128);
- // 产生密钥
- SecretKey secretKey = keyGenerator.generateKey();
- // 获取密钥
- byte[] keyBytes = secretKey.getEncoded();
- // KEY 转换
- Key key = new SecretKeySpec(keyBytes, "AES");
- // 加密
- Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, key);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("jdk aes encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, key);
- result = cipher.doFinal(result);
- System.out.println("jdk aes decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- // 用 bouncy castle 实现:
- public static void bcAES() {
- try {
- Security.addProvider(new BouncyCastleProvider());
- // 生成 KEY
- KeyGenerator keyGenerator = KeyGenerator.getInstance("AES", "BC");
- keyGenerator.getProvider();
- keyGenerator.init(128);
- // 产生密钥
- SecretKey secretKey = keyGenerator.generateKey();
- // 获取密钥
- byte[] keyBytes = secretKey.getEncoded();
- // KEY 转换
- Key key = new SecretKeySpec(keyBytes, "AES");
- // 加密
- Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
- cipher.init(Cipher.ENCRYPT_MODE, key);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("bc aes encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, key);
- result = cipher.doFinal(result);
- System.out.println("bc aes decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
5. 对称加密算法 - PBE
PBE 算法 (Password Based Encryption, 基于口令加密) 是一种基于口令的加密算法, 其特点是使用口令代替了密钥, 而口令由用户自己掌管, 采用随机数杂凑多重加密等方法保证数据的安全性.
PBE 算法在加密过程中并不是直接使用口令来加密, 而是加密的密钥由口令生成, 这个功能由 PBE 算法中的 KDF 函数完成. KDF 函数的实现过程为: 将用户输入的口令首先通过 "盐"(salt)的扰乱产生准密钥, 再将准密钥经过散列函数多次迭代后生成最终加密密钥, 密钥生成后, PBE 算法再选用对称加密算法对数据进行加密, 可以选择 DES,3DES,RC5 等对称加密算法.
具体实现如下:
Java 代码实现:
- import java.security.Key;
- import java.security.SecureRandom;
- import javax.crypto.Cipher;
- import javax.crypto.SecretKeyFactory;
- import javax.crypto.spec.PBEKeySpec;
- import javax.crypto.spec.PBEParameterSpec;
- import org.apache.commons.codec.binary.Hex;
- public class PBE {
- public static final String src = "pbe test";
- public static void main(String[] args) {
- jdkPBE();
- }
- // 用 jdk 实现:
- public static void jdkPBE() {
- try {
- // 初始化盐
- SecureRandom random = new SecureRandom();
- byte[] salt = random.generateSeed(8);
- // 口令与密钥
- String password = "timliu";
- PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
- SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
- Key key = factory.generateSecret(pbeKeySpec);
- // 加密
- PBEParameterSpec pbeParameterSpac = new PBEParameterSpec(salt, 100);
- Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");
- cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpac);
- byte[] result = cipher.doFinal(src.getBytes());
- System.out.println("jdk pbe encrypt:" + Hex.encodeHexString(result));
- // 解密
- cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpac);
- result = cipher.doFinal(result);
- System.out.println("jdk pbe decrypt:" + new String(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
应用举例:
来源: http://netsecurity.51cto.com/art/201908/600702.htm