什么是对称加密算法?
对称加密算法即加密和解密使用相同密钥的算法。
优缺点:
优点:算法公开、计算量小、加密速度快、加密效率高。
缺点:
(1)交易双方都使用同样钥匙,安全性得不到保证。
(2)每对用户每次使用对称加密算法时,都需要使用其他人不知道的惟一钥匙,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。
摘录来源:http://www.cnblogs.com/Free-Thinker/p/5825582.html
常用的算法:
- DES(Data Encryption Standard,数据加密算法)
- 3DES(Triple Data Encryption Algorithm,三重数据加密算法)
- AES(Advanced Encryption Standard,高级加密标准,又称Rijndael加密法)
- PBE(Password-based encryption,基于密码验证)
本文会介绍通过JDK来实现上述相关算法,会在源码中加入其它第三方包的开发源码,建议先看:java加密算法入门(一)-算法概念及单向加密 理解相关概念。另外,本文不会讲述太多算法原理,注重在应用。
2、DES(Data Encryption Standard,数据加密算法)
DES是最基本的对称加密算法,也是使用频率最高的一种算法,加密密钥与解密密钥相同。DES出身比较好,出自IBM之手,后被美国军方采纳,之后便广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法。DES使用56位长度的密钥,有些提供商可能附加8位奇偶校验位。
2.1 算法流程:
发送者构建秘钥-->发送秘钥--> 接收者
发送者明文-->DES算法+秘钥加密--> 密文--> 接收者
接收者--> DES算法+秘钥解密--> 明文
2.2 具体实现
1.初始化密钥
使用KeyGenerator类的getInstance()静态方法,获取生成指定算法的密钥生成器,参数是算法名称.
使用KeyGenerator类的init()方法进行密钥生成器的初始化,指定密钥生成器产生密钥的长度.
使用KeyGenerator类的generatorKey()方法生成一个密钥对象,返回SecretKey密钥对象.
SecretKey为密钥对象.使用它的getEncoded()方法返回一个密钥(字节数组形式)
public static byte[] initSecretKey(){ //返回生成指定算法密钥的KeyGenerator对象 KeyGenerator kg = KeyGenerator.getInstance("DES"); //初始化此密钥生成器,使其具有确定的密钥大小 kg.init(56); //生成一个密钥 SecretKey secretKey = kg.generateKey(); return secretKey.getEncoded(); }
2.转化密钥(还原密钥),将jdk生成的密钥对象转化成DES规则的密钥对象.
创建一个DESKeySpec实例,作用是将JDK初始化的密钥转化成DES规则的密钥,构造方法参数是JDK生成的密钥(字节数组形式).
使用SecretKeyFactory类的getInstance()静态方法获取一个密钥工厂实例,参数是算法名称
使用SecretKeyFactory类的generateSecret()方法生成密钥,参数是DESKeySpec实例.返回SecretKey,返回的SecretKey实例就是符合DES算法的密钥.
private static Key toKey(byte[] key){ //实例化DES密钥规则 DESKeySpec dks = new DESKeySpec(key); //实例化密钥工厂 SecretKeyFactory skf = SecretKeyFactory.getInstance("DES"); //生成密钥 SecretKey secretKey = skf.generateSecret(dks); return secretKey; }
3.加密
创建Cipher对象,该类提供加密和解密功能,使用Cipher类的getInstance()静态方法,参数是“算法/模式/填充”或“算法”,后一种参数使用默认值,后续类似,默认不在说明。
初始化Cipher对象,init(int opmode, Key key),参数:opmode为以下之一:ENCRYPT_MODE、DECRYPT_MODE、WRAP_MODE 或 UNWRAP_MODE,key - 密钥
加密操作,返回加密后的字节数组,然后需要编码。主要编解码方式有Base64, HEX, UUE, 7bit等等。
编码,ps:此为测试用
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));
4.解密
将服务器返回的加密字符串,先用Base64、HEX等解码成byte[]
再用加密时相同的加密方式及key进行解密。加密与解密代码几乎相同。唯一区别为在Cipher类init时,工作模式为Cipher.DECRYPT_MODE。
2.3 实现代码
/** * {@link http://www.cnblogs.com/allanzhang/} * @author 小卖铺的老爷爷 * */ public class DESTest { public static final String src = "laoyeye des"; 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(); } } }