对称加密算法与非对称加密算法

本文深入探讨了对称加密算法中的AES,包括ECB和CBC工作模式,并通过代码示例进行了解析。同时,介绍了非对称加密算法RSA的工作原理,强调了对称加密与非对称加密在安全性、速度上的差异。通过对两种加密方式的对比,突显了非对称加密更高的安全性但较慢的运行速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、什么是对称加密算法

二、常用的对称加密算法

三、AES算法

1、ECB工作模式

2、CBC工作模式

3、小结

四、非对称加密算法

五、对称加密算法与非对称加密算法的区别


一、什么是对称加密算法

对称加密算法就是用一个秘钥进行加密和解密。

从程序的角度看:

加密:一个函数,接收密码和明文,然后输出密文

解密:一个函数,接收密文和密码,然后输出明文

二、常用的对称加密算法

在软件开发的过程中,常用的对称加密算法有:

 本篇博客以AES算法为例,实现对称加密。

三、AES算法

  在AES算法中常用的是ECBCBC两种工作模式,我们分别来介绍:

1、ECB工作模式

在ECB工作模式下,我们的秘钥是固定的,这里为了方便大家理解,加密与解密的过程使用方法来进行封装。在主函数里直接调用加密与解密的方法。

//原文
		String message = "hello";
		System.out.println("Message:" + message);
		
		//128位秘钥 = 16 bytes key:
		byte[] key = "987654321zxcvbnm".getBytes();
		
		//加密
		byte[] data = message.getBytes();
		byte[] encrypted = encrypt(key, data);
		System.out.println("Encrypted(加密) :" + Base64.getEncoder().encodeToString(encrypted));
		
		//解密
		byte[] decrypted = decrypt(key, encrypted);
		System.out.println("解密:" + new String(decrypted));

加密:

1.创建密码对象,需要传入算法名称/工作模式/填充模式,这里使用ECB工作模式

2.根据我们写入的16字节的秘钥,使用SecretKey来恢复秘钥(秘钥必须是指定长度的)

3.初始化秘钥,设置加密模式

//加密
	public static byte[] encrypt(byte[] key,byte[] input) throws GeneralSecurityException {
		//创建密码对象,需要传入算法名称/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		
		//根据key的字节内容,“恢复”秘钥
		SecretKey keySpec = new SecretKeySpec(key,"AES");
		
		//初始化秘钥:设置加密模式
		cipher.init(Cipher.ENCRYPT_MODE, keySpec);
		
		//根据原始内容(字节),进行加密
		return cipher.doFinal(input);
		
	}

解密:

解密与加密唯一不同的是:在初始化过程中设置的是解密模式

public static byte[] decrypt (byte[] key ,byte[] input) throws GeneralSecurityException{
		//创建密码对象,需要传入算法名称/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		
		//根据key的字节内容,“恢复”秘钥
		SecretKey keySpec = new SecretKeySpec(key,"AES");
		
		//初始化秘钥:设置解密模式
		cipher.init(Cipher.DECRYPT_MODE, keySpec);
		
		//根据原始内容(字节),进行加密
		return cipher.doFinal(input);
		
	}

2、CBC工作模式

CBC的算法步骤大致相同,与EBC最大的不同之处,就是CBC多了一个动态IV,一个随机数作为参数,相同的明文,每次产生的密文都不同。

加密:

与EBC相比多了一个需要使用SecureRandom 实例化一个对象,来生成一个16字节的随机数,把它存放在一个字节数组,将随机数封装成ParameterSpec对象。

在初始化秘钥的时候,把这个参数iv一起传进去。

最后在调用一个数组合并的方法将iv与传入的数据都返回出去

//加密
	public static byte[] encrypt(byte[] key,byte[] input) throws GeneralSecurityException {
		//创建密码对象,需要传入算法名称/CBC工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		
		//根据key的字节内容,“恢复”秘钥
		SecretKey keySpec = new SecretKeySpec(key,"AES");
		
		//CBC模式需要生成一个16bytes的initialization vector:
		SecureRandom sr = SecureRandom.getInstanceStrong();
		byte[] iv = sr.generateSeed(16); //生成16个字节的随机数
		IvParameterSpec ivps = new IvParameterSpec(iv); //随机数封装成IvParameterSpec对象
		
		//初始化秘钥:设置加密模式、秘钥、iv
		cipher.init(Cipher.ENCRYPT_MODE, keySpec,ivps);
		
		//进行加密
		byte[] data = cipher.doFinal(input);
		
		//IV不需要保密,把IV和密文一起返回
		return join(iv, data);
	}

数组合并:

	//合并数组
	public static byte[] join(byte[] bs1,byte[] bs2) {
		
		byte[] r = new byte[bs1.length + bs2.length];
		
		System.arraycopy(bs1, 0, r, 0, bs1.length);
		System.arraycopy(bs2, 0, r, bs1.length,bs2.length);
		
		return r;
	}

解密:

我们需要将输入的内容分割成IV和密文,创建两个字节数组分别来保存。

将分割出的iv封装成ParameterSpec对象ipvs,在秘钥初始化时,选择解密模式,连同秘钥一起传进去。

最后调用doFinal()方法进行解密。


	public static byte[] decrypt (byte[] key ,byte[] input) throws GeneralSecurityException{
		//把input分割成IV和密文
		byte[] iv = new byte[16];
		byte[] data = new byte[input.length - 16];
		
		System.arraycopy(input, 0, iv, 0, 16);  //IV
		System.arraycopy(input, 16, data, 0, data.length); //密文
		
		//解密:
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		
		//根据key的字节内容,“恢复”秘钥
		SecretKey keySpec = new SecretKeySpec(key,"AES");
		
		IvParameterSpec ivps = new IvParameterSpec(iv);
		
		//初始化秘钥:设置解密模式、秘钥、IV参数
		cipher.init(Cipher.DECRYPT_MODE, keySpec,ivps);
		
		//解密
		return cipher.doFinal(data);
		
	}

3、小结

        两种工作模式,ECB模式采用固定秘钥,安全性略低,CBC模式使用动态随机数iv,来保证安全性更高,其实不论是ECB模式还是CBC模式,在进行解密与加密的过程中,步骤大致相似,只有在初始化秘钥是,选择的模式不同:加密使用的是==>Cipher.ENCRYPT_MODE,解密使用的是==>Cipher.DECRYPT_MODE,但自始至终使用的都是同一个秘钥,这就是对称加密算法。

四、非对称加密算法

非对称加密算法也叫RSA算法。       

与对称加密算法不同的是,进行加密与解密使用的是不同的秘钥,只有一个公钥-私钥,秘钥对才可以正常的加解密。

例如:如果我向小王准备发送一个加密文件,我需要先得到小王的公钥进行加密,而在进行解密的过程中,只有小王的与之匹配的私钥才可以进行解密,除此之外,任何人都解不开。

非对称加密的优点:  对称加密需要协商密钥,而非对称加密可以安全地公开各自的公钥,在N个人之间通信的时候:使用非对称加密只需要N个密钥对,每个人只管理自己的密钥对。而使用对称加密需要则需要N(N-1)/2个密钥,因此每个人需要管理N 1个密钥,密钥管理难度大,而且非常容易泄漏。
非对称加密的缺点:运算速度非常慢,比对称加密要慢很多。

具体实现步骤如下:

为了方便我们使用,我们把加密与解密的过程封装在方法中。

第一步:我们需要一个用户类,有用户的姓名,公钥、私钥、及构造方法,传入当前对象的名字,以及实例化一个KeyPairGenerator 对象调用generateKeyPair()方法生成一对儿秘钥。

// 用户类
class Human {
	// 姓名
    String name;
    
    // 私钥:
    PrivateKey sk;
    
    // 公钥:
    PublicKey pk;

    // 构造方法
    public Human(String name) throws GeneralSecurityException {
    	// 初始化姓名
        this.name = name;
        
        // 生成公钥/私钥对:
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
        kpGen.initialize(1024);
        KeyPair kp = kpGen.generateKeyPair();
        
        this.sk = kp.getPrivate();
        this.pk = kp.getPublic();
    }

}

第二步:把生成的秘钥对编码成字节


    // 把私钥导出为字节
    public byte[] getPrivateKey() {
        return this.sk.getEncoded();
    }

    // 把公钥导出为字节
    public byte[] getPublicKey() {
        return this.pk.getEncoded();
    }

第三步:使用公钥进行加密

1.使用Cipher 实例化对象声明使用的是RSA算法

2.使用公钥进行初始化

3.调用doFianl()方法进行加密,返回一个字节数组。

// 用公钥加密:
    public byte[] encrypt(byte[] message) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, this.pk); // 使用公钥进行初始化(使用公钥加密)
        return cipher.doFinal(message);
    }

第四步:使用私钥进行解密

与加密不同的是,在传入参数时,传入的字节数组是加密后的密文字节数组,初始化时,使用的是私钥。

   // 用私钥解密:
    public byte[] decrypt(byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, this.sk); // 使用私钥进行初始化 (使用私钥解密)
        return cipher.doFinal(input);
    }

在主函数调用想要的方法来完成:

值得注意的是,在完成对象创建时,就已经在构造方法中创建好了一对秘钥对(公钥---私钥)

 public static void main(String[] args) throws Exception {
        // 明文:
        byte[] plain = "Hello, encrypt use RSA".getBytes("UTF-8");
        
        // 创建公钥/私钥对:
        Human alice = new Human("Alice");
        
        // 用Alice的公钥加密:
        // 获取Alice的公钥
        byte[] pk = alice.getPublicKey();
        
        // 使用公钥加密
        byte[] encrypted = alice.encrypt(plain);
        System.out.println(String.format("encrypted(加密): %x", new BigInteger(1, encrypted)));
       
        // 用Alice的私钥解密:
        // 获取Alice的私钥
        byte[] sk = alice.getPrivateKey();
        
        // 使用私钥解密
        byte[] decrypted = alice.decrypt(encrypted);
        System.out.println("解密:" + new String(decrypted, "UTF-8"));
    }

五、对称加密算法与非对称加密算法的区别

1、对称加密算法不论是在加密还是解密的过程中,使用的都是同一个秘钥,这也体现了它的对称性,而非对称加密算法使用的是一对儿秘钥(公钥---私钥),加密过程使用的是公钥,解密过程中只有使用同一个公钥--私钥对才可以解开,体现了不对称性。

2.在安全性方面来看,非对称加密算法的安全性更高

3.从运行速度来看:非对称加密的运行速度比对称加密慢得多

对称加密算法非对称加密算法
秘钥同一个秘钥一对儿秘钥
安全性较低更高
运行速度很慢

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值