目录
2、DES(Data Encryption Algorithm)加密算法
3、AES(Advanced Encryption Standard)加密算法
1、加密算法概述
加密算法分成对称加密、非对称加密、不可逆加密算法。对称和非对称算法是可逆的,即如果有加密算法、密文,能够解密出明文。对称算法是指加密解密使用相同的秘钥,不对称算法的加解密秘钥互不相同。不管对称与否,秘钥的保存也是一个难题,因此出现了不可逆算法。不可逆算法是即使有加密算法、密文,也不能解析出明文。
比较著名的对称加密算法有:DES、AES;
比较著名的非对称加密算法有:RSA、DSA;
非对称加密算法工作原理
|
非对称加密算法工作原理参考:公钥加密_百度百科
比较著名的不可逆机密算法有:MD5、SHA;本质上不可逆加密其实是Hash,使用时双方先对自己的明文进行加密得到密文,再和对方以同样算法加密后的密文进行比较,若相等则意味着双方持有相同的明文。
md5设计论文:http://www.ietf.org/rfc/rfc1321.txt
2、DES(Data Encryption Algorithm)加密算法
DES(Data Encryption Algorithm,DEA)是一种对称加密算法,很可能是使用最广泛的密钥系统,特别是在保护金融数据的安全中,最初开发的DEA是嵌入硬件中的。通常,自动取款机(Automated Teller Machine,ATM)都使用DEA。它出自IBM的研究工作,IBM也曾对它拥有几年的专利权,但是在1983年已到期后,允许在特定条件下可以免除专利使用费而使用。1977年被美国政府正式采纳。
3、AES(Advanced Encryption Standard)加密算法
AES(Advanced Encryption Standard),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 1997,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。
AES加密又分成AES-128、AES-196、AES-256,其中128、196、256是针对加解密密钥长度的要求,即128位(16字节),196位(24字节),256位(32字节);
Java中,一般的加解密初始化时,都要声明加解密方式,类似如下:
1 2 3 4 5 |
|
那么,什么是加密模式,填充方式呢?
3.1、关于加解密模式和填充方式
针对待加解密明文、密文,长度有严格要求,即必须为16字节的整数倍(所以针对不同长度的数据,需要对齐,不够16位的需要填充数据,由此产生了不同的填充方式)。整个加解密的过程是对所有分割成16个字节长度的数据块进行循环加解密,最后合并起来形成最终结果集(加解密过程的不同产生了不同的加解密模式)。
3.1.1、加密模式
针对AES,潜在的其他的加密模式如下:
所有的加解密模式 | 加解密名称 | 算法描述 |
---|---|---|
ECB | 电码本模式(Electronic Codebook Book (ECB) | 这种模式是将整个明文分成若干段相同的小段,然后对每一小段进行加密。 |
CBC | 密码分组链接模式(Cipher Block Chaining (CBC)) | 这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。 |
CTR | 计算器模式(Counter (CTR)) | 计算器模式不常见,在CTR模式中, 有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。 这种加密方式简单快速,安全可靠,而且可以并行加密,但是在计算器不能维持很长的情况下,密钥只能使用一次。 |
CFB | 密码反馈模式(Cipher FeedBack (CFB)) | |
OFB | 输出反馈模式(Output FeedBack (OFB) |
参考:https://www.cnblogs.com/starwolf/p/3365834.html
3.1.2、常见的填充方式
填充方式 | 备注 | |
---|---|---|
NoPadding | 不填充,需要程序满足数据场地为16字节整数倍的要求。 | |
PKCS5Padding | 是PKCS7Padding子集,并规定块长度为8字节(这里指的是填充块的长度); | |
PKCS7Padding | 假设块长度为bs,则: 数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n; 如果数据长度刚好为块大小的整数倍,则填充bs长度的,且值为bs的块到末尾; | |
ZeroPadding | 数据长度不对齐时使用0填充,否则不填充 | oracle jdk_8u131没有发现有该实现 |
3.2、Java基于AES实现ZeroPadding
package com.pajk.datax.common.util.endecrypt;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
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 TestAES2 {
/**
* 加密
*
* @param content 需要加密的内容
* @param password 加密密码
* @return
*/
private static String AESKey = "dbaisbestooooooo";
public static byte[] encrypt(String content, String password) {
try {
// Step 1: padding
int length = content.length();
//ZeroPadding实现
for (int i = 0; i < (16 - length % 16); i++) {
content = content + '\0';
}
SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(password.getBytes()); //强烈注意:CBC必须要
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");// 创建密码器
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key, ivspec);// 初始化
byte[] result = cipher.doFinal(byteContent);
return result; // 加密
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 解密 解密的时候要传入byte数组
*
* @param content 待解密内容
* @param password 解密密钥
* @return
*/
public static byte[] decrypt(byte[] content, String password) {
try {
SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(password.getBytes());//强烈注意:CBC必须要
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key, ivspec); // 初始化
byte[] result = cipher.doFinal(content);
return result; // 加密
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
/**
* 将二进制转换成16进制
*
* @param buf
* @return
*/
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**
* 将16进制转换为二进制
*
* @param hexStr
* @return
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
public static void main(String[] args) {
String content = "1";
for (int i = 0; i < 10; i++) {
String data = content + "-" + i;
StringBuilder sb = new StringBuilder();
// 加密
sb.append("加密前:" + data + ",\t");
byte[] encryptResult = encrypt(data, AESKey);
String encryptResultStr = parseByte2HexStr(encryptResult);
sb.append("加密后:" + encryptResultStr + "(" + encryptResultStr.length() + ")" + ",\t");
// 解密
byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);
byte[] decryptResult = decrypt(decryptFrom, AESKey);
String ns = new String(decryptResult);
sb.append("解密后:" + ns + "");
System.out.println(sb.toString());
}
}
}
4、不可逆算法MD5、SHA简述
MD5(Secure-Digest Algorithm,信息摘要算法),SHA(Secure Hash Algorithm,安全散列算法)是常见的不可逆加密算法,确切地说是不同的Hash算法。而既然是Hash算法,本质就是摘要,就意味着不追求可逆,同时存在一定的Hash碰撞。针对碰撞,解决的办法就是扩大整个Hash值的范围(捂脸笑吧)。
而MD5、SHA256,具体算法上面的数字,则代表了揭秘结果值的位数(8位一个字节),位数越长,整个Hash值范围越大,碰撞的几率越低。如SHA256表示加密后的结果值长度位256位,即256/8=32字节(注意:每个字节表示的范围是0~256,转换为16进制,因此整个字符串长度会变成32字节*2即64字节),整个SHA的值范围是2的256次方。
MD5系列有分成MD2、MD4、MD5,长度都是160位。其中MD2、MD5在Java JDK中都由实现,常用的算法是MD5。
SHA系列有分成SHA1、SHA256、SHA384、SHA512,成都分别为160位,256位,384位,512位。