Java 中的加密使用和理解

我的网站 | 我的博客

常用加密

  • 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代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
# DES, RSA
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×