转自:https://www.jianshu.com/p/a8194c237363
JCA是平台的一个主要部分,包含一个“Provider”体系结构和一组用于数字签名,消息摘要(哈希),证书和证书验证,加密(对称/非对称块/流密码),密钥生成 管理和安全随机数生成等等。
JCA包含两个软件组件:
JDK中提供的其他密码通信库使用JCA提供程序体系结构,但在别处进行了介绍。
Java安全套接字扩展(JSSE)提供对安全套接字层(SSL)和传输层安全性(TLS)实现的访问。
Java通用安全服务(JGSS)(通过Kerberos)API以及简单身份验证和安全层(SASL)也可用于在通信应用程序之间安全地交换消息。
JCE(Java Cryptography Extension),在早期JDK版本中,由于受美国的密码出口条例约束,Java中涉及加解密功能的API被限制出口,所以Java中安全组件被分成了两部分: 不含加密功能的JCA(Java Cryptography Architecture )和含加密功能的JCE(Java Cryptography Extension)。现在JCE已经捆绑在JDK中,所以,这里JCE是JCA的一部分。
实现独立性和互操作性
算法独立性和可扩展性
JCA提供标准化的、算法特定的API来实现上面两个原则。
JCA相关安全API软件包:
provider提供者,这里的全称是 Cryptographic Service Provider (CSP),是指实现一个或多个密码服务(如数字签名算法,消息摘要算法和密钥转换服务)的包或一组包。 每个JDK安装都默认安装并配置了一个或多个provider包。用户可以静态或动态添加其他provider。
JDK中的加密库出于历史原因,由几个不同的提供者实现:
java.security.Provider是所有安全提供程序的基类。
有两者指定Provider的方式:
图片.png
图片.png
JCA使用引擎类作为路由来实现Provider的关联,实现算法独立性。
下面的案例,展示了引擎类的使用,获取Provider对象实例的过程:
例如
import javax.crypto.*;
Cipher c = Cipher.getInstance("AES");
c.init(ENCRYPT_MODE, key);
图片.png
引擎类为特定类型的密码服务提供接口,而不依赖于特定的密码算法或提供者。 引擎需要提供:
以下引擎类是可用的:
注意:生成器可以创建具有全新内容的对象,而工厂只能从现有材料(例如编码)中创建对象。
Security类管理已安装的提供程序和安全性属性。 它只包含静态方法,永远不会实例化。
提供了一系列API查询Provider、增加Provider、删除Provider
Provider[] arr = Security.getProviders();
SecureRandom类是提供随机数生成器(RNG)功能的引擎类。 它不同于java.lang.Random类,因为它产生密码强的随机数。 如果生成器中的随机性不足,则会使保护机制变得更加容易。 在密码学中使用随机数字,例如生成加密密钥,算法参数等等。
MessageDigest类是一个引擎类,用于提供密码安全的消息摘要(如SHA-256或SHA-512)的功能。 加密安全的消息摘要采用任意大小的输入(一个字节数组),并生成一个固定大小的输出,称为摘要或散列。
图片.png
Signature类是一个引擎类,旨在提供加密数字签名算法(如DSA或RSAwithMD5)的功能。 密码安全签名算法采用任意大小的输入和私钥,并生成一个相对较短(通常是固定大小)的字节串,称为签名,具有以下属性:
只有私钥/公钥对的所有者才能创建签名。 任何拥有公钥的人都可以在计算上不可能恢复私钥
鉴于与用于生成签名的私钥相对应的公钥,应该有可能验证输入的真实性和完整性。
签名和公钥没有透露有关私钥的任何信息。
图片.png
Cipher类提供用于加密和解密的加密密码的功能。 加密是取数据(称为明文)和密钥的过程,并且产生对不知道密钥的第三方毫无意义的数据(密文)。 解密是相反的过程:取密文和密钥并产生明文。
图片.png
HMAC是基于密码散列函数的MAC。 HMAC可以与任何密码散列函数(例如SHA-256)结合秘密共享密钥一起使用。
图片.png
秘钥有两种表示形式:key(不透明)和keyspecs(透明)。
秘钥可以通过以下方式获得:
java.security.Key接口是所有不透明密钥的顶层接口。
以下是在java.security.interfaces和javax.crypto.interfaces包中扩展Key接口的接口列表:
SecretKey用于对称秘钥
PublicKey和PrivateKey接口分别用于非对称秘钥的公钥和私钥。
KeyPair类是密钥对(公钥和私钥)的简单持有者。
也叫密钥规范(密钥材料)接口
java.security.spec包中的密钥规范接口和类。
DESKeySpec是一种DES密钥规范。
X509EncodedKeySpec是一种公钥编码规范,它表示公钥的DER编码,根据X.509标准中规定的格式。
PKCS8EncodedKeySpec是一种私钥编码规范,以PKCS8标准中指定的格式对私钥进行DER编码。
KeySpecs实现的子类如下:
图片.png
生成器用于生成一个全新的对象(秘钥)。比如KeyGenerator生成SecretKey,KeyPairGenerator生成KeyPair。
生成器一般有两种方法来生成密钥对
void initialize(int keysize, SecureRandom random)
void initialize(int keysize)
void initialize(AlgorithmParameterSpec params, SecureRandom random)
void initialize(AlgorithmParameterSpec params)
KeyPairGenerator类,用于生成公钥和私钥对的引擎类。
图片.png
KeyGenerator类, 用于为对称算法生成密钥。
图片.png
工厂类用于将数据从一个现有的对象类型转换为另一个。一个密钥工厂可以用来在兼容的密钥规范之间进行转换。
比如SecretKeyFactory和KeyFactory,可以转换keySpecs为key。比如CertificateFactory,从字节输入流(FileInputStream)转换成证书(Certificate)对象。
秘钥工厂是双向的,密钥工厂用于将密钥(java.security.Key类型的不透明密钥)转换为密钥规范(以合适的格式对基础密钥材料进行透明表示),反之亦然。
比如KeyFactory类和SecretKeyFactory类:
图片.png
图片.png
Diffie-Hellman算法是一种密钥协议,是两方或多方可以建立相同密码密钥而不必交换任何秘密信息的协议。
图片.png
生成共享密钥有如下几步:
KeyAgreement.getInstance()
public void init(Key key);
public void init(Key key, SecureRandom random);
public void init(Key key, AlgorithmParameterSpec params);
public void init(Key key, AlgorithmParameterSpec params, SecureRandom random);
public Key doPhase(Key key, boolean lastPhase);
public byte[] generateSecret();
public int generateSecret(byte[] sharedSecret, int offset);
public SecretKey generateSecret(String algorithm);
“密钥库”是一种可用于管理密钥和证书的存储库,一个密码库包含多个私钥和证书。
KeyStore类
图片.png
密钥库中有两种不同类型的条目:Key Entry(密钥条目)和Trusted Certificate Entry(可信任的证书条目)
KeyStore对象可以从文件中load()或store()到文件。并提供了一系列方法来操作key条目和Certificate条目。
AlgorithmParameters:不透明的加密参数接口
AlgorithmParameterSpecs:透明的加密参数接口
AlgorithmParameters或AlgorithmParameterSpecs用于配置算法的初始化参数
AlgorithmParameterGenerator生成器,是一个引擎类,用于生成一组适用于特定算法的全新参数,提供了生成AlgorithmParameters和AlgorithmParameterSpecs的方法。
CertificateFactory类是定义证书工厂功能的引擎类,用于从其编码(文件流)生成证书和证书吊销列表(CRL)对象。
KeyManager和TrustManager作用:
SSL/TLS握手过程:
客户端首先发送一个ClientHello消息给服务器。 服务器选择要使用的密码组,然后将其发回到ServerHello消息中,并根据套件选择开始创建JCA对象。 我们将在下面的例子中使用服务器唯一身份验证。
图片.png
在第一个示例中,服务器尝试使用基于RSA的密码组,例如TLS_RSA_WITH_AES_128_CBC_SHA。 查询服务器的KeyManager,并返回相应的RSA条目。 服务器的凭证(即:证书/公钥)将在服务器的证书消息中发送。 客户端的TrustManager验证服务器的证书,如果接受,客户端使用SecureRandom对象生成一些随机字节。 然后使用已使用在服务器证书中找到的PublicKey初始化的加密非对称RSA密码对象对其进行加密。 此加密数据在客户端密钥交换消息中发送。 服务器将使用其相应的PrivateKey在解密模式下使用类似的密码恢复字节。 这些字节然后用于建立实际的加密密钥。
一旦建立了真实的加密密钥,秘密密钥就被用来初始化一个对称的密码对象,并且这个密码被用来保护所有传输中的数据。 为了帮助确定数据是否已被修改,创建MessageDigest并接收发往网络的数据的副本。 当数据包完成时,摘要(哈希)被附加到数据,并且整个数据包被密码加密。 如果使用诸如AES的分组密码,则必须填充数据以形成完整的块。 在另一端,这些步骤简单地颠倒过来。
作者:jection
链接:https://www.jianshu.com/p/a8194c237363
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章