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

对称加密算法

对称加密算法就是传统的用一个密码进行加密和解密;例如,我们常用的WinZIP和WinRAR对压缩包的加密和解密,就是使用对称加密算法。
常用的对称加密算法
算法
 密钥长度
工作模式
 DES( 版本太老)
56/64
ECB/CBC/PCBC/CTR/...
AES
128/192/256
ECB/CBC/PCBC/CTR/...
IDEA
128
ECB
使用AES/ ECB模式(没有IV参数)
核心代码
加密步骤
  1. 设置算法/工作模式/ECB/填充模式   
  2. 根据key的字节内容,恢复秘钥对象
  3. 初始化密钥:设置加密模式
  4. 根据原始内容字节进行加密:返回的是字节数组
解密步骤
  1. 设置算法/工作模式/ECB/填充模式
  2. 根据key的字节内容,恢复秘钥对象
  3. 初始化密钥:设置解密模式
  4. 根据加密内容字节进行解密:
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

//ECB模式
public class Test {
	public static void main(String[] args) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
		//原文
		String message = "Hello";
        //128位密钥 = 16 bytes key:
		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 IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
		//创建密码对象:需要传入算法/工作模式/填充模式
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		//根据key的字节内容,“恢复”秘钥对象
		SecretKey keySpec = new SecretKeySpec(key,"AES");
		//初始化秘钥:设置加密模式ENCRYPT_MOD
		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_MOD
		cipher.init(Cipher.DECRYPT_MODE, keySpec);
		//根据原始内容(字节)进行解密
		return cipher.doFinal(input);
	
	}
}
使用AES CBC模式(带有IV参数) 此处的IV参数相当于对密钥进行"加盐",步骤与ECB模式大致相同
。不同的是CBC模式需要生成一个16 bytes的IV,随后在初始化密钥时将IV设置进去;解密时 我们首先得拿到他的IV字节内容,根据IV字节内容恢复IV,同样在初始化密钥时将IV设置进去。
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


public class Test {
	 public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
		 	//原文
			String message = "Hello";
			//256位密钥 =32 bytes key:
			byte[] key = "1234567890abcdef1234567890abcdef".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, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
		 //设置算法/工作模式CBC/填充
		 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		 //恢复密钥对象
		 SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
		 //CBC模式需要生成一个16bytes的initialization vector
		 SecureRandom sr = SecureRandom.getInstanceStrong();
		 byte[] iv = sr.generateSeed(16);//生成16个字节的随机数
		 System.out.println(Arrays.toString(iv));
		 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[] decrypt(byte[] key,byte[] input) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
		 //把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);//密文
		 System.out.println(Arrays.toString(iv));
		 //解密
		 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//密码对象
		 SecretKeySpec keySpec = new SecretKeySpec(key, "AES");//恢复秘钥
		 IvParameterSpec ivps = new IvParameterSpec(iv);//恢复IV
		 //初始化秘钥:操作模式、秘钥、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;
	 }
}

非对称加密算法

非对称加密算法使用一组密钥对进行对文件加密解密,也就是说加密和解密使用的不是相同的密钥,当我们想让A向B发送加密文件时,A首先需要将自己的公钥发送给B,B使用A的公钥对文件进行加密,随后将加密文件发送给A,A可以通过自己私钥对文件进行解密。
步骤实现
  1. 首先必须生成一个密钥对
  2. 使用公钥加密
  3. 使用私钥解密
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.Cipher;

// RSA
public class Test {
    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(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);
    }
}

对称式加密与非对称式加密的区别

1、对称加密中加密和解密使用的秘钥是同一个;非对称加密中采用两个密钥,一般使用公钥进行加密,私钥进行解密。

2、对称加密解密的速度比较快,非对称加密和解密花费的时间长、速度相对较慢。

3、对称加密的安全性相对较低,非对称加密的安全性较高。

  • 24
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
RSA 是一种非对称加密算法,它可以用于数据加密和数字签名。下面是 RSA 加密算法的实现过程: 1. 选择两个大素数 p 和 q,并计算 n = p*q。 2. 计算欧拉函数 φ(n) = (p-1)*(q-1)。 3. 选择一个小于 φ(n) 的整数 e,使得 e 和 φ(n) 互质。 4. 计算 e 的模反元素 d,即满足 (d*e) mod φ(n) = 1 的整数 d。可以使用扩展欧几里得算法来计算 d。 5. 公钥为 (n, e),私钥为 (n, d)。 6. 加密时,将消息 m 转换成整数 M,然后计算密文 C = M^e mod n。 7. 解密时,将密文 C 计算出明文 M = C^d mod n。 下面是 Python 实现 RSA 加密算法的代码: ```python import random def gcd(a, b): if b == 0: return a else: return gcd(b, a % b) def extended_gcd(a, b): if b == 0: return (a, 1, 0) else: d, x, y = extended_gcd(b, a % b) return (d, y, x - (a // b) * y) def mod_inverse(a, m): d, x, y = extended_gcd(a, m) if d != 1: raise ValueError("No inverse exists") else: return x % m def generate_key_pair(p, q): n = p * q phi = (p - 1) * (q - 1) e = random.randrange(1, phi) while gcd(e, phi) != 1: e = random.randrange(1, phi) d = mod_inverse(e, phi) return ((n, e), (n, d)) def encrypt(msg, public_key): n, e = public_key m = int.from_bytes(msg.encode(), 'big') c = pow(m, e, n) return c.to_bytes((c.bit_length() + 7) // 8, 'big').decode() def decrypt(cipher, private_key): n, d = private_key c = int.from_bytes(cipher.encode(), 'big') m = pow(c, d, n) return m.to_bytes((m.bit_length() + 7) // 8, 'big').decode() # 选择两个大素数 p 和 q p = 61 q = 53 # 生成公钥和私钥 public_key, private_key = generate_key_pair(p, q) print("公钥:", public_key) print("私钥:", private_key) # 加密和解密 msg = "Hello, world!" cipher = encrypt(msg, public_key) print("密文:", cipher) plaintext = decrypt(cipher, private_key) print("明文:", plaintext) ``` 需要注意的是,由于 RSA 加密算法使用了大整数计算,因此在处理大数时需要使用适当的库来避免溢出等问题。在 Python 中,可以使用内置的 `pow()` 函数来计算幂取模,也可以使用第三方库(如 `gmpy2` )来进行大整数运算。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值