网络安全之密码学
文章目录
- 绪论
- 密码学基础
- 古典密码学
- 现代密码学
- 对称加密
- DES
- 3DES
- AES
- RC4
- 消息摘要
学习内容:
密码学相关内容:
https://www.bilibili.com/video/BV1tz4y197hm/?spm_id_from=333.337.search-card.all.click&vd_source=c901ae3ff497a02016ba7bada52b2e3b
https://www.cnblogs.com/WittPeng/p/8978737.html
绪论
1. 信息安全与密码学
传统信息安全三要素:机密性、完整性、认证性;
现代信息安全的基本要求:机密性、完整性、认证性、不可否认性;
机密性 = 通过加密方式;完整性 = 消息摘要(哈希函数);认证性 = 数字签名;不可否认性 = 数字签名;
2. 密码学发展:
源自:1949年香农发表一篇题为《保密系统的通信理论》的经典论文。
先后经历了两个阶段:传统密码学和现代密码学。
传统密码:古代密码学、近代密码。
现代密码学:1949年香农发表《保密系统的通信理论》标志着现代密码学的真正开始(第一次质的飞跃)。1976年,Diffie和Hellman发表《密码学的新方向》,标志着公钥密码体制的诞生(第二次质的飞跃)。1978年,Rivest、Shamir和Adleman提出了RSA公钥密码体制。
密码学基础
密码学分类
1. 密码编码学和密码分析学
编码学:保密体制和认证体制;
保密体制:分类:明文空间、密文空间、密钥空间、加密算法、解密算法;
按照密钥划分为:对称密钥体制和非对称密钥体制;
分析学:遵循柯克霍夫准则;
2. 攻击方式分类:
枚举攻击、统计分析攻击、数学分析攻击;
古典密码学
时间范围:
1976年之前,一般都采用手工或机械;
经典算法:
置换密码:
明文保持不变,但是顺序被打乱;典型方法:棍子加密、抽象代数法;
代换密码:
明文中每个字符被替换为密文中的另一个字符;典型方法:单表代换密码-凯撒密码;
特点:
数据安全基于算法的保密,而现在密码是基于密钥的加密,算法是公开的;
以字母表为主要的加密对象,而现在密码是基于比特序列进行加密的;
现代密码学
三个代表事件:
1976年:由 Diffie 和 Hellman 在《 密码学的新方向》(《New Directions in Cryptography》)提出了公钥密码学体制的思想
1977年:美国国家标准局颁布数据加密标准 DES(Data Encryption Standard)
1978年:第一个公钥算法 RSA 算法(由 Ron Rivest、Adi Shamir 和 Leonard Adleman 的姓氏首字母组成)
三个方向:
私钥密码(对称加密)、公钥密码(非对称加密)、安全协议;
对称加密
定义:
加密和解密使用的相同的密钥;
设计原则:
扩散-将明文的统计结构打乱,使得这种结构在密文中不再明显。具体来说,扩散是为了确保明文中的单个位或字符的变化能够影响到密文中多个位置的变化。这样做的目的是使得攻击者无法通过分析密文中的模式来推断出明文。
混乱-使得密文的统计特性与密钥的取值之间的关系尽量复杂,即改变密钥中的任何一个比特都会导致密文发生不可预测的变化。
DES
定义:
DES(Data Encryption Standard)是1977年美国联邦信息处理标准(FIPS)中所采用的一种对称密码(FIPS46.3)。
应用场景:
被美国以及其他国家的政府和银行等广泛使用;
现状:
DES的密文可以在短时间内被破译,现阶段基本不在使用;
核心:
将64bit的明文加密成64bit的密文;
密钥长度,规格上是64bit,其中8bit的错误检查位,56bit真实密钥;
以64bit为一个单位进行加密,该方法为分组加密的一种;
代码实现:
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
// 工具类
// 辅助函数,用于将字节数组转换成十六进制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
// DES算法 之 密码生成
public Key DESKey() {
// 创建一个DES算法的KeyGenerator对象
KeyGenerator keyGen = null;
try {
keyGen = KeyGenerator.getInstance("DES");
// 初始化此密钥生成器,使其具有确定的密钥大小
keyGen.init(56); // DES密钥长度固定为56位
// 生成一个密钥
SecretKey secretKey = keyGen.generateKey();
System.out.println(secretKey.getEncoded().length); // 结果是8
return secretKey;
// 密钥支持某种编码(即它可以被序列化为字节数组),那么 getEncoded() 方法会返回一个包含密钥信息的字节数组。
// 密钥长度最后应该是64bit
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
main方法:
//DES 密钥生成 加解密;
Key key = new encryptDecrypt().DESKey();
byte[] result = key.getEncoded();
System.out.println("密钥:**********");
System.out.println("密钥 string:"+result.toString()); // 密钥 string:[B@cb5822
// 上述表示会多一个符号 [ 需要将其去掉; 真实使用不能用toString的方法
System.out.println("密钥 长度:"+result.length); // 密钥 长度:8
System.out.println("密钥 十六进制:"+bytesToHex(result)); // 密钥 十六进制:02ECD0314A75BA4F
// 16进制 那么64位 就是16个数字
String encryptedText = "";
// 加密
System.out.println("加密: **********");
// 创建Cipher对象并初始化为加密模式
Cipher cipheren = null;
Cipher cipherde = null;
try {
cipheren = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipheren.init(Cipher.ENCRYPT_MODE, key );
// 明文
String plainText = "Hello, World!";
byte[] plainTextBytes = plainText.getBytes();
// 加密过程
byte[] encryptedBytes = cipheren.doFinal(plainTextBytes);
encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("Encrypted Text: " + encryptedText); // Encrypted Text: 8u9aORKY2aElbp7bimAFNg==
} catch (Exception e) {
throw new RuntimeException(e);
}
// 解密
System.out.println("解密: **********");
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
// 解密过程
byte[] decryptedBytes = new byte[0];
try {
cipherde = Cipher.getInstance("DES/ECB/PKCS5Padding");
// 表示 DES=加密算法类型,单重DES加密;ECB=加密模式,即每个块都单独加密,没有前后关联;PKCS5Padding=填充模式,输入数据长度不是块大小的整数倍,会使用该标准来填充;
cipherde.init(Cipher.DECRYPT_MODE, key);
decryptedBytes = cipherde.doFinal(encryptedBytes);
String decryptedText = new String(decryptedBytes);
System.out.println("Decrypted Text: " + decryptedText); // Decrypted Text: Hello, World!
} catch (Exception e) {
throw new RuntimeException(e);
}
3DES
定义:
是基于DES研发的,为了增强其强度,将DES重复3次所得到;
加密:明文——加密1——密文1——解密2——密文2——加密3——密文3
解密:密文3——解密3——密文2——加密2——密文1——解密1——明文
核心:
每个密钥56位,再加上错误检测位8位,三个密钥,总共是192位;其中密钥为168位;
一般代码创建密钥都不包括错误检测位,只包含密钥部分;
如果三个密钥都相同,则3DES = DES;
常见模式为为:EDE(加密-解密-加密)和EDE3(加密-解密-加密,第三个密钥不同于前两个)
代码实现:
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
// 3DES 密钥生成
public static Key threeDESKey() {
KeyGenerator keyGen = null;
try {
keyGen = KeyGenerator.getInstance("DESede");
// 初始化此密钥生成器,使其具有确定的密钥大小
keyGen.init(168);
// 3DES密钥长度固定为168位
// 生成一个密钥
SecretKey secretKey = keyGen.generateKey();
System.out.println(secretKey.getEncoded().length); // 结果是8
return secretKey;
// 密钥支持某种编码(即它可以被序列化为字节数组),那么 getEncoded() 方法会返回一个包含密钥信息的字节数组。
// 密钥长度最后应该是64bit
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
main方法:
// 3DES 算法
Key key2 = encryptDecrypt.threeDESKey();
byte[] result2 = key2.getEncoded();
System.out.println("密钥:**********");
System.out.println("密钥 string:"+result2.toString()); // 密钥 string:[B@2b98378d
// 上述表示会多一个符号 [ 需要将其去掉; 真实使用不能用toString的方法
System.out.println("密钥 长度:"+result2.length); // 密钥 长度:24
System.out.println("密钥 十六进制:"+bytesToHex(result2)); // 密钥 十六进制:2C1640469B1A1CE5B540EF70EF911C5837618601C4AE26DC
// 16进制 那么64位 就是16个数字
String encryptedText2 = "";
// 加密
System.out.println("加密: **********");
// 创建Cipher对象并初始化为加密模式
Cipher cipheren2 = null;
Cipher cipherde2 = null;
try {
cipheren2 = Cipher.getInstance("DESede/ECB/PKCS5Padding");
// 表示 DESede=加密算法类型,三重DES加密,其中ede表示-加密-解密-加密,使用三个密钥进行三次加密;ECB=加密模式,即每个块都单独加密,没有前后关联;PKCS5Padding=填充模式,输入数据长度不是块大小的整数倍,会使用该标准来填充;
// 其中PKCS5Padding 针对使用8字节块大小的算法,如果不是8的整数倍,需要添加响应模块数
cipheren2.init(Cipher.ENCRYPT_MODE, key2 );
// 明文
String plainText = "Hello, World!";
byte[] plainTextBytes = plainText.getBytes();
// 加密过程
byte[] encryptedBytes2 = cipheren2.doFinal(plainTextBytes);
encryptedText2 = Base64.getEncoder().encodeToString(encryptedBytes2);
System.out.println("Encrypted Text: " + encryptedText2); // Encrypted Text: RvvQQgmDpES/BgH4ggo6Gg==
} catch (Exception e) {
throw new RuntimeException(e);
}
// 解密
System.out.println("解密: **********");
byte[] encryptedBytes2 = Base64.getDecoder().decode(encryptedText2);
// 解密过程
byte[] decryptedBytes2 = new byte[0];
try {
cipherde2 = Cipher.getInstance("DESede/ECB/PKCS5Padding");
//
cipherde2.init(Cipher.DECRYPT_MODE, key2);
decryptedBytes2 = cipherde2.doFinal(encryptedBytes2);
String decryptedText2 = new String(decryptedBytes2);
System.out.println("Decrypted Text: " + decryptedText2); // Decrypted Text: Hello, World!
} catch (Exception e) {
throw new RuntimeException(e);
}
AES
定义:
高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法;
涉及到明文P、密钥K、密文C、AES加密函数、AES解密函数;
AES加密函数,C=E(K,P);AES解密函数,P=D(K,C);
分类:
AES-128,密钥16字节,分组16字节,加密10轮;
AES-192,密钥24字节,分组16字节,加密12轮;
AES-256,密钥32字节,分组16字节,加密14轮;
原理分析:
AES处理单位是字节,即密钥16字节(K0...K15),明文16字节(C0...C15),
代码实现:
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
// 方法整合 之 密钥生成
public static Key genKey(String keyName,int len){
// 创建一个DES算法的KeyGenerator对象
KeyGenerator keyGen = null;
try {
keyGen = KeyGenerator.getInstance(keyName);
// 初始化此密钥生成器,使其具有确定的密钥大小
keyGen.init(len);
// 生成一个密钥
SecretKey secretKey = keyGen.generateKey();
System.out.println(secretKey.getEncoded().length);
return secretKey;
// 密钥支持某种编码(即它可以被序列化为字节数组),那么 getEncoded() 方法会返回一个包含密钥信息的字节数组。
// 密钥长度最后应该是64bit
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
// 方法整合 之 密钥加密
public static String encrypt(Key key , String plainText,String keyMode , IvParameterSpec ivParameter){
byte[] result = key.getEncoded();
// 16进制 那么64位 就是16个数字
String encryptedText = "";
// 加密
System.out.println("加密: **********");
// 创建Cipher对象并初始化为加密模式
Cipher cipheren = null;
try {
cipheren = Cipher.getInstance(keyMode);
cipheren.init(Cipher.ENCRYPT_MODE, key, ivParameter);
// 明文
byte[] plainTextBytes = plainText.getBytes();
// 加密过程
byte[] encryptedBytes = cipheren.doFinal(plainTextBytes);
System.out.println("Encrypted len: " + encryptedBytes.length);
encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("Encrypted Text: " + encryptedText); // Encrypted Text: 8u9aORKY2aElbp7bimAFNg==
return encryptedText;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 方法整合 之 密钥解密
public static String decrypt(Key key , String encryptedText,String keyMode , IvParameterSpec ivParameter){
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
String decryptedText = "";
// 加密
System.out.println("解密: **********");
// 创建Cipher对象并初始化为加密模式
Cipher cipherde = null;
try {
cipherde = Cipher.getInstance(keyMode);
cipherde.init(Cipher.DECRYPT_MODE, key , ivParameter);
// 解密过程
byte[] decryptedBytes = cipherde.doFinal(encryptedBytes);
decryptedText = new String(decryptedBytes);
System.out.println("Decrypted Text: " + decryptedText);
return decryptedText;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
main方法:
Key aes = encryptDecrypt.genKey("AES", 256);
byte[] iv = new byte[16]; // IV的长度取决于使用的模式,对于AES/CBC/PKCS5Padding通常是16字节
new java.security.SecureRandom().nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
String encrypt = encryptDecrypt.encrypt(aes, "Hello, World!", "AES/CBC/PKCS5Padding",ivParameterSpec);
// CBC(Cipher Block Chaining)模式时,会需要一个初始化向量(Initialization Vector, IV)。初始化向量的作用是在每个加密块开始时引入一些不可预测的数据,从而确保即使相同的明文在不同的消息中会被加密成不同的密文,提高了安全性。 其中密钥长度是256时,则ivParameterSpec长度为16
String decrypt = encryptDecrypt.decrypt(aes, encrypt, "AES/CBC/PKCS5Padding",ivParameterSpec);