网络安全之密码学

学习内容:
密码学相关内容:
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年,DiffieHellman发表《密码学的新方向》,标志着公钥密码体制的诞生(第二次质的飞跃)。1978年,RivestShamirAdleman提出了RSA公钥密码体制。

密码学基础

密码学分类

1. 密码编码学和密码分析学
编码学:保密体制和认证体制;
	保密体制:分类:明文空间、密文空间、密钥空间、加密算法、解密算法;
	按照密钥划分为:对称密钥体制和非对称密钥体制;
分析学:遵循柯克霍夫准则;

2. 攻击方式分类:
枚举攻击、统计分析攻击、数学分析攻击;


古典密码学

时间范围:
	1976年之前,一般都采用手工或机械;
经典算法:
	置换密码:
		明文保持不变,但是顺序被打乱;典型方法:棍子加密、抽象代数法;
	代换密码:
		明文中每个字符被替换为密文中的另一个字符;典型方法:单表代换密码-凯撒密码;
特点:
	数据安全基于算法的保密,而现在密码是基于密钥的加密,算法是公开的;
	以字母表为主要的加密对象,而现在密码是基于比特序列进行加密的;
		

现代密码学

三个代表事件:	
	1976年:由 DiffieHellman 在《 密码学的新方向》(《New Directions in Cryptography》)提出了公钥密码学体制的思想
	1977年:美国国家标准局颁布数据加密标准 DES(Data Encryption Standard1978年:第一个公钥算法 RSA 算法(由 Ron RivestAdi ShamirLeonard Adleman 的姓氏首字母组成)

三个方向:
	私钥密码(对称加密)、公钥密码(非对称加密)、安全协议;

对称加密

定义:
	加密和解密使用的相同的密钥;
设计原则:
	扩散-将明文的统计结构打乱,使得这种结构在密文中不再明显。具体来说,扩散是为了确保明文中的单个位或字符的变化能够影响到密文中多个位置的变化。这样做的目的是使得攻击者无法通过分析密文中的模式来推断出明文。
	混乱-使得密文的统计特性与密钥的取值之间的关系尽量复杂,即改变密钥中的任何一个比特都会导致密文发生不可预测的变化。

公用部分:

🍓 密钥生成
1. KeyGenerator keyGen = KeyGenerator.getInstance(); //用于生成对称加密算法的密钥
	其中参数:DES = DES密钥;DESede = 3DES(加--加)类型;AES = AES密钥;
2. keyGen.init(); // 初始化密钥
	其中有如下几种类型:
		keyGen.init(int keySize); // keySize是一个整数,表示密钥的长度(通常以比特为单位)。
		keyGen.init(int keySize, SecureRandom random); // random 是一个 SecureRandom 对象,用于生成高质量的随机数。
		keyGen.init(AlgorithmParameterSpec params); // params 是一个 AlgorithmParameterSpec 对象,包含算法特定的参数。
	
3. SecretKey secretKey = keyGen.generateKey(); //生成密钥

4. byte[] encoded = secretKey.getEncoded(); // 返回包含密钥信息的字节数组;

	

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=EKP);AES解密函数,P=DKC);
分类:
	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);

RC4

定义:
	RC4(也称为 Rivest Cipher 4)是流密码的一种形式,流密码逐字节操作数据流。
	是针对字节流的方式,依次对明文中的每个字节进行加密/解密;
	是一种在电子信息领域加密的技术手段,用于无线通信网络,是一种电子密码,只有经过授权的用户才能享受该服务,使用 64 位或 128 位密钥大小。
	
核心:
	密钥调度算法(Key Scheduling Algorithm, KSA);
	伪随机生成算法(Pseudo-Random Generation Algorithm, PRGA)。
应用:
	通常用于安全套接层 (SSL)、传输层安全 (TLS) 等应用,也用于 IEEE 802.11 无线 LAN 标准。
	
优点及缺点:
	运算速度快;密钥大小可变;
	容易受到攻击;不能在小数据流上实现;不能验证身份;
	
原理介绍:
	密文通过密钥流异或一次就能得到明文;
	向量s(256位),用来做密钥流生成的种子,具体值为0,1,2,....254,255;
	向量T(随机位),用户输入,如果小于256位,则需要轮转填充,即123123123...等方式;
	打乱向量s,采用以下方法:
		j=0;
		for(i = 0 ; i < 256; i ++){
				j = (j + s[i] + t[i]) mod 256;
				swap(s[i],s[j]);
			}		
	密钥流生成以及加密:
		i = 0;
		j = 0;
		while(datalength -- ){//需要执行1024次 也就是密钥流是1024个字节
			i = (i+1) mod 256;
			j = (j + s[i]) mode 256;
			swap(s[i],s[j]);
			t = (s[i] + s[j]) mod 256;
			k = s[t]; // 密钥流中的一位
			// 可以直接加密,也可以保存在数组中,最后异或
			data[] = data[] ^ k; // ^异或
			ArrayList<object> list = new ArrayList<>();
			list.add(k);
			K[] = list.toArray();
			data[] = data[] ^ K;

代码实现:

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public static Key getRC4(String key,String keyMode){
   SecretKeySpec reKey = new SecretKeySpec(key.getBytes(), keyMode);
   System.out.println("密钥长度"+reKey.getEncoded().length); // 密钥长度9 说明是72位? 输入的是9位数字
   System.out.println("密钥:"+bytesToHex(reKey.getEncoded())); // 密钥:313233343536373839 18位
   return reKey;
}

public static String encrypt(Key key,String plainText,String keyMode){
        return encrypt(key,plainText,keyMode,null);
    }
    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){
        return decrypt(key,encryptedText,keyMode,null);
    }
    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 rc4 = encryptDecrypt.getRC4("123456789","RC4");
String encryptRC4 = encryptDecrypt.encrypt(rc4, "Hello, World!", "RC4");
String decryptRC4 = encryptDecrypt.decrypt(rc4, encryptRC4, "RC4");

密钥生成方法

🍎 DH

定义:
	DH算法主要用于密钥交换,而不是直接用于数据加密或解密。
	允许双方在一个不安全的网络上协商出一个共享的对称密钥。一旦共享密钥建立成功,就可以使用对称加密算法(如AES)来加密数据。
	这是一种对称密钥的生成方法,而不是用来加密或解密数据的算法本身。
	

非对称密码

定义:
	加解密需要两个密钥:公钥和私钥;
	一般采用公钥加密,私钥解密;
特点:
	算法复杂度强;极端情况下,加解密速度慢于对称加密;
场景:
	信息加密;登录认证;数字签名;数字证书;
常用算法:
	RSA、DSA、ECC;

公用部分:




RSA

定义:
	于1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出;
	RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
原理:
	两个大素数相乘;乘积为加密密钥(公钥),两个大素数组合成解密密钥(私钥);

代码实现:

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
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();
}

public static Object genRSA(String keyMode,int len){
        // 生成RSA密钥对
        KeyPairGenerator keyGen = null;
        try {
            keyGen = KeyPairGenerator.getInstance(keyMode);
            keyGen.initialize(len); // 可以选择不同的密钥长度,例如1024, 2048, 4096等
            KeyPair keyPair = keyGen.generateKeyPair();
            System.out.println("公钥:" + encryptDecrypt.bytesToHex(keyPair.getPublic().getEncoded()));
            System.out.println("私钥:" + encryptDecrypt.bytesToHex(keyPair.getPrivate().getEncoded()));
            return keyPair;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

// 方法整合 之 密钥加密
    public static String encrypt(Key key,String plainText,String keyMode){
        return encrypt(key,plainText,keyMode,null);
    }
    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){
        return decrypt(key,encryptedText,keyMode,null);
    }
    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方法:
KeyPair rsa = (KeyPair)encryptDecrypt.genRSA("RSA", 1024);
String encryptRSA = encryptDecrypt.encrypt(rsa.getPublic(), "Hello, World!", "RSA");
// 表示算法/工作模式/填充模式,其中RSA/None/PKCS1Padding表示使用RSA算法,使用PKCS1Padding填充模式
String decryptRSA = encryptDecrypt.decrypt(rsa.getPrivate(), encryptRSA, "RSA");
// 使用上述方式会导致 java.security.NoSuchAlgorithmException: Cannot find any provider supporting RSA/None/PKCS1Padding 异常
// java.security.NoSuchAlgorithmException: Cannot find any provider supporting OAEPWithSHA-256AndMGF1Padding

DSA

定义:
	DSA (Digital Signature Algorithm)SchnorrElGamal 签名算法的变种,被美国 NIST 作为 DSS (DigitalSignature Standard)。
	是一种更高级的验证方式,用作数字签名;
	DSA 是基于整数有限域离散对数难题的。
	
特点:
	不单单只有公钥、私钥,还有数字签名;
	私钥加密生成数字签名,公钥验证数据及签名,如果数据和签名不匹配则认为验证失败。
原理:
	发送数据经过消息摘要算法加密生成数字摘要;
	数字摘要经过私钥加密,得到数字签名;
	发送消息 将数字签名和原文发送;
	接收方,用公钥对数字签名的进行解密,得到数字摘要;
	然后利用原文信息结合消息摘要算法 得到数字摘要1,比较数字摘要和数字摘要1是否一致,一致则说明没有被篡改,否则,该消息以不能使用;

代码实现:

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.util.Base64;

// 非对称密钥 生成
    public static Object genRSA(String keyMode,int len){
        // 生成RSA密钥对
        KeyPairGenerator keyGen = null;
        try {
            keyGen = KeyPairGenerator.getInstance(keyMode);
            keyGen.initialize(len); // 可以选择不同的密钥长度,例如1024, 2048, 4096等
            KeyPair keyPair = keyGen.generateKeyPair();
            System.out.println("公钥:" + encryptDecrypt.bytesToHex(keyPair.getPublic().getEncoded()));
            System.out.println("私钥:" + encryptDecrypt.bytesToHex(keyPair.getPrivate().getEncoded()));
            return keyPair;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

main方法:
KeyPair dsa = (KeyPair)encryptDecrypt.genRSA("DSA", 1024);
// 创建签名对象
try {
    Signature dsaSign = Signature.getInstance("SHA1withDSA");
    dsaSign.initSign(dsa.getPrivate());
    // 需要签名的数据
    byte[] message = "Hello, this is a message to be signed.".getBytes("UTF-8");
    dsaSign.update(message);

    // 创建签名
    byte[] signature = dsaSign.sign();

    // 验证签名
    Signature dsaVerify = Signature.getInstance("SHA1withDSA");
    dsaVerify.initVerify(dsa.getPublic());
    dsaVerify.update(message);

    boolean verifyResult = dsaVerify.verify(signature);

    System.out.println("Verification result: " + verifyResult);
    // 密钥长度设置为1024后,密钥长度为:公钥长度:444,私钥长度:336
} catch (Exception e) {
    throw new RuntimeException(e);
}

ECC

定义:
	ECC,全称Elliptic Curve Cryptography,是椭圆曲线密码学。这是一种公钥加密技术,其安全性基于椭圆曲线离散对数问题,被广泛应用于信息安全领域。

特点:
	ECC是RSA的后继更短的密钥长度、更快的签名、更快的密钥协商;
	私钥长度25632字节,大小在曲线的域范围内(field size),256bits的整数;
	公钥在曲线上的点,坐标为{x,y}.能够压缩为一个坐标长度+1bit,为压缩的公钥;

代码实现:

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.util.Base64;

public static Object genRSA(String keyMode,int len){
        // 生成RSA密钥对
        KeyPairGenerator keyGen = null;
        try {
            keyGen = KeyPairGenerator.getInstance(keyMode);
            keyGen.initialize(len); // 可以选择不同的密钥长度,例如1024, 2048, 4096等
            KeyPair keyPair = keyGen.generateKeyPair();
            System.out.println("公钥:" + encryptDecrypt.bytesToHex(keyPair.getPublic().getEncoded()));
            System.out.println("私钥:" + encryptDecrypt.bytesToHex(keyPair.getPrivate().getEncoded()));
            System.out.println("公钥长度:"+keyPair.getPublic().getEncoded().length+","+ "私钥长度:"+keyPair.getPrivate().getEncoded().length);
            return keyPair;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

public static String encrypt(Key key,String plainText,String keyMode){
        return encrypt(key,plainText,keyMode,null);
    }
    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){
        return decrypt(key,encryptedText,keyMode,null);
    }
    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:
KeyPair ecc = (KeyPair)encryptDecrypt.genRSA("EC", 256);
String encryptECC = encryptDecrypt.encrypt(ecc.getPublic(), "Hello, World!", "EC");
String decryptECC = encryptDecrypt.decrypt(ecc.getPrivate(), encryptECC, "EC");

国密

定义:
	国密算法是指由中国国家密码管理局(简称“国密局”)制定的一系列密码算法标准。这些算法主要用于保障信息安全,特别是在政府机构、金融系统、重要行业等领域有着广泛的应用。国密算法涵盖了对称加密、非对称加密、哈希函数等多个方面,旨在提供符合国家标准的安全解决方案。

包括:
	SM1(SCB2)、SM2、SM3、SM4、SM7、SM9、祖冲之密码算法(ZUC) 等。
	其中SM1、SM4、SM7、祖冲之密码(ZUC)是对称算法。
	SM2、SM9是非对称算法。
	SM3是哈希算法。
	其中SM1、SM7算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。
	项目常用算法为SM2 SM3 SM4;

SM2

定义:
	SM2算法就是ECC椭圆曲线密码机制;
	SM2推荐了一条256位的曲线作为标准曲线;
	SM2算法在很多方面都优于RSA算法(RSA发展得早应用普遍,SM2领先也很自然)
使用场景:
	数字签名、密钥交换、公钥加密;
原理:
	SM2算法主要包括数字签名、密钥交换和公钥加密三个部分。其中,数字签名采用椭圆曲线数字签名算法(ECDSA),密钥交换采用椭圆曲线Diffie-Hellman(ECDH)算法,公钥加密采用椭圆曲线公钥加密算法(ECIES)。

代码:

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;

public static Object genSM2Key(){
        // 生成RSA密钥对
        KeyPairGenerator keyGen = null;
        try {
            keyGen = KeyPairGenerator.getInstance("EC","BC");
            keyGen.initialize(new ECGenParameterSpec("sm2p256v1"), new SecureRandom());
            KeyPair keyPair = keyGen.generateKeyPair();
            System.out.println("公钥:" + encryptDecrypt.bytesToHex(keyPair.getPublic().getEncoded()));
            System.out.println("私钥:" + encryptDecrypt.bytesToHex(keyPair.getPrivate().getEncoded()));
            System.out.println("公钥长度:"+keyPair.getPublic().getEncoded().length+","+ "私钥长度:"+keyPair.getPrivate().getEncoded().length);
            // 公钥长度:91,私钥长度:150
            return keyPair;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

public static String encrypt(Key key , String plainText,String keyMode1 , String keyMode2){

        byte[] result = key.getEncoded();
        String encryptedText = "";
        // 加密
        System.out.println("加密: **********");
        // 创建Cipher对象并初始化为加密模式
        Cipher cipheren = null;
        try {
            cipheren = Cipher.getInstance(keyMode1,keyMode2);
            cipheren.init(Cipher.ENCRYPT_MODE, key);
            // 明文
            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 keyMode1 ,String keyMode2){
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
        String decryptedText = "";
        // 加密
        System.out.println("解密: **********");
        // 创建Cipher对象并初始化为加密模式
        Cipher cipherde = null;
        try {
            cipherde = Cipher.getInstance(keyMode1,keyMode2);
            cipherde.init(Cipher.DECRYPT_MODE,key);
            // 解密过程
            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方法:
KeyPair sm2 = (KeyPair)encryptDecrypt.genSM2Key();
String encryptSM2 = encryptDecrypt.encrypt(sm2.getPublic(), "Hello, World!", "ECIES", "BC");
String decryptSM2 = encryptDecrypt.decrypt(sm2.getPrivate(), encryptSM2, "ECIES", "BC");

SM3

SM4

常见概念

数字证书

CA用私钥对信息原文发布者的公钥和信息加密,得出内容就是数字证书;
信息原文所有者发布信息时,带上自己的签名和数字证书,就可以保证信息不被篡改;信息接收者利用CA给的公钥解出信息所有者的公钥,保证信息所有者的公钥是真的,

消息摘要

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值