常用加密
- DES, Data Encryption Standard, 数据加密标准
- 3DES, Triple DES, 三重数据加密算法
- AES, Advanced Encryption Standard, 高级加密标准
- RSA
名词解释
- 分组加密:将明文切分成多个固定长度的分组
- 块加密:加密算法只能处理固定长度的数据
- 对称加密:解密与加密的使用同一个秘钥
- 非对称加密:加密和解密使用不同的秘钥
- 流密码:在分组加密中
- 加密模式(mode):在分组加密中针对每个分组,有不同的处理方式。
- 填充模式(padding):在分组加密或块加密中,数据长度无法不足时,需要按照一定模式对数据进行填充
填充模式
AES中的填充模式
PKCS5
分组数据缺少几个字节,就在数据的末尾填充几个字节的几,比如缺少5个字节,就在末尾填充5个字节的5
PKCS7
分组数据缺少几个字节,就在数据的末尾填充几个字节的0,比如缺少7个字节,就在末尾填充7个字节的0
NoPadding
不需要填充,保证数据长度满足加密算法的长度限定。
ISO10126Padding
填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。
RSA中的填充模式
PKCS1_PADDING
输入:必须 比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11, 如果输入的明文过长,必须切割, 然后填充
输出:和modulus一样长
PKCS1_OAEP_PADDING
输入:RSA_size(rsa) – 41
输出:和modulus一样长
NO_PADDING
不需要填充,保证数据长度满足加密算法的长度限定。
加密模式
- ECB (Elecyronic Code Book,电子密码本模式)
- CBC (Cipher Block Chaining,密码分组链接模式)
- CFB (Cipher FeedBack Mode加密反馈)
- OFB (Output FeedBack,输出反馈)
- CTR (Counter ,计算器模式)
加密模式详解:
1、https://www.jianshu.com/p/5973a6b63593
2、https://www.jianshu.com/p/5973a6b63593
ECB
ECB模式是最基本的加密模式,即仅仅使用明文和密钥来加密数据,相同的明文块会被加密成相同的密文块,
这样明文和密文的结构将是完全一样的,就会更容易被破解,相对来说不是那么安全,因此很少使用。
CBC
而CBC模式则比ECB模式多了一个初始向量IV,加密的时候,第一个明文块会首先和初始向量IV做异或操作,
然后再经过密钥加密,然后第一个密文块又会作为第二个明文块的加密向量来异或,依次类推下去,
这样相同的明文块加密出的密文块就是不同的,明文的结构和密文的结构也将是不同的,因此更加安全,我们常用的就是CBC加密模式。
CFB
CFB的加密工作分为两部分:1、将一前段加密得到的密文再加密;2、将第1步加密得到的数据与当前段的明文异或。
OFB
OFB是先用块加密器生成密钥流,然后再将密钥流与明文流异或得到密文流,解密是先用块加密器生成密钥流,再将密钥流与密文流异或得到明文,由于异或操作的对称性所以加密和解密的流程是完全一样的。
java 中如何使用
java 提供的加密工具类在 javax.crypto.* 包下,提供统一的加密类Cipher 来完成。我们无法直接创建一个Cipher对象,需要通过Cipher.getInstance(String transformation)方法获取到Cipher实例,需要指定转换器的名称。转换器格式:Alg/Mode/Padding。 详解可见:https://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html#Cipher
工具类:sprite-utils
AES代码
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "AES");
// 偏移量,默认偏移量为 new byte[16],建议不适用默认的偏移量
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));
// 解密
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, params);
// 加密
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec, params);
byte[] result = cipher.doFinal(content);
DES代码
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "DES");
// 偏移量,默认偏移量为 new byte[16],建议不适用默认的偏移量
AlgorithmParameters params = AlgorithmParameters.getInstance("DES");
params.init(new IvParameterSpec(iv));
// 解密
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, params);
// 加密
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec, params);
byte[] result = cipher.doFinal(content);
RSA代码
注:RSA是没有加密模式的,在获取Cipher时如果想指定填充模式,只能将模式指定为ECB才可以。java默认的填充模式是PKCS1Padding
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "RSA");
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 私钥加密
cipher.init(Cipher.ENCRYPT_MODE, keyFactory.generatePrivate(new PKCS8EncodedKeySpec(key)));
// 公钥加密
cipher.init(Cipher.ENCRYPT_MODE, keyFactory.generatePublic(new X509EncodedKeySpec(key)));
// 公钥解密
cipher.init(Cipher.DECRYPT_MODE, keyFactory.generatePublic(new X509EncodedKeySpec(key)));
// 私钥解密
cipher.init(Cipher.DECRYPT_MODE, keyFactory.generatePrivate(new PKCS8EncodedKeySpec(key)));
byte[] result = cipher.doFinal(content);