一、什么是对称加密算法?
顾名思义,对称加密算法就是加密和解密使用相同密钥的一种算法。
优点:使用简单快捷,密钥较短,加密速度快,且破译困难,适用于一对一的加密信息传输;
缺点:不能验证通信双方的身份,密钥管理和分发困难,不适宜一对多的加密信息传输。
二、DES加解密
des是非常经典的对称加密算法。
1.密钥生成
View Code
指定算法名称(或者既指定算法名称又指定包提供程序),获取到唯一的随机数
SecureRandom secureRandom = SecureRandom.getInstance(
"SHA1PRNG" );
或
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
密钥为
64位(二进制)长的密码key, ,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是奇偶校验位)。
奇偶校验位是一个表示给定位数的二进制数中 1 的个数是奇数还是偶数的二进制数。奇偶校验位是最简单的错误检测码。
奇偶校验位有两种类型:偶校验位与奇校验位。如果一组给定数据位中 1 的个数是奇数,那么偶校验位就置为 1;如果给定一组数据位中 1 的个数是偶数,那么奇校验位就置为 1,总之,奇偶校验位保证这组数据位中1 的个数是奇数。
2、了解des加密的四种模式
ECB模式
优点:
1.简单;
2.有利于并行计算;
3.误差不会被传送;
缺点:
1.不能隐藏明文的模式;
2.可能对明文进行主动攻击;
CBC模式:
优点:
1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点:
1.不利于并行计算;
2.误差传递;
3.需要初始化向量IV
CFB模式:
优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.误差传送:一个明文单元损坏影响多个单元;
3.唯一的IV;
OFB模式:
优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.对明文的主动攻击是可能的;
3.误差传送:一个明文单元损坏影响多个单元;
3、简单了解填充方式
PKCS5Padding与
PKCS7Padding基本上是可以通用的。
PKCS5Padding:
If numberOfBytes(clearText) mod 8 == 7, PM = M + 0x01
If numberOfBytes(clearText) mod 8 == 6, PM = M + 0x0202
...
If numberOfBytes(clearText) mod 8 == 0, PM = M + 0x0808080808080808
PKCS7Padding:
PKCS #7 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。
下面的示例演示这些模式的工作原理。假定块长度为 8,数据长度为 9,则填充用八位字节数等于 7,数据等于 FF FF FF FF FF FF FF FF FF:
数据: FF FF FF FF FF FF FF FF FF
PKCS7 填充: FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07
在PKCS5Padding中,明确定义Block的大小是8位,而在PKCS7Padding定义中,对于块的大小是不确定的,可以在1-255之间(块长度超出255的尚待研究),填充值的算法都是一样的:value=k - (l mod k) ,K=块大小,l=数据长度,如果l=8, 则需要填充额外的8个byte的08。
4、算法
想了解具体算法的可以在网上找下,这里就不写了。
三、DES加密在java中的实现
package com.su.mybatis.mysql.util.encryption; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.CipherOutputStream; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class DESUtil { /** * CFB */ public static final String CFB = "CFB"; /** * OFB */ public static final String OFB = "OFB"; /** * CBC */ public static final String CBC = "CBC"; /** * iv向量 */ private static final byte[] DESIV = { (byte) 0xCE, (byte) 0x35, (byte) 0x5, (byte) 0xD, (byte) 0x98, (byte) 0x91, (byte) 0x8, (byte) 0xA }; /** * AlgorithmParameterSpec */ private static AlgorithmParameterSpec IV = null; /** * SHA1PRNG */ private static final String SHA1PRNG = "SHA1PRNG"; /** * DES默认模式 */ private static final String DES = "DES"; /** * CBC加密模式 */ private static final String DES_CBC_PKCS5PADDING = "DES/CBC/PKCS5Padding"; /** * OFB加密模式 */ private static final String DES_OFB_PKCS5PADDING = "DES/OFB/PKCS5Padding"; /** * CFB加密模式 */ private static final String DES_CFB_PKCS5_PADDING = "DES/CFB/PKCS5Padding"; /** * 加密模式 */ private static final int ENCRYPT_MODE = 1; /** * 解密模式 */ private static final int DECRYPT_MODE = 2; /** * 密钥 */ private Key key; public DESUtil(String str) { getKey(str); } public Key getKey() { return key; } public void setKey(Key key) { this.key = key; } /** * 通过密钥获得key * @param secretKey 密钥 * @author sucb * @date 2017年2月28日下午1:17:58 */ public void getKey(String secretKey) { try { SecureRandom secureRandom = SecureRandom.getInstance(SHA1PRNG); secureRandom.setSeed(secretKey.getBytes()); KeyGenerator generator = null; try { generator = KeyGenerator.getInstance(DES); } catch (NoSuchAlgorithmException e) { } generator.init(secureRandom); IV = new IvParameterSpec(DESIV); this.key = generator.generateKey(); generator = null; } catch (Exception e) { throw new RuntimeException("Error in getKey(String secretKey), Cause: " + e); } } /** * 字符串des加密 * @param data 需要加密的字符串 * @param encryptType 加密模式 (ECB/CBC/OFB/CFB) * @return 加密结果 * @throws Exception 异常 * @author sucb * @date 2017年3月2日下午7:47:37 */ public String encrypt(String data, String encryptType) throws Exception { Cipher cipher = getPattern(encryptType, ENCRYPT_MODE); byte[] pasByte = cipher.doFinal(data.getBytes("UTF-8")); BASE64Encoder base64Encoder = new BASE64Encoder(); return base64Encoder.encode(pasByte); } /** * 字符串des解密 * @param data 需要解密的字符串 * @param decryptType 解密模式 (ECB/CBC/OFB/CFB) * @return 解密结果 * @throws Exception 异常 * @author sucb * @date 2017年3月2日下午7:48:21 */ public String decrypt(String data, String decryptType) throws Exception { Cipher cipher = getPattern(decryptType, DECRYPT_MODE); BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] pasByte = cipher.doFinal(base64Decoder.decodeBuffer(data)); return new String(pasByte, "UTF-8"); } /** * 初始化cipher * @param type 加密/解密模式 (ECB/CBC/OFB/CFB) * @param cipherMode cipher工作模式 1:加密; 2:解密 * @return cipher * @throws Exception 异常 * @author sucb * @date 2017年3月2日下午7:49:16 */ private Cipher getPattern(String type, int cipherMode) throws Exception { Cipher cipher; switch (type){ case CBC : cipher = Cipher.getInstance(DES_CBC_PKCS5PADDING); cipher.init(cipherMode, key, IV); break; case OFB : cipher = Cipher.getInstance(DES_OFB_PKCS5PADDING); cipher.init(cipherMode, key, IV); break; case CFB : cipher = Cipher.getInstance(DES_CFB_PKCS5_PADDING); cipher.init(cipherMode, key, IV); break; default : cipher = Cipher.getInstance(DES); cipher.init(cipherMode, key); break; } return cipher; } /** * 文件 file 进行加密并保存目标文件 destFile 中 * @param file 要加密的文件 如 c:/test/file.txt * @param destFile 加密后存放的文件名 如 c:/ 加密后文件 .txt * @param encryptType 加密模式 (ECB/CBC/OFB/CFB) * @return 加密结果 0:异常 1:加密成功; 5:未找到需要加密的文件 * @author sucb * @date 2017年3月2日下午7:56:08 */ public int encryptFile(String file, String destFile, String encryptType) { int result = 0; try { Cipher cipher = getPattern(encryptType, ENCRYPT_MODE); InputStream is = new FileInputStream(file); OutputStream out = new FileOutputStream(destFile); CipherInputStream cis = new CipherInputStream(is, cipher); byte[] buffer = new byte[1024]; int r; while ((r = cis.read(buffer)) > 0) { out.write(buffer, 0, r); } cis.close(); is.close(); out.close(); result = 1; } catch (FileNotFoundException e) { result = 5; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 文件 file 进行解密并保存目标文件 destFile 中 * @param file 要解密的文件 如 c:/test/file.txt * @param destFile 解密后存放的文件名 如 c:/ 解密后文件 .txt * @param decryptType 解密模式 (ECB/CBC/OFB/CFB) * @return 解密结果 0:解密异常;1:解密正常;5:未找到需要解密的文件 * @author sucb * @date 2017年3月2日下午7:58:56 */ public int decryptFile(String file, String destFile, String decryptType) { int result = 0; try { Cipher cipher = getPattern(decryptType, DECRYPT_MODE); InputStream is = new FileInputStream(file); OutputStream out = new FileOutputStream(destFile); CipherOutputStream cos = new CipherOutputStream(out, cipher); byte[] buffer = new byte[1024]; int r; while ((r = is.read(buffer)) >= 0) { cos.write(buffer, 0, r); } cos.close(); out.close(); is.close(); result = 1; }catch (FileNotFoundException e) { result = 5; } catch (Exception e) { e.printStackTrace(); } return result; } public static void main(String[] args) throws Exception { String testString = "82171ba02fc44b52b9f4a4853d0bcc34"; DESUtil desUtil = new DESUtil("13325710641"); String stringMi = desUtil.encrypt(testString, "CBC"); System.out.println("密文" + stringMi); String stringMing = desUtil.decrypt(stringMi, "CBC"); System.out.println("明文:" + stringMing); } }
以上就是des加解密。