Java安全:证书存储与加密解密技术详解
1. 证书存储相关
在处理证书存储时,类型参数代表存储库类型的名称,例如LDAP或Java集合的Collection。每个存储库类型都有特定的
CertStoreParameters
。可以使用以下方法检索用于初始化
CertStore
的参数:
public final CertStoreParameters getCertStoreParameters()
为了从
CertStore
中检索证书和证书撤销列表(CRLs),引入了选择器的概念。选择器定义了用于选择一组证书或CRLs的标准。以下方法用于选择并返回一组证书或CRLs:
public final Collection getCertificates(CertSelector selector)
throws CertStoreException
public final Collection getCRLs(CRLSelector selector)
throws CertStoreException
每个方法都返回其相应对象的集合。选择器接口都定义了一个名为
match
的方法,该方法接受一个证书或CRL,如果指定的对象符合某些标准,则返回
true
,否则返回
false
。安全库中提供了这些接口的具体实现,例如
X509CertSelector
和
X509CRLSelector
,用于验证证书或CRL是否符合X509证书/CRL的格式。
2. Java加密扩展(JCE)概述
Java加密扩展(JCE)指定了其他重要的加密服务,以提供更完整的安全包。JCE基于与Java加密体系结构(JCA)相同的架构,因此是基于提供者的。J2SDK 1.6附带的默认提供者包名为
SunJCE
。JCE提供的服务如下:
-
加密/解密
:使用密钥将未加密的明文消息转换为加密形式,或执行相反的操作。
-
基于密码的加密(PBE)
:从给定的密码派生加密密钥,有时基于盐(随机数)来延长暴力攻击所需的时间,从而使暴力攻击更不可行。
-
Cipher
:基于特定算法执行信息加密和解密的对象。
-
密钥协商
:一种协议,使两个或多个参与方能够在无需共享秘密信息的情况下建立相同的加密密钥。
-
消息认证码(MAC)
:用于验证信息完整性/来源的短代码,类似于使用数字签名验证数据完整性/来源。
JCE提供的引擎类包括
Cipher
、
KeyGenerator
、
KeyAgreement
和
Mac
。下面将详细讨论这些引擎类及其相关类。
3. Cipher引擎类
Cipher
引擎类是JCE中最大的引擎类,它提供加密和解密支持。JCE还引入了
CipherInputStream
和
CipherOutputStream
,与
Cipher
对象结合使用时,可提供安全的输入和输出流。
Cipher
对象的
getInstance
方法与JCA中引擎类的
getInstance
方法不同。转换参数用于指定特定的转换,形式为
algorithm/mode/padding
或仅为
algorithm
。指定
DES
或
DES/ECB/PKCS5Padding
(
SunJCE
提供的默认算法/模式/填充)都是有效的。提供者参数允许你指定应使用的提供者。如果未指定提供者,则会找到提供所请求转换的提供者:
public static Cipher getInstance(String transformation);
public static Cipher getInstance(String transformation,
String provider);
对象创建后,
Cipher
对象必须使用操作模式和其他信息进行初始化。
init
方法有八种形式:
public void init(int opmode, Key key)
public void init(int opmode, Certificate certificate)
public void init(int opmode, Key key, SecureRandom random)
public void init(int opmode, Certificate certificate,
SecureRandom random)
public void init(int opmode, Key key,
AlgorithmParameterSpec params)
public void init(int opmode, Key key,
AlgorithmParameterSpec params, SecureRandom random)
public void init(int opmode, Key key,
AlgorithmParameters params)
public void init(int opmode, Key key,
AlgorithmParameters params, SecureRandom random)
opmode
参数可以取
Cipher
类中定义为最终整数的四个整数值之一。这些操作模式如下表所示:
| 操作模式常量名称 | 描述 |
| — | — |
| ENCRYPT_MODE | 配置
Cipher
以加密数据 |
| DECRYPT_MODE | 配置
Cipher
以解密数据 |
| WRAP_MODE | 将
Cipher
配置为密钥包装模式,将密钥转换为可安全传输的字节 |
| UNWRAP_MODE | 配置
Cipher
以解包先前包装的密钥 |
你可以通过
key
或
certificate
参数(对于包含密钥的证书)传入密钥。
params
参数包含所请求特定算法的参数,
random
用于使用不同于系统随机源的随机数生成器。
如果模式为
DECRYPT_MODE
,
Cipher
需要一个密钥和适当的参数。如果未指定这些参数,则会抛出
InvalidKeyException
或
InvalidAlgorithmParameterException
。如果
Cipher
配置为
ENCRYPT_MODE
,则这些参数将使用已定义的值进行配置,除非在
init
方法中明确传入。
4. 数据加密/解密操作
数据可以部分或一次性传递给
Cipher
对象。
update
方法用于一次传递一块数据,
doFinal
方法用于一次性传递所有数据或表示通过
update
方法传递的数据序列的结束:
public byte[] update(byte[] input)
public byte[] update(byte[] input, int inputOffset,
int inputLen)
public int update(byte[] input, int inputOffset,
int inputLen, byte[] output)
public int update(byte[] input, int inputOffset,
int inputLen, byte[] output, int outputOffset)
这些方法允许你将一块数据传递给
Cipher
。使用这些方法可以处理比一次性拥有的数据更多的数据。后两种形式将加密/解密的数据存储在传入的缓冲区中,而前两种形式返回数据。
以下方法用于一次性处理所有输入或在多次调用
update
后表示输入结束:
public byte[] doFinal(byte[] input)
public byte[] doFinal(byte[] input, int inputOffset,
int inputLen)
public int doFinal(byte[] input, int inputOffset,
int inputLen, byte[] output)
public int doFinal(byte[] input, int inputOffset,
int inputLen, byte[] output,
int outputOffset)
public byte[] doFinal();
public int doFinal(byte[] output, int outputOffset)
前四种形式允许你结合传递剩余数据和检索结果的操作。后两种形式表示输入结束,然后获取结果。最后一种形式返回输出的长度。
5. 密钥包装和解包
以下方法用于将密钥转换为可以安全轻松传输的字节序列。密钥使用
Cipher
进行加密,以便安全传输。对于接收方解包密钥,还需要传输密钥算法的名称和密钥类型(
SECRET_KEY
、
PRIVATE_KEY
或
PUBLIC_KEY
):
public final byte[] wrap(Key key)
此方法使用指定的算法和密钥类型解包包装的密钥。
wrappedKeyType
可以是
SECRET_KEY
、
PRIVATE_KEY
或
PUBLIC_KEY
:
public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
int wrappedKeyType)
以下方法有助于确定输出的大小,以便客户端代码在其缓冲区中为加密/解密数据分配足够的空间:
public int getOutputSize(int inputLen)
JCE
提供了两个类用于在文件输入/输出操作中链接密码。
CipherInputStream
继承自
FilterInputStream
类,
CipherOutputStream
继承自
FilterOutputStream
类。通过这些类传递的数据使用关联的
Cipher
对象进行加密或解密。
CipherInputStream
和
CipherOutputStream
的使用很简单,下面是一个示例:
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
public class CipherExample {
private Cipher m_encrypter;
private Cipher m_decrypter;
public void init(SecretKey key)
{
// for CBC; must be 8 bytes
byte[] initVector = new byte[]{0x10, 0x10, 0x01, 0x04,
0x01, 0x01, 0x01, 0x02};
AlgorithmParameterSpec algParamSpec =
new IvParameterSpec(initVector);
try {
m_encrypter = Cipher.getInstance("DES/CBC/PKCS5Padding");
m_decrypter = Cipher.getInstance("DES/CBC/PKCS5Padding");
m_encrypter.init(Cipher.ENCRYPT_MODE, key, algParamSpec);
m_decrypter.init(Cipher.DECRYPT_MODE, key, algParamSpec);
} catch (InvalidAlgorithmParameterException e) {
System.out.println("Exception: " + e);
} catch (NoSuchPaddingException e) {
System.out.println("Exception: " + e);
} catch (NoSuchAlgorithmException e) {
System.out.println("Exception: " + e);
} catch (InvalidKeyException e) {
System.out.println("Exception: " + e);
}
}
public void write(byte[] bytes, OutputStream out)
{
try {
CipherOutputStream cos =
new CipherOutputStream(out, m_encrypter);
cos.write(bytes, 0, bytes.length);
cos.close();
} catch(IOException ioe) {
System.out.println("Exception: " + ioe);
}
}
public void read(byte[] bytes, InputStream in)
{
try {
CipherInputStream cis =
new CipherInputStream(in, m_decrypter);
int pos=0, intValue;
while( (intValue = cis.read()) != -1) {
bytes[pos] = (byte)intValue;
pos++;
}
} catch(IOException ioe) {
System.out.println("Exception: " + ioe);
}
}
public byte[] encrypt(byte[] input)
{
try {
return(m_encrypter.doFinal(input));
} catch(IllegalBlockSizeException ibse) {
System.out.println("Exception: " + ibse);
} catch(BadPaddingException bpe) {
System.out.println("Exception: " + bpe);
}
return(null);
}
public byte[] decrypt(byte[] input)
{
try {
return(m_decrypter.doFinal(input));
} catch(IllegalBlockSizeException ibse) {
System.out.println("Exception: " + ibse);
} catch(BadPaddingException bpe) {
System.out.println("Exception: " + bpe);
}
return(null);
}
public static void main(String args[])
{
try {
CipherExample ce = new CipherExample();
SecretKey key =
KeyGenerator.getInstance("DES").generateKey();
ce.init(key);
System.out.println("Testing encrypt/decrypt of bytes");
byte[] clearText = new byte[]{65,73,82,68,65,78,67,69};
byte[] encryptedText = ce.encrypt(clearText);
byte[] decryptedText = ce.decrypt(encryptedText);
String clearTextAsString = new String(clearText);
String encTextAsString = new String(encryptedText);
String decTextAsString = new String(decryptedText);
System.out.println(" CLEARTEXT: " + clearTextAsString);
System.out.println(" ENCRYPTED: " + encTextAsString);
System.out.println(" DECRYPTED: " + decTextAsString);
System.out.println("\nTesting encrypting of a file\n");
FileInputStream fis = new FileInputStream("cipherTest.in");
FileOutputStream fos =
new FileOutputStream("cipherTest.out");
int dataInputSize = fis.available();
byte[] inputBytes = new byte[dataInputSize];
fis.read(inputBytes);
ce.write(inputBytes, fos);
fos.flush();
fis.close();
fos.close();
String inputFileAsString = new String(inputBytes);
System.out.println("INPUT FILE CONTENTS\n" +
inputFileAsString + "\n");
System.out.println("File encrypted and saved to disk\n");
fis = new FileInputStream("cipherTest.out");
byte[] decrypted = new byte[dataInputSize];
ce.read(decrypted, fis);
fis.close();
String decryptedAsString = new String(decrypted);
System.out.println("DECRYPTED FILE:\n" +
decryptedAsString + "\n");
} catch(IOException ioe) {
System.out.println("Exception: " + ioe);
} catch(NoSuchAlgorithmException e) {
System.out.println("Exception: " + e);
}
}
}
这个示例展示了如何使用
Cipher
类本身以及
CipherInputStream
和
CipherOutputStream
类。可以很容易地修改这个示例,使其作为使用
Cipher
引擎类的实用类。
6. KeyGenerator引擎类
KeyGenerator
引擎类用于为对称算法生成秘密密钥。它提供标准的
getInstance
方法。对象创建后,使用以下方法之一初始化
KeyGenerator
:
-
与算法无关的初始化方法
:
public void init(SecureRandom random)
public void init(int keysize)
public void init(int keysize, SecureRandom random)
- 与算法相关的初始化方法 :
public void init(AlgorithmParameterSpec params)
public void init(AlgorithmParameterSpec params, SecureRandom random)
与算法无关的初始化允许你指定随机数生成器(RNG)或密钥大小,或两者都指定,作为初始化密钥生成器的参数。与算法相关的初始化方法接受一组参数(可能还有RNG),这些参数与所选算法一起使用。这些参数取决于所使用的算法。
KeyGenerator
创建并初始化后,调用
generateKey
方法生成秘密密钥:
public SecretKey generateKey()
可以参考前面的
Cipher
示例,了解
KeyGenerator
的实际使用。
7. SecretKeyFactory引擎类
SecretKeyFactory
与
java.security
包中的
KeyFactory
非常相似,但这个引擎类仅处理秘密(对称)密钥。该类用于在密钥的透明和不透明表示之间进行转换。使用标准的
getInstance
方法创建
SecretKeyFactory
对象。主要使用三个方法来操作密钥:
generateSecret
、
getKeySpec
和
translateKey
。
SecretKey generateSecret(KeySpec keySpec)
将密钥规范转换为
SecretKey
对象。如果工厂无法使用当前算法转换密钥,则抛出
InvalidKeySpecException
。
KeySpec getKeySpec(SecretKey key, Class keySpec)
将密钥转换为
keySpec
参数指定格式的密钥规范。如果工厂由于算法或其他不匹配(如不兼容的格式)而无法执行转换,则抛出
InvalidKeySpecException
。
SecretKey translateKey(SecretKey key)
将来自未知或不可信提供者的密钥对象转换为该工厂的密钥对象。
8. SealedObject类的使用
JCE
提供的一个有用的类是
SealedObject
,它可以对任何可序列化的对象进行加密和解密。
SealedObject
类用于加密任何可序列化的类,它与
Cipher
类的实例一起使用。
SealedObject
的构造函数用于指定要密封的对象和已初始化的
Cipher
对象。稍后使用三个
getObject
方法之一来解密对象。可以使用
getAlgorithm
方法检索用于加密对象的算法名称:
Object getObject(Cipher c)
Object getObject(Key key)
Object getObject(Key key, String provider)
第一种形式使用提供的
Cipher
解密对象。第二种形式使用加密对象的算法解密对象,需要一个密钥进行解密。最后一种形式允许你指定特定的提供者以及解密对象所需的密钥。
下面是一个创建自定义类、密封它然后解封它的示例:
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
class CustomerData implements Serializable {
public String name;
public String password;
}
public class SealedObjectExample {
private SecretKey secretKey;
private Cipher encrypter, decrypter;
public SealedObjectExample()
{
try {
secretKey = KeyGenerator.getInstance("DES").generateKey();
encrypter = Cipher.getInstance("DES");
encrypter.init(Cipher.ENCRYPT_MODE, secretKey);
decrypter = Cipher.getInstance("DES");
decrypter.init(Cipher.DECRYPT_MODE, secretKey);
} catch(NoSuchAlgorithmException e) {
} catch(InvalidKeyException e) {
} catch(NoSuchPaddingException e) {
}
}
public SealedObject seal(Serializable obj)
{
try {
return(new SealedObject(obj, encrypter));
} catch(IOException e) {
} catch(IllegalBlockSizeException e) {
}
return(null);
}
public Object unseal(SealedObject so)
{
try {
String algorithmName = so.getAlgorithm();
// can use algorithmName to construct a decrypter
return(so.getObject(decrypter));
} catch(IOException e) {
} catch(IllegalBlockSizeException e) {
} catch(BadPaddingException e) {
} catch(ClassNotFoundException e) {
}
return(null);
}
public static void main(String args[])
{
CustomerData cust, unsealed;
SealedObject sealed;
SealedObjectExample soe = new SealedObjectExample();
// configure a CustomerData object
cust = new CustomerData();
cust.name = "Paul";
cust.password = "password";
// Seal it, storing it in a SealedObject
sealed = soe.seal(cust);
// Try unsealing it
unsealed = (CustomerData)soe.unseal(sealed);
System.out.println("NAME: " + unsealed.name);
System.out.println("PASSWORD: " + unsealed.password);
}
}
要密封的类的唯一要求是它继承自
Serializable
。
SealedObject
类包含密封的对象,解封对象所需的只是
SealedObject
对象。可以使用
SealedObject
类的
getAlgorithm
方法检索用于密封对象的算法名称。还需要一个
Cipher
对象来执行解封操作。
9. 消息认证码的计算
Mac
引擎类根据给定的秘密密钥为输入数据计算哈希值,类似于消息摘要。
Mac
类具有标准的
getInstance
方法用于对象创建。创建后,必须使用以下方法之一初始化对象:
public void init(Key key)
public void init(Key key, AlgorithmParameterSpec params)
密钥必须是继承自
javax.crypto.SecretKey
接口的密钥类,例如
KeyGenerator.generateKey()
或
KeyAgreement.generateSecret()
。某些算法要求生成密钥的算法与
getInstance
调用中指定的算法兼容。如果不兼容,则抛出
InvalidKeyException
。
Mac
类在向计算引擎发送数据时遵循类似的语义。数据可以使用
doFinal
方法一次性传递,也可以使用
update
方法逐块传递(然后调用
doFinal
表示输入结束):
public byte[] doFinal(byte[] input)
public byte[] doFinal()
public void doFinal(byte[] output, int outOffset)
第一个
doFinal
方法接受包含输入数据的字节数组,计算消息认证码,并以字节数组的形式返回。第二种形式用于在多次调用
update
方法后表示输入结束。最后一种形式可在一系列
update
方法之后使用,既接受最后一块数据,又表示输入结束。
outOffset
参数指定在输出数组中开始读取数据的位置,数据在数组末尾结束。
以下三个方法用于逐块向
Mac
类发送数据:
public void update(byte input)
public void update(byte[] input)
public void update(byte[] input, int inputOffset, int inputLen)
第一个方法接受单个字节的输入。第二个方法接受字节数组。第三个方法允许你传入数组,并指定从数组的
inputOffset
位置开始读取数据的长度
inputLen
。调用
update
完成后,别忘了调用
doFinal
的某个版本来表示输入结束并计算消息认证码。
综上所述,Java的安全机制通过这些丰富的类和方法为开发者提供了强大的工具,能够实现各种复杂的安全需求,包括证书管理、加密解密、密钥生成和消息认证等。在实际应用中,开发者可以根据具体的场景选择合适的类和方法,确保数据的安全性和完整性。
Java安全:证书存储与加密解密技术详解
10. 各引擎类操作流程总结
为了更清晰地理解各引擎类的使用流程,下面通过 mermaid 流程图展示主要操作步骤。
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([开始]):::startend --> B(创建 KeyGenerator):::process
B --> C{初始化方式?}:::decision
C -->|算法无关| D(init(SecureRandom random)):::process
C -->|算法无关| E(init(int keysize)):::process
C -->|算法无关| F(init(int keysize, SecureRandom random)):::process
C -->|算法相关| G(init(AlgorithmParameterSpec params)):::process
C -->|算法相关| H(init(AlgorithmParameterSpec params, SecureRandom random)):::process
D --> I(generateKey()):::process
E --> I
F --> I
G --> I
H --> I
I --> J(创建 Cipher):::process
J --> K(init(int opmode, Key key...)):::process
K --> L{操作模式?}:::decision
L -->|ENCRYPT_MODE| M(加密数据):::process
L -->|DECRYPT_MODE| N(解密数据):::process
L -->|WRAP_MODE| O(包装密钥):::process
L -->|UNWRAP_MODE| P(解包密钥):::process
M --> Q(结束):::startend
N --> Q
O --> Q
P --> Q
这个流程图展示了从生成密钥到使用 Cipher 进行各种操作的主要步骤。首先通过 KeyGenerator 生成密钥,然后使用该密钥初始化 Cipher,最后根据不同的操作模式进行相应的操作。
11. 各引擎类使用注意事项
-
Cipher 类
-
初始化参数
:在使用
init方法初始化 Cipher 时,要确保传入的参数正确。特别是在DECRYPT_MODE下,必须提供合适的密钥和参数,否则会抛出异常。 -
输出大小
:在处理大量数据时,使用
getOutputSize方法预先计算输出大小,避免缓冲区溢出。
-
初始化参数
:在使用
-
KeyGenerator 类
- 算法兼容性 :选择合适的算法进行密钥生成,确保与后续使用的 Cipher 算法兼容。
- 随机数生成器 :合理使用随机数生成器,增强密钥的安全性。
-
SecretKeyFactory 类
-
密钥转换
:在进行密钥转换时,要确保密钥规范和算法的兼容性,避免
InvalidKeySpecException异常。
-
密钥转换
:在进行密钥转换时,要确保密钥规范和算法的兼容性,避免
-
Mac 类
-
算法匹配
:生成密钥的算法必须与
getInstance调用中指定的算法兼容,否则会抛出InvalidKeyException。 -
数据处理
:使用
update和doFinal方法时,要注意数据的传递顺序和完整性。
-
算法匹配
:生成密钥的算法必须与
12. 实际应用场景分析
-
数据加密存储
:在需要将敏感数据存储在本地或远程服务器时,可以使用 Cipher 类对数据进行加密。例如,用户密码、个人信息等。具体操作步骤如下:
- 使用 KeyGenerator 生成密钥。
-
初始化 Cipher 为
ENCRYPT_MODE。 - 将数据传递给 Cipher 进行加密。
- 将加密后的数据存储。
-
数据传输安全
:在网络传输过程中,为了防止数据被窃取或篡改,可以使用 CipherInputStream 和 CipherOutputStream 对数据进行加密和解密。例如,在客户端和服务器之间传输文件时:
- 客户端使用 CipherOutputStream 对文件进行加密后发送。
- 服务器使用 CipherInputStream 对接收的文件进行解密。
-
消息认证
:在需要验证消息的完整性和来源时,可以使用 Mac 类计算消息认证码。例如,在分布式系统中,节点之间传递消息时:
- 发送方使用 Mac 类计算消息的认证码,并将消息和认证码一起发送。
- 接收方使用相同的密钥和算法重新计算认证码,并与接收到的认证码进行比较。
13. 代码示例优化建议
-
异常处理
:在实际应用中,要对可能出现的异常进行更细致的处理。例如,在
CipherExample类中,可以将异常信息记录到日志文件中,而不仅仅是打印到控制台。
import java.io.FileWriter;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.BadPaddingException;
import java.security.spec.InvalidKeySpecException;
public class CipherExample {
private Cipher m_encrypter;
private Cipher m_decrypter;
public void init(SecretKey key) {
byte[] initVector = new byte[]{0x10, 0x10, 0x01, 0x04, 0x01, 0x01, 0x01, 0x02};
AlgorithmParameterSpec algParamSpec = new IvParameterSpec(initVector);
try {
m_encrypter = Cipher.getInstance("DES/CBC/PKCS5Padding");
m_decrypter = Cipher.getInstance("DES/CBC/PKCS5Padding");
m_encrypter.init(Cipher.ENCRYPT_MODE, key, algParamSpec);
m_decrypter.init(Cipher.DECRYPT_MODE, key, algParamSpec);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
logException(e);
}
}
private void logException(Exception e) {
try (FileWriter writer = new FileWriter("error.log", true)) {
writer.write(e.toString() + "\n");
} catch (IOException ioe) {
System.out.println("Failed to log exception: " + ioe);
}
}
// 其他方法保持不变
}
-
资源管理
:在使用流和对象时,要确保资源的正确关闭。可以使用
try-with-resources语句来简化代码并确保资源的自动关闭。例如,在CipherExample类的write和read方法中:
public void write(byte[] bytes, OutputStream out) {
try (CipherOutputStream cos = new CipherOutputStream(out, m_encrypter)) {
cos.write(bytes, 0, bytes.length);
} catch (IOException ioe) {
logException(ioe);
}
}
public void read(byte[] bytes, InputStream in) {
try (CipherInputStream cis = new CipherInputStream(in, m_decrypter)) {
int pos = 0, intValue;
while ((intValue = cis.read()) != -1) {
bytes[pos] = (byte) intValue;
pos++;
}
} catch (IOException ioe) {
logException(ioe);
}
}
14. 总结
Java 提供了丰富的安全类和方法,涵盖了证书存储、加密解密、密钥生成、消息认证等多个方面。通过合理使用这些类和方法,开发者可以实现复杂的安全需求,确保数据的安全性和完整性。在实际应用中,要注意各引擎类的使用流程和注意事项,根据具体的场景选择合适的类和方法。同时,要对代码进行优化,提高代码的健壮性和可维护性。
以下是一个总结表格,展示各引擎类的主要功能和使用场景:
| 引擎类 | 主要功能 | 使用场景 |
| — | — | — |
| Cipher | 数据加密、解密、密钥包装和解包 | 数据加密存储、数据传输安全 |
| KeyGenerator | 生成对称密钥 | 为加密和解密操作提供密钥 |
| SecretKeyFactory | 密钥的透明和不透明表示转换 | 密钥管理 |
| Mac | 计算消息认证码 | 消息完整性和来源验证 |
通过对这些内容的深入理解和实践,开发者可以更好地掌握 Java 的安全机制,为应用程序的安全保驾护航。
超级会员免费看

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



