Java密码体系结构简介:Java Cryptography Architecture (JCA) Reference Guide

来自Java官方的文档,作备忘使用。

简介:

Java平台非常强调安全性,包括语言安全,密码学,公钥基础设施,认证,安全通信和访问控制。

JCA是平台的一个主要部分,包含一个“提供者”体系结构和一组用于数字签名,消息摘要(哈希),证书和证书验证,加密(对称/非对称块/流密码),密钥生成管理和安全随机数生成等等。这些API允许开发人员将安全性轻松集成到应用程序代码中。这个架构是围绕以下原则设计的:

  实现独立性:应用程序不需要实现安全算法。相反,他们可以从Java平台请求安全服务。安全服务在提供者(见下文)中实现,通过标准接口插入Java平台。应用程序可能依靠多个独立的提供者来提供安全功能。

  实现互操作性:提供者可以跨应用程序进行互操作。具体而言,应用程序不绑定到特定的提供者,而提供者也不绑定到特定的应用程序。

  算法可扩展性:Java平台包括许多内置的提供者,这些提供者实现了当今广泛使用的一组基本的安全服务。但是,一些应用程序可能依赖尚未实施的新兴标准或专有服务。 Java平台支持安装实现这些服务的定制提供程序。

JDK中提供的其他密码通信库使用JCA提供程序体系结构,但在别处进行了介绍。 Java Secure Socket Extension (JSSE) Java安全套接字扩展(JSSE)提供对 Secure Socket Layer(SSL)和 Transport Layer Security(TLS)实现的访问。 Java通用安全服务(JGSS)(通过Kerberos)API以及简单身份验证和安全层(SASL)也可用于在通信应用程序之间安全地交换消息。

术语注释:

在JDK 1.4之前,JCE是一个非捆绑产品,因此,JCA和JCE被定期称为独立的,独特的组件。由于JCE现在捆绑在JDK中,所以区别变得不那么明显了。由于JCE使用与JCA相同的体系结构,所以JCE应该更适合作为JCA的一部分。

JDK中的JCA包含两个软件组件:

1. 定义和支持提供者为其提供实现的加密服务的框架。这个框架包含了诸如java.security,javax.crypto,javax.crypto.spec和javax.crypto.interfaces等软件包。

2.Sun,SunRsaSign,SunJCE等实际提供者都包含了具体的加密实现。

无论什么时候提及特定的JCA提供者,都可以找到与之对应的名称。


警告:JCA可以轻松地将安全功能集成到您的应用程序中。然而,除了基本介绍讨论API所需的概念之外,本文档不包括安全/密码学理论。本文档也没有涵盖特定算法的优缺点,也不涵盖协议设计。密码学是一个高级课题,为了最好地利用这些工具,应该参考一个可靠的,最近的参考文献。
 
你应该总是明白你在做什么,为什么,而不是简单地复制随机代码,并期望它完全解决你的使用场景。不然就会出现,由于选择了错误的工具或算法,而部署了许多包含重大安全或性能问题的应用程序。

 

设计原则:

JCA是围绕这些原则设计的:

1.实现独立性和互操作性

2.算法独立性和可扩展性

实现独立性和算法独立性是互补的;您可以使用加密服务(如数字签名和消息摘要),而无需担心实现细节,甚至是构成这些概念基础的算法。尽管完全的算法独立性是不可能的,但JCA提供了标准化的,算法特定的API。当实现独立性不可取时,JCA让开发人员指出具体的实现。

通过定义密码“引擎”(服务)的类型,并定义提供这些密码引擎的功能的类来实现算法独立性。这些类被称为引擎类,例如MessageDigest,Signature,KeyFactory,KeyPairGenerator和Cipher类。

实现独立性是使用基于“提供者”的体系结构实现的。术语密码服务提供商(CSP)(在本文档中与“提供商”可互换使用)是指实现一个或多个密码服务(如数字签名算法,消息摘要算法和密钥转换服务)的包或一组包。程序可以简单地请求实现特定服务(例如DSA签名算法)的特定类型的对象(例如签名对象),并从一个安装的提供者获得实现。如果需要的话,程序可以改为请求来自特定提供者的实现。提供商可能会更新透明的应用程序,例如,当更快或更安全的版本可用。

实现互操作性意味着各种实现可以相互协作,使用彼此的密钥,或者验证彼此的签名。这就意味着,例如,对于相同的算法,由一个提供者生成的密钥可以被另一个提供者使用,并且由一个提供者生成的签名可以被另一个提供者验证。

算法可扩展性意味着可以容易地添加适合于所支持的引擎类之一的新算法。

 

加密服务提供者:

java.security.Provider是所有安全提供程序的基类。每个CSP都包含这个类的一个实例,它包含了提供者的名字,并列出了它实现的所有安全服务/算法。当需要特定算法的实例时,JCA框架会咨询提供者的数据库,如果找到合适的匹配项,则创建该实例。

提供者包含一个包(或一组包),为广告的加密算法提供具体的实现。每个JDK安装都默认安装并配置了一个或多个提供程序。其他提供者可以静态或动态添加(参见提供者和安全类)。客户端可以配置其运行时环境来指定提供程序的首选顺序。首选顺序是在没有请求特定提供者时提供者搜索请求的服务的顺序。

要使用JCA,应用程序只需要请求特定类型的对象(如MessageDigest)和特定的算法或服务(如“SHA-256”算法),并从一个已安装的提供者获取实现。或者,程序可以请求来自特定提供者的对象。每个提供者都有一个名字来引用它。

md = MessageDigest.getInstance("SHA-256");
md = MessageDigest.getInstance("SHA-256", "ProviderC");

 下图说明了请求“SHA-256”消息摘要实现。这些图显示了实现各种消息摘要算法(“SHA-256”,“SHA-384”和“SHA-512”)的三个不同的提供者。提供者按照优先顺序从左至右排列(1-3)。在第一个例子中,一个应用程序请求一个SHA-256算法实现而不指定提供者名称。提供程序按优先顺序搜索,并返回提供该特定算法ProviderB的第一个提供程序的实现。在第二个图中,应用程序请求来自特定提供者ProviderC的SHA-256算法实现。这次ProviderC的实现被返回,即使具有更高优先级的提供者ProviderB也提供SHA-256实现。

JDK中的加密实现主要是出于历史原因通过几个不同的提供者(Sun,SunJSSE,SunJCE,SunRsaSign)分发的,但在较小的程度上由它们提供的功能和算法的类型来分发。其他Java运行时环境可能不一定包含这些Sun提供程序,因此除非知道特定的提供程序可用,否则应用程序不应请求提供程序特定的实现。

JCA提供了一组API,允许用户查询安装哪些提供程序以及支持哪些服务。

提供者如何实际执行:

如前所述,通过定义所有应用程序用于访问服务类型的通用高级应用程序编程接口(API)来实现算法独立性。实现独立性是通过使所有提供者实现符合定义良好的接口来实现的。引擎类的实例因此被具有相同方法签名的实现类“支持”。应用程序调用通过引擎类路由,并传递到底层的后台实现。该实现处理请求并返回正确的结果。

每个引擎类中的应用程序API方法通过实现相应Service Provider Interface(SPI)的类路由到提供程序的实现。也就是说,对于每个引擎类,都有一个相应的抽象SPI类,它定义了每个加密服务提供者算法必须实现的方法。每个SPI类的名称与相应的引擎类相同,接着是Spi。例如,签名引擎类提供对数字签名算法的功能的访问。实际的提供者实现是在SignatureSpi的子类中提供的。应用程序调用引擎类的API方法,在实际的实现中又调用SPI方法。

每个SPI类都是抽象的。为了为特定算法提供特定类型的服务,提供者必须继承相应的SPI类,并提供所有抽象方法的实现。

对于API中的每个引擎类,通过调用引擎类中的getInstance()工厂方法来请求和实例化实现实例。工厂方法是一个返回一个类的实例的静态方法。引擎类使用上述框架提供者选择机制来获取实际的后台实现(SPI),然后创建实际的引擎对象。引擎类的每个实例都封装(作为专用字段)相应SPI类的实例,称为SPI对象。 API对象的所有API方法都声明为final,并且它们的实现调用封装SPI对象的相应SPI方法。
 
为了使这个更清楚,请查看下面的代码和插图:
 
import javax.crypto.*;

Cipher c = Cipher.getInstance("AES");
c.init(ENCRYPT_MODE, key);

 

 

 

 
这里的应用程序需要一个“AES”javax.crypto.Cipher实例,并不关心使用哪个提供程序。应用程序调用Cipher引擎类的getInstance()工厂方法,然后请求JCA框架查找支持“AES”的第一个提供程序实例。该框架会咨询每个已安装的提供者,并获取提供者类的提供者实例。 (回想一下Provider类是可用算法的数据库。)框架搜索每个提供者,最后在CSP3中找到合适的条目。这个数据库入口指向扩展CipherSpi的实现类com.foo.AESCipher,因此适用于Cipher引擎类。创建一个com.foo.AESCipher的实例,并将其封装在一个新创建的javax.crypto.Cipher实例中,该实例返回给应用程序。当应用程序现在对Cipher实例执行init()操作时,Cipher引擎类将请求路由到com.foo.AESCipher类中相应的engineInit()支持方法。
 
 
密钥管理
 
 
“密钥库”数据库可用于管理密钥和证书的存储库。密钥库可用于需要用于身份验证,加密或签名的数据的应用程序。
 
 
应用程序可以通过java.security包中的KeyStore类的实现来访问密钥库。建议的密钥库类型(格式)是“pkcs12”,它基于RSA PKCS12个人信息交换语法标准。默认的密钥库类型是“jks”,这是一种专有格式。其他密钥库格式也是可用的,例如作为替代专有密钥库格式的“jceks”,以及基于RSA PKCS11标准的“pkcs11”,并且支持对硬件安全模块和智能卡等加密令牌的访问。
 
 
应用程序可以通过java.security包中的KeyStore类的实现来访问密钥库。 Sun Microsystems提供了一个默认的KeyStore实现。它使用名为“jks”的专有密钥库类型(格式)将密钥库作为文件实现。其他密钥库格式也是可用的,比如“jceks”,它是一种比“jks”更加强大的加密的专有密钥库格式,以及基于RSA PKCS12个人信息交换语法标准的“pkcs12”。
 
应用程序可以使用上述相同的提供程序机制,从不同的提供程序中选择不同的密钥库实现。
 
JCA概念
 
本节介绍主要的JCA API
 
引擎类和算法
 
引擎类为特定类型的密码服务提供接口,而不依赖于特定的密码算法或提供者。引擎要么提供:
 
  * 密码操作(加密,数字签名,消息摘要等),
  * 生成器或密码材料的转换器(密钥和算法参数),或
  * 对象(密钥库或证书)封装了密码数据,可以在更高的抽象层使用。
 
以下引擎类别可用:
 
  *SecureRandom:用于生成随机或伪随机数字。
  *MessageDigest:用于计算指定数据的消息摘要(散列)。
  *Signature:使用密钥初始化,这些签名用于签署数据并验证数字签名。
  *Cipher:用密钥初始化,用于加密/解密数据。存在各种类型的算法:对称批量加密(例如AES),非对称加密(例如RSA)和基于密码的加密(例如PBE)。
  *Message Authentication Codes (MAC):与MessageDigests一样,它们也会生成散列值,但是首先使用密钥初始化以保护消息的完整性。
  *KeyFactory:用于将Key类型的现有不透明密钥转换为密钥规范(底层密钥材料的透明表示),反之亦然。
  *SecretKeyFactory:用于将SecretKey类型的现有不透明加密密钥转换为密钥规范(底层密钥材料的透明表示),反之亦然。 SecretKeyFactorys是特殊的只能创建密钥(对称)的KeyFactorys。
  *KeyPairGenerator:用于生成一对适用于指定算法的公钥和私钥。
  *KeyGenerator:用于生成与指定算法一起使用的新密钥。
  *KeyAgreement:由两方或多方使用,商定和建立一个特定的密钥,用于特定的密码操作。
  *AlgorithmParameters:用于存储特定算法的参数,包括参数编码和解码。
  *AlgorithmParameterGenerator:用于生成适合于指定算法的一组AlgorithmParameters。
  *KeyStore:用于创建和管理密钥库。密钥库是密钥的数据库。密钥库中的私钥具有与其关联的证书链,用于验证相应的公钥。密钥库还包含来自可信实体的证书。
  *CertificateFactory:用于创建公钥证书和证书吊销列表(CRL)。
  *CertPathBuilder:用于构建证书链(也称为证书路径)。
  *CertPathValidator:用于验证证书链。
  *CertStore:用于从存储库中检索证书和CRL。
 
注意:生成器创建具有全新内容的对象,而工厂从现有元素(例如编码)创建对象。
 
核心类和接口
 
本节讨论JCA中提供的核心类和接口:
 
  *the Provider and Security classes,
   *the Key interfaces and classes,
   *the Algorithm Parameter Specification Interfaces and Classes and the Key Specification Interfaces and Classes, and miscellaneous support and convenience interfaces and classes.
 
本部分显示每个类和接口中主要方法的签名。其中一些类(MessageDigest,Signature,KeyPairGenerator,SecureRandom,KeyFactory和关键规范类)的示例在相应的示例部分中提供。
 
相关安全API软件包的完整参考文档可以在软件包摘要中找到
 
java.security
javax.crypto
java.security.cert
java.security.spec
javax.crypto.spec
java.security.interfaces
javax.crypto.interfaces

The Provider Class

术语“加密服务提供者”(在本文档中与“提供者”可互换使用)是指提供JDK安全API加密特征子集的具体实现的一个或一组包。 Provider类是这种包或一组包的接口。它具有访问提供程序名称,版本号和其他信息的方法。请注意,除了注册加密服务的实现之外,Provider类还可以用于注册可能被定义为JDK安全API或其扩展之一的其他安全服务的实现。

为了提供加密服务的实现,实体(例如开发组)编写实现代码并创建提供者类的子类。 Provider子类的构造函数设置各种属性的值; JDK安全API使用这些值来查找提供者实现的服务。换句话说,子类指定实现服务的类的名称。

 

 

不同的实现可能具有不同的特性。有些可能是基于软件的,有些可能是基于硬件的。有些可能是平台无关的,有些可能是平台特定的。一些供应商的源代码可能可用于审查和评估,而有些则可能不可用。 JCA让最终用户和开发者决定他们的需求。

在本节中,我们解释最终用户如何安装符合他们需求的加密实现,以及开发人员如何请求适合他们的实现。

详细参见:https://docs.oracle.com/javase/7/docs/technotes/guides/security/crypto/CryptoSpec.html

 

 
 
 
 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2017-12-11 18:00  狂奔的小狮子  阅读(2809)  评论(0编辑  收藏  举报