DES
- DES加密算法因现代的计算能力,已经被淘汰掉了,因为现在在24小时内就可以被破解
- 特点:
分组加密算法:明文以64位分组,64位明文输入,64位密文输出 对称算法:加密和解密使用同一密钥 有效密钥长度为56位:密钥通常表示为64位数,但每个第8位用于奇偶校验,可以忽略 代替和置换:DES算法是两种加密技术的组合:混合和扩散,先替代后置换 易于实现: DES算法只是使用了标准的算术和逻辑运算,其作用的数最多也只有64位 - DES算法简述:
- (1)输入64位明文数据,进行初始置换:DES算法使用64位密钥Key将64位明文输入块变为64位的密文输出块,并将输出块分为L0、R0两部分,每部分均为32位
- (2)在密钥的控制下,进行完全相同的16轮运算f,运算过程中总数据和密钥结合,函数f由四步运算构成(ps:以下内容我已经看不懂了):密钥置换、扩展置换、S-盒代替、P-盒置换
- (3)16轮之后,左右两部分进行交换,再连接到一起,然后再进行逆置换
- (4)输出64位密文
java代码使用Cipher进行DES加解密
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.util.Locale;
public class DES {
private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding";
private static final String ALGORITHM = "DES";
public static void main(String[] args) {
try {
String originalStr = "DES最棒了";
System.out.println("待加密字符:" + originalStr);
String desKey = initDesKey("12345679");
System.out.println("密钥:" + desKey);
String encrypted = encrypt(originalStr, desKey);
System.out.println("加密结果:" + encrypted);
String decrypted = decrypt(encrypted, desKey);
System.out.println("密文解密后:" + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
private static String initDesKey(String seed) throws Exception{
SecureRandom secureRandom;
if (null!=seed && seed.length()!=0) {
secureRandom = new SecureRandom(HexBin.decode(seed));
}else {
secureRandom = new SecureRandom();
}
KeyGenerator key=KeyGenerator.getInstance(ALGORITHM);
key.init(secureRandom);
SecretKey secretKey = key.generateKey();
byte[] encoded = secretKey.getEncoded();
return HexBin.encode(encoded);
}
private static String encrypt(String data,String key) throws Exception{
DESKeySpec desKeySpec = createDesKeySpec(key);
Cipher cipher = getCipher(desKeySpec, Cipher.ENCRYPT_MODE);
return HexBin.encode(cipher.doFinal(data.getBytes())).toUpperCase(Locale.ROOT);
}
private static String decrypt(final String data,String key)throws Exception {
DESKeySpec desKeySpec = createDesKeySpec(key);
Cipher cipher = getCipher(desKeySpec, Cipher.DECRYPT_MODE);
return new String(cipher.doFinal(HexBin.decode(data)));
}
private static Cipher getCipher(DESKeySpec desKeySpec, int mode) throws Exception {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(mode, secretKey, new IvParameterSpec(desKeySpec.getKey()));
return cipher;
}
private static DESKeySpec createDesKeySpec(String key) throws InvalidKeyException {
return new DESKeySpec(key.getBytes());
}
}
运行结果如下:
3DES
- 3DES加密算法是对DES算法的改进加强版,它相当于是对每个数据块应用三次DES加密算法
- 加密流程,图源博主AtlanSI
- 解密流程:图源AtlanSI
- 当3DES中所有的密钥都相同时,3DES等同于普通DES
- 特点:
密钥长度增长,通过增加迭代次数提高了数据的安全性 但处理速度也随之变慢,加密效率不高
java使用Cipher进行3DES加解密
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import javax.crypto.*;
import javax.crypto.spec.DESedeKeySpec;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.util.Locale;
public class DES3 {
private static final String CIPHER_ALGORITHM = "DESede/ECB/PKCS5Padding";
private static final String ALGORITHM = "DESede";
public static void main(String[] args) {
try {
String originalStr = "3DES才是最棒的";
System.out.println("待加密字符:" + originalStr);
String des3Key = initKey("4545454545AAAA");
System.out.println("密钥长度:" + des3Key.getBytes().length);
System.out.println("密钥:" + des3Key);
String encrypted = encrypt(originalStr, des3Key);
System.out.println("加密结果:" + encrypted);
String decrypted = decrypt(encrypted, des3Key);
System.out.println("解密结果:" + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String initKey(String seed) throws Exception{
SecureRandom secureRandom;
if (null!=seed && seed.length()!=0) {
secureRandom = new SecureRandom(HexBin.decode(seed));
}else {
secureRandom = new SecureRandom();
}
KeyGenerator key=KeyGenerator.getInstance(ALGORITHM);
key.init(secureRandom);
SecretKey secretKey = key.generateKey();
byte[] encoded = secretKey.getEncoded();
return HexBin.encode(encoded);
}
private static String encrypt(String data,String key) throws Exception{
DESedeKeySpec desEdeKeySpec = createDesKeySpec(key);
Cipher cipher = getCipher(desEdeKeySpec, Cipher.ENCRYPT_MODE);
return HexBin.encode(cipher.doFinal(data.getBytes())).toUpperCase(Locale.ROOT);
}
private static String decrypt(final String data,String key)throws Exception {
DESedeKeySpec deSedeKeySpec = createDesKeySpec(key);
Cipher cipher = getCipher(deSedeKeySpec, Cipher.DECRYPT_MODE);
return new String(cipher.doFinal(HexBin.decode(data)));
}
private static DESedeKeySpec createDesKeySpec(String key) throws InvalidKeyException {
return new DESedeKeySpec(key.getBytes());
}
private static Cipher getCipher(DESedeKeySpec deSedeKeySpec, Integer mode) throws Exception{
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secureKey = keyFactory.generateSecret(deSedeKeySpec);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(mode, secureKey);
return cipher;
}
}
运行结果如下:
AES
- AES加密算法被设计为支持128/192/256为密码长度
- AES加密算法的安全性要高于3DES加密算法,所以现在已经成为了主流的对称加密算法
- AES加密算法的五个关键词(别问我,我也不知道这五个东西具体是些啥):分组密码体制、Padding、密钥、初始向量IV和四种加密模式
分组密码体制: 将明文切成一段一段的来加密,然后再把一段一段的密文拼起来形成最终的密文(每组数据的长度必须要求是128位,如果最后一段不够16字节,就需要Padding进行填满) Padding: padding就是用来把不满16个字节的分组填满为16个字节,它有三个模式PKCS5(缺几个字节就填充几个字节的5),PKCS7( 缺几个字节就填充几个字节的0),NOPADDING(不需要填充,因为懂事的数据发送方肯定会把证最后一段数据也正好是16个字节) 初始向量IV: 初始向量IV的作用是使加密更加安全可靠,我们使用AES加密时需要主动提供初始向量,并且只需要提供一个初始向量即可,后面每段数据的加密向量都是前面一段的密文 密钥: AES要求密钥长度可以是128/192/256位,位数越高,加密强度越大,但同时加密效率也会低一些。使用AES加密时需要主动提供一个密钥,密钥来源位随机生成(我们传入的叫做初始密钥,而后面每一轮的密钥都是由上一轮的密钥扩展而来的,密钥扩展有四个步骤:排列、置换、与轮常量异或、生成下一轮密钥的其他列) 四种加密模式: ECB(电子密码本模式)、CBC(密码分组链接模式)、CFB、OFB,我们一般使用CBC模式,四种模式除了ECB相对不安全外,其余三种模式的区别并没有那么大
Java使用Cipher进行AES加密
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
public class AES {
private static final String CIPHER_MODE = "AES/ECB/PKCS5Padding";
private static final String ALGORITHM = "AES";
public static void main(String[] args) {
try {
String originalStr = "AES才是最最厉害的";
System.out.println("待加密字符:" + originalStr);
String aesKey = initAesKey(null);
System.out.println("密钥:" + aesKey);
String encrypted = encrypt(originalStr, aesKey);
System.out.println("加密结果:" + encrypted);
String decrypted = decrypt(encrypted, aesKey);
System.out.println("解密结果:" + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String initAesKey(String seed) throws Exception {
SecureRandom secureRandom;
if (null!=seed && seed.length()!=0) {
secureRandom = new SecureRandom(HexBin.decode(seed));
} else {
secureRandom = new SecureRandom();
}
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
kg.init(128, secureRandom);
SecretKey secretKey = kg.generateKey();
byte[] encoded = secretKey.getEncoded();
return HexBin.encode(encoded);
}
public static String encrypt(String data, String key)throws Exception {
Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE);
return HexBin.encode(cipher.doFinal(data.getBytes())).toUpperCase();
}
public static String decrypt(String data, String key) throws Exception{
Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE);
return new String(cipher.doFinal(HexBin.decode(data)));
}
private static Cipher getCipher(String key, Integer mode) throws Exception {
SecretKey secretKey = new SecretKeySpec(HexBin.decode(key), ALGORITHM);
Cipher cipher = Cipher.getInstance(CIPHER_MODE);
cipher.init(mode, secretKey);
return cipher;
}
}
运行结果
|