目录
一、对称加密算法
二、使用AES加密
下面先介绍ECB工作模式加密并解密:
下面介绍CBC工作模式加密并解密:
三、非对称加密算法
下面通过代码:的形式实现RSA算法:
以上就是对于对称式加密与非对称式加密的对比的分享,如有不当之处还请大家多多评论指正,喜欢的话可以留下您的关注和点赞,一起学习,一起进步!
一、对称加密算法
对称加密算法就是用一个密码进行加密和解密,从程序的角度来看,加密就是接收密码和明文,然后输出密文,而解密恰恰相反,它接收密码和密文,然后输出明文。
算法 | 密钥长度 | 工作模式 | 填充模式 |
DES | 56/64 | ECB/CBC/PCBC/CTR/... | NoPadding/PKCS5Padding/... |
AES | 128/192/156 | ECB/CBC/PCBC/CTR/... | NoPadding/PKCS5Padding/PKCS7Padding/... |
IDEA | 128 | ECB | PKCS5Padding//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);
}
}
以上就是对于对称式加密与非对称式加密的对比的分享,如有不当之处还请大家多多评论指正