Java安全编程:证书读取、加密及算法标准详解
1. 读取包含证书的文件
在处理包含证书的文件时,我们常常会遇到Base64编码的证书,这些证书以
-----BEGIN CERTIFICATE-----
开头,以
-----END CERTIFICATE-----
结尾。下面为你介绍两种读取此类文件的方法。
1.1 逐个读取证书
此方法将
FileInputStream
转换为
ByteArrayInputStream
,这样每次调用
generateCertificate
时,输入流的读取位置都能正确定位。具体代码如下:
FileInputStream fis = new FileInputStream(filename);
DataInputStream dis = new DataInputStream(fis);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
byte[] bytes = new byte[dis.available()];
dis.readFully(bytes);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
while (bais.available() > 0) {
Certificate cert = cf.generateCertificate(bais);
System.out.println(cert.toString());
}
1.2 解析PKCS #7格式的证书回复
当需要从PKCS #7格式的文件中提取所有证书时,可以使用以下代码:
FileInputStream fis = new FileInputStream(filename);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection c = cf.generateCertificates(fis);
Iterator i = c.iterator();
while (i.hasNext()) {
Certificate cert = (Certificate) i.next();
System.out.println(cert.toString());
}
1.3 流程图
graph TD
A[开始] --> B[打开文件输入流]
B --> C{选择读取方式}
C -->|逐个读取| D[转换为字节数组输入流]
C -->|解析PKCS #7| E[生成证书集合]
D --> F[逐个生成证书并输出]
E --> G[遍历集合输出证书]
F --> H[结束]
G --> H
2. 使用加密技术
2.1 生成密钥
以DES加密算法为例,使用
KeyGenerator
生成密钥:
KeyGenerator keygen = KeyGenerator.getInstance("DES");
SecretKey desKey = keygen.generateKey();
2.2 创建并初始化密码器
创建一个DES密码器,采用电子密码本(ECB)模式和PKCS #5填充方式:
Cipher desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
desCipher.init(Cipher.ENCRYPT_MODE, desKey);
2.3 加密和解密操作
byte[] cleartext = "This is just an example".getBytes();
byte[] ciphertext = desCipher.doFinal(cleartext);
desCipher.init(Cipher.DECRYPT_MODE, desKey);
byte[] cleartext1 = desCipher.doFinal(ciphertext);
2.4 操作步骤总结
-
生成密钥:使用
KeyGenerator实例化并生成密钥。 - 创建密码器:指定算法、模式和填充方式。
- 初始化密码器:选择加密或解密模式。
-
执行加密或解密操作:调用
doFinal方法。
3. 使用基于密码的加密
3.1 收集用户密码
由于
String
对象不可变,不适合存储敏感信息,因此使用
char
数组收集用户密码:
public char[] readPasswd(InputStream in) throws IOException {
char[] buf;
int i;
buf = lineBuffer = new char[128];
int room = buf.length;
int offset = 0;
int c;
while (true) {
switch (c = in.read()) {
case -1:
case '\n':
break loop;
int c2 = in.read();
if ((c2 != '\n') && (c2 != -1)) {
if (!(in instanceof PushbackInputStream)) {
in = new PushbackInputStream(in);
}
((PushbackInputStream)in).unread(c2);
} else {
break loop;
}
default:
if (--room < 0) {
buf = new char[offset + 128];
room = buf.length - offset - 1;
System.arraycopy(lineBuffer, 0, buf, 0, offset);
Arrays.fill(lineBuffer, ' ');
lineBuffer = buf;
}
buf[offset++] = (char) c;
break;
}
if (offset == 0) {
return null;
}
char[] ret = new char[offset];
System.arraycopy(buf, 0, ret, 0, offset);
return ret;
}
}
3.2 生成PBE密钥和参数
PBEKeySpec pbeKeySpec;
PBEParameterSpec pbeParamSpec;
SecretKeyFactory keyFac;
byte[] salt = { (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c, (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99 };
int count = 20;
pbeParamSpec = new PBEParameterSpec(salt, count);
System.out.print("Enter encryption password: ");
System.out.flush();
pbeKeySpec = new PBEKeySpec(readPasswd(System.in));
keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
3.3 创建并初始化PBE密码器
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
3.4 加密操作
byte[] cleartext = "This is another example".getBytes();
byte[] ciphertext = pbeCipher.doFinal(cleartext);
3.5 操作步骤总结
-
收集用户密码:使用
readPasswd方法。 - 生成盐和迭代次数:用于PBE加密。
- 创建PBE密钥规范和参数规范。
-
生成PBE密钥:使用
SecretKeyFactory。 - 创建并初始化PBE密码器。
- 执行加密操作。
4. 标准名称
4.1 消息摘要算法
| 算法名称 | 描述 |
|---|---|
| MD2 | 定义于RFC 1319,输出128位摘要 |
| MD5 | 定义于RFC 1321,输出128位摘要 |
| SHA-1 | 定义于NIST FIPS 180 - 2,160位哈希函数 |
| SHA-256 | 256位哈希函数,提供128位安全 |
| SHA-384 | 可通过截断SHA - 512获得 |
| SHA-512 | 512位哈希函数,提供256位安全 |
4.2 密钥和参数算法
| 算法名称 | 描述 |
|---|---|
| DSA | 数字签名算法,定义于FIPS PUB 186 |
| RSA | 加密算法,定义于PKCS #1 |
| Diffie-Hellman | 密钥交换算法,定义于PKCS #3 |
| Blowfish | Bruce Schneier设计的块密码 |
| DES | 数据加密标准,定义于FIPS PUB 46 - 2 |
| DESede | 三重DES加密 |
| PBE | 基于密码的加密算法(PKCS #5) |
4.3 数字签名算法
| 算法名称 | 描述 |
|---|---|
| SHA1withDSA | 使用SHA - 1摘要和DSA创建并验证签名 |
| MD2withRSA | 使用MD2摘要和RSA创建并验证签名 |
| MD5withRSA | 使用MD5摘要和RSA创建并验证签名 |
| SHA1withRSA | 使用SHA - 1和RSA的签名算法 |
| with | 用于形成特定摘要和加密算法的签名算法名称 |
4.4 随机数生成算法
| 算法名称 | 描述 |
|---|---|
| SHA1PRNG | SUN提供的伪随机数生成算法,基于SHA - 1 |
4.5 证书类型
| 证书类型 | 描述 |
|---|---|
| X.509 | 定义于X.509 |
4.6 密钥库类型
| 密钥库类型 | 描述 |
|---|---|
| JKS | SUN提供的密钥库实现 |
| PKCS12 | 个人身份信息传输语法,定义于PKCS #12 |
| JCEKS | SunJCE提供的密钥库实现 |
4.7 服务属性
| 属性名称 | 描述 |
|---|---|
| KeySize | 提供者支持的最大密钥大小 |
| ImplmentedIn | 实现方式:软件或硬件 |
4.8 密码器算法、模式和填充
4.8.1 算法
| 算法名称 | 描述 |
|---|---|
| AES | 高级加密标准,支持128、192和256位密钥 |
| Blowfish | Bruce Schneier设计的块密码 |
| DES | 数据加密标准 |
| DESede | 三重DES加密 |
| PBEWith And | 基于密码的加密算法 |
| RC2, RC4, RC5 | Ron Rivest开发的可变密钥大小加密算法 |
| RSA | 加密算法,定义于PKCS #1 |
4.8.2 模式
| 模式名称 | 描述 |
|---|---|
| NONE | 无模式 |
| CBC | 密码块链接模式,定义于FIPS PUB 81 |
| CFB | 密码反馈模式,定义于FIPS PUB 81 |
| ECB | 电子密码本模式,定义于NIST FIPS PUB 81 |
| OFB | 输出反馈模式,定义于FIPS PUB 81 |
| PCBC | 传播密码块链接模式,由Kerberos V4定义 |
4.8.3 填充
| 填充名称 | 描述 |
|---|---|
| NoPadding | 无填充 |
| OAEPWith And Padding | 最优非对称加密填充,如OAEPWithMD5AndMGF1Padding |
| PKCS5Padding | 定义于RSA Laboratories的PKCS #5 |
| SSL3Padding | 定义于SSL协议版本3.0 |
4.9 密钥生成算法
| 算法名称 | 描述 |
|---|---|
| AES | 高级加密标准 |
| Blowfish | 块密码 |
| DES | 数据加密标准 |
| DESede | 三重DES加密 |
| HmacMD5 | HMAC - MD5密钥哈希算法 |
| HmacSHA1 | HMAC - SHA1密钥哈希算法 |
4.10 秘密密钥算法
| 算法名称 | 描述 |
|---|---|
| AES | 高级加密标准 |
| DES | 数据加密标准 |
| DESede | 三重DES加密 |
| PBEWith And | 基于密码的加密算法 |
4.11 MAC算法
| 算法名称 | 描述 |
|---|---|
| HmacMD5 | 定义于RFC 2104的HMAC - MD5密钥哈希算法 |
| HmacSHA1 | 定义于RFC 2104的HMAC - SHA1密钥哈希算法 |
| PBEWith | 用于PKCS #5 v2.0基于密码的消息认证 |
5. 算法规范
5.1 SHA - 1消息摘要算法
- 名称 :SHA - 1
- 类型 :MessageDigest
- 描述 :定义于NIST的FIPS 180 - 1,输出160位摘要
5.2 MD2消息摘要算法
- 名称 :MD2
- 类型 :MessageDigest
- 描述 :定义于RFC 1319,输出128位摘要
5.3 MD5消息摘要算法
- 名称 :MD5
- 类型 :MessageDigest
- 描述 :定义于RFC 1321,输出128位摘要
5.4 数字签名算法(SHA1withDSA)
- 名称 :SHA1withDSA
- 类型 :Signature
- 描述 :使用DSA和SHA - 1消息摘要算法,定义于NIST FIPS 186
- 密钥对算法 :DSA
6. 算法规范的重要性及应用场景
6.1 算法规范的重要性
在实现加密算法时,遵循标准的算法规范至关重要。这些规范确保了不同实现之间的互操作性和安全性。例如,当使用特定的数字签名算法时,遵循标准规范可以保证签名的生成和验证过程在不同系统中能够正确执行。如果不遵循规范,可能会导致签名验证失败,从而影响系统的安全性和可靠性。
6.2 应用场景分析
不同的算法适用于不同的应用场景,下面通过表格展示部分算法的应用场景:
| 算法类型 | 算法名称 | 应用场景 |
| ---- | ---- | ---- |
| 消息摘要算法 | SHA - 1 | 用于文件完整性验证、数字签名中的摘要生成等,但由于其安全性逐渐降低,在一些对安全性要求较高的场景中逐渐被替代 |
| 消息摘要算法 | MD5 | 早期常用于文件校验,但由于存在碰撞漏洞,不适合用于安全敏感的场景 |
| 密钥和参数算法 | RSA | 广泛用于安全通信、数字签名、密钥交换等场景,如HTTPS协议中的密钥交换 |
| 数字签名算法 | SHA1withDSA | 在需要进行数字签名的场景中使用,如电子文档的签名、软件的数字签名等 |
| 随机数生成算法 | SHA1PRNG | 用于生成随机数,如在加密密钥生成过程中作为随机数源 |
6.3 流程图:算法选择流程
graph TD
A[开始] --> B{应用场景需求}
B -->|文件完整性验证| C(SHA - 1、MD5等消息摘要算法)
B -->|安全通信、密钥交换| D(RSA、Diffie - Hellman等密钥和参数算法)
B -->|数字签名| E(SHA1withDSA、MD5withRSA等数字签名算法)
B -->|随机数生成| F(SHA1PRNG等随机数生成算法)
C --> G[选择合适算法]
D --> G
E --> G
F --> G
G --> H[结束]
7. 总结与实践建议
7.1 总结
本文详细介绍了Java安全编程中的多个重要方面,包括读取包含证书的文件、使用加密技术、基于密码的加密、标准名称和算法规范等内容。通过具体的代码示例和操作步骤,展示了如何在Java中实现这些安全功能。同时,对各种算法的标准名称和规范进行了梳理,为开发者在选择和使用算法时提供了参考。
7.2 实践建议
- 证书读取 :在读取包含证书的文件时,根据文件的格式选择合适的读取方法。如果是Base64编码的单个证书文件,可以使用逐个读取的方法;如果是PKCS #7格式的证书回复文件,则使用解析PKCS #7的方法。
- 加密技术 :在使用加密技术时,要根据实际需求选择合适的加密算法、模式和填充方式。例如,对于对称加密,可以选择DES、AES等算法;对于非对称加密,可以选择RSA算法。同时,要注意密钥的生成和管理,确保密钥的安全性。
-
基于密码的加密
:在收集用户密码时,使用
char数组代替String对象,以避免密码信息的泄露。在生成PBE密钥和参数时,要确保盐和迭代次数的安全性和一致性。 - 算法选择 :在选择算法时,要考虑算法的安全性、性能和应用场景。遵循标准的算法规范,确保不同实现之间的互操作性和安全性。
7.3 操作步骤总结表
| 操作类型 | 操作步骤 |
|---|---|
| 证书读取 |
1. 打开文件输入流
2. 根据文件格式选择读取方法(逐个读取或解析PKCS #7) 3. 生成并输出证书 |
| 加密操作 |
1. 生成密钥:使用
KeyGenerator
实例化并生成密钥
2. 创建密码器:指定算法、模式和填充方式 3. 初始化密码器:选择加密或解密模式 4. 执行加密或解密操作:调用
doFinal
方法
|
| 基于密码的加密 |
1. 收集用户密码:使用
readPasswd
方法
2. 生成盐和迭代次数:用于PBE加密 3. 创建PBE密钥规范和参数规范 4. 生成PBE密钥:使用
SecretKeyFactory
5. 创建并初始化PBE密码器 6. 执行加密操作 |
通过以上总结和建议,希望开发者能够更好地在Java中实现安全编程,保护系统和数据的安全。
超级会员免费看

被折叠的 条评论
为什么被折叠?



