上一章中讲到了 ,这一章中让我们进一步了解密码是怎么加密的及密码加密到底是个什么原理,这将有助于我们深刻理解 密码学 的奥秘,这对以后的工作中后者学习中都有很大的帮助。‘
1 AES加解密
什么是 DES
什么是DES?它是美国国家标准技术研究院(NIST)于1977年引入的对称分组密码。它是 Feistel Structure的实现(一种多轮密码,将整个文本分为两部分,并分别在每一部分上工作)。它适用于64位输入密钥,并使用56位共享密钥生成64位密文。在DES中,整个纯文本在处理之前被分为32位的两个部分,每个部分都执行相同的操作。每个部分都要进行16轮运算,然后进行最后的置换以获得64位密文。
AES使用几种不同的方法来执行排列和置换运算。AES是一个迭代的、对称密钥分组的密码,它可以使用128、192和256位密钥,并且用128位(16字节)分组加密和解密数据。
与公共密钥加密使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换和替换输入数据。
java代码实现AES加解密
package com.fire.DesAes;
import com.sun.org.apache.xml.internal.security.utils.Base64;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class DesAesDemo {
public static void main(String[] args) throws Exception {
String input="张飞";
// AES加密算法 ,比较高级,所以key的大小必须是16个字节
String key="1234567811111111";
//算法
String algorithm="AES";
//加密类型
String transformation="AES";
String encode = encryptDES(input, key, algorithm, transformation);
System.out.println("加密:"+encode);
String decode=decryptDES(encode, key, algorithm, transformation);
System.out.println("解密:"+decode);
}
private static String decryptDES(String encode, String key, String algorithm, String transformation) throws Exception{
Cipher cipher=Cipher.getInstance(transformation);
SecretKeySpec secretKeySpec=new SecretKeySpec(key.getBytes(),algorithm);
cipher.init(Cipher.DECRYPT_MODE,secretKeySpec);
byte[] byt=Base64.decode(encode);
byte[] bytes=cipher.doFinal(byt);
return new String(bytes);
}
private static String encryptDES(String input, String key, String algorithm, String transformation) throws Exception {
//参数表示使用什么类型进行加密
//1,获取加密对象
Cipher cipher=Cipher.getInstance(transformation);
//指定密码规则
SecretKeySpec secretKeySpec=new SecretKeySpec(key.getBytes(),algorithm);
//3,对加密进行初始化
cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec);
//4,调用dofinal方法加密
byte[] bytes= cipher.doFinal(input.getBytes());
String encode=Base64.encode( byte s);
return encode;
}
}
输出结果:
加密:8OKAHs5P66MgSnBpHU+XcQ==
解密:张飞
2 加密模式
加密模式:
2.1 ECB
ECB : Electronic codebook, 电子密码本. 需要加密的消息按照块密码的块大小被分为数个块,并对每个块进行独立加密
- 优点 : 可以并行处理数据
- 缺点 : 同样的原文生成同样的密文, 不能很好的保护数据
- 同时加密,原文是一样的,加密出来的密文也是一样的
2.2 CBC
CBC : Cipher-block chaining, 密码块链接. 每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块
- 优点 : 同样的原文生成的密文不一样
- 缺点 : 串行处理数据.
2.3填充模式
- 当需要按块处理的数据, 数据长度不符合块处理需求时, 按照一定的方法填充满块长的规则
NoPadding
- 不填充.
- 在 DES加密算法 下, 要求原文长度必须是8byte的整数倍
- 在AES加密算法下, 要求原文长度必须是16byte的整数倍
PKCS5Padding
数据块的大小为8位, 不够就补足
Tips
- 默认情况下, 加密模式和填充模式为 : ECB/PKCS5Padding
- 如果使用CBC模式, 在初始化Cipher对象时, 需要增加参数, 初始化向量IV : IvParameterSpec iv = new IvParameterSpec(key.getBytes());
加密模式和填充模式
代码示例:
AES/CBC/NoPadding (128)
AES/CBC/PKCS5Padding (128)
AES/ECB/NoPadding (128)
AES/ECB/PKCS5Padding (128)
DES/CBC/NoPadding (56)
DES/CBC/PKCS5Padding (56)
DES/ECB/NoPadding (56)
DES/ECB/PKCS5Padding (56)
DESede/CBC/NoPadding (168)
DESede/CBC/PKCS5Padding (168)
DESede/ECB/NoPadding (168)
DESede/ECB/PKCS5Padding (168)
RSA /ECB/PKCS1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
package com.fire.DesAes;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.Key;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
/**
* @Date 2020/1/9 19:27
* @Created by Alter Ego
*/public class DesCBCUtil {
public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";
/**
* DES算法,加密
*
* @param data 待加密字符串
* @param key 加密私钥,长度不能够小于8位
* @return 加密后的字节数组,一般结合Base64编码使用
* @throws CryptException 异常
*/ public static String encode(String key, String data) throws Exception {
return encode(key, data.getBytes());
}
/**
* DES算法,加密
*
* @param data 待加密字符串
* @param key 加密私钥,长度不能够小于8位
* @return 加密后的字节数组,一般结合Base64编码使用
* @throws CryptException 异常
*/ public static String encode(String key, byte[] data) throws Exception {
try {
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
//key的长度不能够小于8位字节
Key secretKey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
IvParameterSpec iv = new IvParameterSpec(key.getBytes());
AlgorithmParameterSpec paramSpec = iv;
cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
byte[] bytes = cipher.doFinal(data);
return new String(Base64.encodeBase64(bytes));
} catch (Exception e) {
throw new Exception(e);
}
}
/**
* DES算法,解密
*
* @param data 待解密字符串
* @param key 解密 私钥 ,长度不能够小于8位
* @return 解密后的字节数组
* @throws Exception 异常
*/ public static byte[] decode(String key, byte[] data) throws Exception {
try {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
//key的长度不能够小于8位字节
Key secretKey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
IvParameterSpec iv = new IvParameterSpec(key.getBytes());
AlgorithmParameterSpec paramSpec = iv;
cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec);
return cipher.doFinal(data);
} catch (Exception e) {
throw new Exception(e);
}
}
/**
* 获取编码后的值
*
* @param key
* @param data
* @return
* @throws Exception
*/ public static String decode(String key, String data) {
byte[] datas;
String value = null;
try {
datas = decode(key, Base64.decodeBase64(data.getBytes()));
value = new String(datas);
} catch (Exception e) {
value = "";
}
return value;
}
public static void main(String[] args) throws Exception {
String clearText = "张飞";
String key = "ALTEREGO";//密钥
System.out.println("明文:" + clearText + "n密钥:" + key);
String encryptText = encode(key,clearText);
System.out.println("加密后:" + encryptText);
String decodeText = decode(key,encryptText);
System.out.println("解密后:"+decodeText);
}
}
输出结果:
明文:张飞
密钥:ALTEREGO
加密后:9aidajHFZD8=
解密后:张飞
总结:密码学看似比较复杂,其实只要弄懂原理就是一件比较简单的事情,学习什么还是要学习底层的原理比较重要,掌握了原理到哪里都不会发怵和紧张,今天就到这里吧。
谢谢!