Java加密:对称式加密与非对称式加密的对比

目录

一、对称加密算法

二、使用AES加密

下面先介绍ECB工作模式加密并解密:

下面介绍CBC工作模式加密并解密:

三、非对称加密算法

      下面通过代码:的形式实现RSA算法:

 以上就是对于对称式加密与非对称式加密的对比的分享,如有不当之处还请大家多多评论指正,喜欢的话可以留下您的关注和点赞,一起学习,一起进步!

一、对称加密算法

对称加密算法就是用一个密码进行加密和解密,从程序的角度来看,加密就是接收密码和明文,然后输出密文,而解密恰恰相反,它接收密码和密文,然后输出明文。

算法密钥长度工作模式填充模式
DES56/64ECB/CBC/PCBC/CTR/...NoPadding/PKCS5Padding/...
AES128/192/156ECB/CBC/PCBC/CTR/...NoPadding/PKCS5Padding/PKCS7Padding/...
IDEA128ECBPKCS5Padding//PKCS7Padding/...

 密钥长度直接决定加密的强度,工作模式和填充模式可以看作对称加密的参数和格式选择。特别注意一点,DES算法由于密钥过程,可以在短时间内被暴力破解,现在已经不安全了。

二、使用AES加密

AES算法是目前应用最广泛的加密算法,比较常见的工作模式是ECB和CBC。

下面先介绍ECB工作模式加密并解密:

加密:

首先创建创建密码对象Cipher,通过调用getInstance()方法,此时需要传入算法名称AES/工作模式ECB/填充模式PKCS5Padding;

其次根据key的字节内容,通过new SecretKeySpec()“恢复”密钥对象SecretKey,密钥必须指定长度;

初始化密钥,设置加密模式ENCRYPT_MODE;

最后根据原始内容(字节),调用doFinal()方法进行加密;

解密:

首先创建创建密码对象Cipher,通过调用getInstance()方法,此时需要传入算法名称AES/工作模式ECB/填充模式PKCS5Padding;

其次根据key的字节内容,通过new SecretKeySpec()“恢复”密钥对象SecretKey;

初始化密钥,设置加密模式DECRYPT_MODE;

最后根据原始内容(字节),调用doFinal()方法进行j解密。

public class demo {
	public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
		//原文
		String message = "Hello,world";
		System.out.println("Message(原始信息): " + message);
		
		//128位密钥 = 16字节
		byte[] key = "1234567890abcdef".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("Decrypted(解密内容):" + new String(decrypted));
	}
	
	//加密
	public static byte[] encrypt(byte[] key,byte[] input) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		//创建密码对象,需要传入算法名称/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		
		//根据key的字节内容,“恢复”密钥对象
		SecretKey keySpec = new SecretKeySpec(key, "AES");
		
		//初始化密钥:设置加密模式ENCRYPT_MODE
		cipher.init(cipher.ENCRYPT_MODE, keySpec);
		
		//根据原始内容(字节),进行加密
		return cipher.doFinal(input);
	}
	
	//解密
	public static byte[] decrypt(byte[] key,byte[] input) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		//创建密码对象,需要传入算法/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
			
		//根据key的字节内容,“恢复”密钥对象
		SecretKey keySpec = new SecretKeySpec(key, "AES");
			
		//初始化密钥:设置解密模式DECRYPT_MODE
		cipher.init(cipher.DECRYPT_MODE, keySpec);
			
		//根据原始内容(字节),进行解密
		return cipher.doFinal(input);
	}

}

运行结果:

下面介绍CBC工作模式加密并解密:

加密:

首先创建创建密码对象Cipher,通过调用getInstance()方法,此时需要传入算法名称AES/工作模式CBC/填充模式PKCS5Padding;

其次根据key的字节内容,通过new SecretKeySpec()“恢复”密钥对象SecretKey;

然后CBC模式需要生成一个16 bytes的 initialization vector;

初始化密钥,设置加密模式ENCRYPT_MODE;

最后根据原始内容(字节),调用doFinal()方法进行加密,将IV和密文一起返回输出。

解密:

首先分割IV和密文;

其次创建创建密码对象Cipher,通过调用getInstance()方法,此时需要传入算法名称AES/工作模式CBC/填充模式PKCS5Padding;

然后根据key的字节内容,通过new SecretKeySpec()“恢复”密钥对象SecretKey,恢复IV;

初始化密钥,设置加密模式DECRYPT_MODE;

最后根据原始内容(字节),调用doFinal()方法进行解密。

public class demo {
	public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
		//原文
		String message = "Hello,world";
		System.out.println("Message(原始信息): " + message);
		
		//128位密钥 = 16字节
		byte[] key = "1234567890abcdef".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("Decrypted(解密内容):" + new String(decrypted));
	}
	
	//加密
	public static byte[] encrypt(byte[] key,byte[] input) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
		//创建密码对象,需要传入算法名称/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		
		//根据key的字节内容,“恢复”密钥对象
		SecretKey keySpec = new SecretKeySpec(key, "AES");
		
		//CBC模式需要生成一个16 bytes的 initialization vector
		SecureRandom sr = SecureRandom.getInstanceStrong();
		byte[] iv = sr.generateSeed(16); //生成16字节的随机数
		System.out.println(Arrays.toString(iv));
		IvParameterSpec ivps = new IvParameterSpec(iv); //随机数封装成IvParameterSpec参数对象
		
		//初始化密钥:设置加密模式ENCRYPT_MODE,密钥,IV参数
		cipher.init(cipher.ENCRYPT_MODE, keySpec,ivps);
		
		//根据原始内容(字节),进行加密
		byte[] data = cipher.doFinal(input);
		
		//IV不需要保密,将IV和密文一起返回
		return join(iv, data);
	}
	
	//解密
	public static byte[] decrypt(byte[] key,byte[] input) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
		//把input分割成IV和密文
		byte[] iv = new byte[16];
		byte[] data = new byte[input.length - 16];
		
		System.arraycopy(input, 0, iv, 0, iv.length);
		System.arraycopy(input, 16, data, 0, data.length);
		System.out.println(Arrays.toString(iv));
		
		//创建密码对象,需要传入算法/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			
		//根据key的字节内容,“恢复”密钥对象
		SecretKey keySpec = new SecretKeySpec(key, "AES");
		
		//恢复IV
		IvParameterSpec ivps = new IvParameterSpec(iv);
			
		//初始化密钥:设置解密模式DECRYPT_MODE、密钥、IV参数
		cipher.init(cipher.DECRYPT_MODE, keySpec,ivps);
			
		//根据原始内容(字节),进行解密
		return cipher.doFinal(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;
	}
 
}

运行结果:

       总结:ECB模式相对来说比较简单,安全性较低,而CBC模式需要生成一个16 bytes的随机数initialization vector,然后将随机数封装成IvParameterSpec参数对象,因此安全性高;两者加密都需要设置加密模式ENCRYPT_MODE,解密需要设置加密模式DECRYPT_MODE

三、非对称加密算法

       非对称加密算法:加密和解密使用的不是相同的密钥,只有使用同一对公钥-私钥才能正常加密和解密,典型的算法就是RSA算法

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

      下面通过代码:的形式实现RSA算法:

       大致思路:

首先通过KeyPairGenerator创建对象,调用generateKeyPair()生成公钥-私钥对;

其次通过定义Person类来模拟人,用Alice的公钥加密,私钥解密;

公钥加密:创建Cipher对象,调用getInstance("RSA");初始化密钥,设置ENCRYPT_MODE加密模式;调用doFinal生成加密信息。

私钥加密:创建Cipher对象,调用getInstance("RSA");初始化密钥,设置DECRYPT_MODE加密模式;调用doFinal生成加密信息。

public class demo01 {
    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();
        System.out.println(String.format("public key(公钥): %x", new BigInteger(1, pk)));
        
        // 使用公钥加密
        byte[] encrypted = alice.encrypt(plain);
        System.out.println(String.format("encrypted(加密): %x", new BigInteger(1, encrypted)));
       
        // 用Alice的私钥解密:
        // 获取Alice的私钥,并输出
        byte[] sk = alice.getPrivateKey();
        System.out.println(String.format("private key(私钥): %x", new BigInteger(1, sk)));
        
        // 使用私钥解密
        byte[] decrypted = alice.decrypt(encrypted);
        System.out.println("decrypted(解密): " + new String(decrypted, "UTF-8"));
    }
}

// 用户类
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();
    }

    // 用公钥加密:
    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);
    }
}

 以上就是对于对称式加密与非对称式加密的对比的分享,如有不当之处还请大家多多评论指正,喜欢的话可以留下您的关注和点赞,一起学习,一起进步!

 

  • 61
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值