180630-JCE介绍

JCE介绍

一、前言

Java Cryptography Extension(JCE)是一组包,它们提供用于加密、密钥生成和协商以及 Message Authentication Code(MAC)算法的框架和实现。它提供对对称、不对称、块和流密码的加密支持,它还支持安全流和密封的对象。它不对外出口,用它开发完成封装后将无法调用。

在早期JDK版本中,由于受美国的密码出口条例约束,Java中涉及加解密功能的API被限制出口,所以Java中安全组件被分成了两部分: 不含加密功能的JCA(Java Cryptography Architecture )和含加密功能的JCE(Java Cryptography Extension)。

在JDK1.1-1.3版本期间,JCE属于扩展包,仅供美国和加拿大的用户下载,JDK1.4+版本后,随JDK核心包一起分发。

加解密

Cipher

JCE的API都在 javax.crypto 包下,核心功能包括:加解密、密钥生成(对称)、MAC生成、密钥协商。

加解密功能由Cipher组件提供,其也是JCE中最核心的组件。
Cipher的几个知识点:

  1. Cipher在使用时需以参数方式指定transformation

  2. transformation的格式为algorithm/mode/padding(算法/模式/填充),其中algorithm(算法)为必输项,如: DES/CBC/PKCS5Padding

  3. 缺省的mode为ECB,缺省的padding为PKCS5Padding

  4. 在block算法与流加密模式组合时, 需在mode后面指定每次处理的bit数, 如DES/CFB8/NoPadding, 如未指定则使用缺省值, SunJCE缺省值为64bits

  5. Cipher有4种操作模式: ENCRYPT_MODE(加密), DECRYPT_MODE(解密), WRAP_MODE(导出Key), UNWRAP_MODE(导入Key),初始化时需指定某种操作模式(都是静态参数)。

对称加密的算法与密钥长度选择

算法名称 密钥长 块长 速度 说明
DES 56 64 不安全, 不要使用
3DES 112/168 64 很慢 中等安全, 适合加密较小的数据
AES 128, 192, 256 128 安全
Blowfish (4至56)*8 64 应该安全, 在安全界尚未被充分分析、论证
RC4 40-1024 64 很快 安全性不明确

一般情况下,不要选择DES算法,推荐使用AES算法。一般认为128bits的密钥已足够安全,如果可以请选择256bits的密钥。

密钥长度是在生成密钥时指定的。如:

1
2
3
KeyGenerator generator = KeyGenerator.getInstance("AES/CBC/PKCS5PADDING");
generator.init(256);
SecretKey key = generator.generateKey();

加密示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 根据密钥{@link #getKey()}对指定的明文
* plainText
* 进行加密.
*
* @param plainText 明文
* @return 加密后的密文.
*/
public static final String encrypt(String plainText) {
Key secretKey = getKey();
try {
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] p = plainText.getBytes("UTF-8");
byte[] result = cipher.doFinal(p);
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(result);
return encoded;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

解密示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 根据密钥{@link #getKey()}对指定的密文
* cipherText
* 进行解密.
*
* @param cipherText 密文
* @return 解密后的明文.
*/
public static final String decrypt(String cipherText) {
Key secretKey = getKey();
try {
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
BASE64Decoder decoder = new BASE64Decoder();
byte[] c = decoder.decodeBuffer(cipherText);
byte[] result = cipher.doFinal(c);
String plainText = new String(result, "UTF-8");
return plainText;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

带算法参数的加解密

Cipher可能用到算法参数(AlgorithmParameterSpec或AlgorithmParameters)的情形:

  • DES, DES-EDE, and Blowfish使用feedback模式时(如CBC, CFB, OFB或PCBC), 将用到IV
  • PBEWithMD5AndDES将用到salt和iteration count
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 根据密钥{@link #getKey()}对指定的密文
* cipherText
* 进行解密.
*
* @param cipherText 密文
* @return 解密后的明文.
*/
public static final String decrypt(String cipherText) {
Key secretKey = getKey();
try {
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
BASE64Decoder decoder = new BASE64Decoder();
byte[] c = decoder.decodeBuffer(cipherText);
byte[] result = cipher.doFinal(c);
String plainText = new String(result, "UTF-8");
return plainText;
} catch (Exception e) {
throw new RuntimeException(e);
}
}

密钥生成

非对称密钥的生成请参考java.security.KeyPairGenerator,样例代码请参考JCA中的示例,对称密钥生成的示例代码如下

1
2
3
KeyGenerator gen = KeyGenerator.getInstance("DES");
gen.init(56, new SecureRandom());
Key key= gen.generateKey();

MAC生成

MAC技术用于确认数据的完整性,Mac要求通讯双方共享一个secret key,示例代码如下:

1
2
3
4
5
6
7
Key key = KeyGeneratorDemo.generateMac();
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
String msg = "新庄杨渡10#";
byte[] result = mac.doFinal(msg.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
System.out.println(encoder.encode(result));

MAC优于数据摘要的地方在于:MAC双方要共享一个密钥,所以其也有互相认证的功能,可有效防止数据摘要中明文和数据摘要被同时替换而无法发现的问题。

密钥协商

密钥协商就是在通讯多方间不直接交换通讯密钥的情况下而选择一个大家达成一致的密钥(session key),这个session key是对称密钥。

密钥协商可以通过2种途径实现

  1. 通过KeyAgreement组件完成,常用算法包括DH(Diffie-Hellman),ECDH(Elliptic Curve Diffie-Hellman),ECMQV(Elliptic Curve Menezes-Qu-Vanstone)等。
  2. 通过数字信封完成,常用算法包括RSA等。

通过KeyAgreement使用DH算法协商密钥

  1. DH算法由PKCS#3定义,DH算法需在多方间交换公钥,大素数p,私钥的基数g,和私钥的长度l。设协商密钥的双方为Alice和Bob,则协商共涉及5个阶段:
  • Alice生成DH公私密钥对
  • Alice将公钥和算法参数p,g和l发送给Bob
  • Bob根据算法参数生成自己的公私密钥对,并将公钥发送给Alice
  • Alice使用自己的私钥和Bob的公钥通过KeyAgreement得到通讯密钥
  • Bob使用自己的私钥和Alice的公钥通过KeyAgreement得到与Alice相同的通讯密钥

通过数字信封使用RSA算法协商密钥

数字信封的原理就是利用通讯对方的公钥加密目标密钥(session key,对称密钥),使用目标密钥对报文进行加密,然后将密钥密文与报文密文一起发送给接收方。接收方首先使用自己的私钥对密钥报文进行解密,这样就得到了协商后的密钥,再使用解密后的密钥解密报文,这样就得到了业务数据。过程图示如下:

  • a. DH仅限于交换共享密钥,而无法对交换双方的身份进行认证,易受中间人攻击
  • b. RSA可以用于交换共享密钥也可以用于身份认证
  • c. 建议:在双方都有数字证书时,使用RSA,一方或两方都没有数字证书则使用Diffie-Hellman,SSL3.0就是采用的此策略

总结

JCE中最常用和最核心的功能就是加解密,此功能由Cipher组件提供,在使用Cipher前需对加密算法及参数先做出选择:

算法选择

对称算法一般速度较快,非对称算法速度较慢;对称算法的密钥管理比较困难,非对称算法密钥管理简单;非对称算法一般用于认证和加密会话密钥,通讯双方大部分也就是在开启会话时使用一次,对称算法一般用来加密双方之间的报文/交换的数据,使用频度较高。

块/流模式选择

块(Block)模式加密以块为基本单位,适用于明文长度已知的情形;流(Stream)模式以bit或byte为加解密单位, 适用于明文长度未知、内容较大的情形,如加密一个套接字管道或文件读写流等,一般仅适用于硬件实现。块模式下不同算法的块大小可能不一样,一般都是2的次方数,大部分长度为64bits,整个明文长度不是块长度整倍数时,需在最后一个Block进行补长(Padding)

反馈模式选择

使用块算法加密,如果明文有大量重复的内容,则对块加密后得到的密文也会存在大量的重复,这对密文分析、破解提供了极大的便利,为消除这方面的威胁,有个思路就是对不同块密文再进行运算,这样就极大去除了块密文与块明文几间的特征关联,这种做法称为块反馈模式。常见的反馈模式有:ECB、CBC、CFB、OFB等。对于第1个block,因没有其它块密文可供运算,有的模式引入了初始矢量(Initialization Vector,IV,由用户指定)作为第1个block内容,这样就进一步解决了第1个block密文的脆弱性。注意:尽量不要使用ECB模式。

补长方案选择

密钥的选择

密钥可以使用KeyGenerator/KeyPairGenerator生成,也可以由外部导入,还可以有密钥参数构造KeySpec再转换为Key。

密钥长度选择

对于对称加密算法,128bits的密钥足够安全,条件许可请选择256bits,注意密钥长度大于128bits需单独下载并安装jurisdiction policy files;对于非对称加密算法,1024bits的密钥足够安全。

Your browser is out-of-date!

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

×