JAVA Security Provider 简介 (JAVA安全服务提供者)

JAVA安全包提供数字签名,消息摘要等加密引擎。 这些类的具体实现由Sun在SDK中提供,也可以选择获取这些引擎的第三方实现。 所有这些都可以通过安全服务提供程序基础结构实现(Security Provider)。 提供程序基础结构允许在运行时找到安全包中各种类的具体实现,而无需对代码进行任何更改。 这提供了一个可供所有程序使用的一致API,无论谁提供实际实现。

安全服务提供程序提取了两个概念:引擎和算法。“引擎”是一组操作的抽象概念,在Java中,这些操作称为引擎。算法则定义应如何执行特定操作。算法可以被认为是引擎的实现,可能存在算法的若干实现。举一个简单的例子,Java安全包知道消息摘要。消息摘要是引擎:它是程序员可以执行的操作。消息摘要的想法与可以如何计算任何特定消息摘要无关。所有消息摘要共享某些特征,将这些共同特征抽象为单个接口的类称为引擎。引擎通常是抽象的,并且始终独立于任何特定算法。
消息摘要可以由特定算法实现,例如MD5或SHA。算法通常作为具体类提供,它扩展抽象引擎类,完成类的定义。但是,可能有许多类提供特定的算法;可能拥有Java平台附带的SHA类,并且可能还从第三方获得了SHA类。这两个类应该提供相同的结果,但它们的内部实现可能会有很大的不同。

加密服务提供者(CSP)

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

Provider包含一个包(或一组包),为声明的加密算法提供具体的实现。 每个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实现。

图一 自动搜索Provider

图二 指定特定的Provider

JDK中的加密实现主要是出于历史原因通过几个不同的提供者(Sun,SunJSSE,SunJCE,SunRsaSign)分发的, 其他的Java运行时环境可能不一定包含这些Sun安全服务提供程序,因此除非知道特定的提供程序可用,否则应用程序不应请求提供程序特定的实现。

密钥管理

称为“KeyStore”的数据库可用于管理密钥和证书的存储库。 密钥库可用于需要用于身份验证,加密或签名的数据的应用程序。

应用程序可以通过java.security包中的KeyStore类的实现来访问密钥库。 建议的密钥库类型(格式)是“pkcs12”,它基于RSA PKCS12个人信息交换语法标准。 默认的密钥库类型是“jks”,这是一种专有格式。 其他密钥库格式也是可用的,例如作为替代专有密钥库格式的“jceks”,以及基于RSA PKCS11标准的“pkcs11”,并且支持对硬件安全模块和智能卡等加密令牌的访问。应用程序可以使用上述相同的提供程序机制,从不同的提供程序中选择不同的密钥库实现。

JCA中的Engine类和算法

Engine引擎类为特定类型的密码服务提供接口,而不依赖于特定的密码算法和提供者。 引擎类主要应用于:

密码操作(加密,数字签名,消息摘要等)
生成器(Key Generator)或密码的转换器(密钥和算法参数)
对象(密钥库或证书)封装了密码数据

引擎类包含:

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中的核心类和接口

? Provider和Security类
? SecureRandom,MessageDigest,Signature,Cipher,Mac,KeyFactory,SecretKeyFactory,KeyPairGenerator,KeyGenerator,KeyAgreement,AlgorithmParameters,AlgorithmParameterGenerator,KeyStore和CertificateFactory等引擎类
? Key 接口和类
? Algorithm Parameter Specification接口和类以及Key Specification接口和类,以及
? 其他的支持和工具类。

注:有关CertPathBuilder,CertPathValidator和CertStore引擎类的更多信息,请参阅“Java PKI编程指南”。

简单地说,密钥(公钥,私钥和加密)由各种JCA类生成和表示,并被其他的高级类用作其操作的一部分。

相关安全API软件包的完整参考文档可以在软件包摘要中找到:

java.security
javax.crypto
java.security.cert
java.security.spec
javax.crypto.spec
java.security.interfaces
javax.crypto.interfaces

Provider类

加密安全服务提供者是指提供JDK安全API加密特征的具体实现的一个或一组包。 Provider类是这种包或一组包的接口。 它具有访问安全服务提供程序名称,版本号和其他信息的方法。 为了提供安全服务Provider的实现,用户编写实现代码并创建Provider类的子类。 Provider子类的构造函数设置各种属性的值;

不同的实现可能具有不同的特性。 有些可能是基于软件的,有些可能是基于硬件的。 有些可能是平台无关的,有些可能是平台特定的。

Provider的请求和服务如何实现

对于API中的每个引擎类,通过调用引擎类的getInstance方法之一来请求和实例化实现实例,指定想要实现的所需算法的名称以及可选的提供者(或提供者类)的名称。

static EngineClassName getInstance(String algorithm) throws NoSuchAlgorithmException

static EngineClassName getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException

static EngineClassName getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException

其中EngineClassName是所需的引擎类型(MessageDigest / Cipher / etc)。 例如:

MessageDigest md = MessageDigest.getInstance(“SHA-256”);
KeyAgreement ka = KeyAgreement.getInstance(“DH”, “SunJCE”);

分别返回“SHA-256”MessageDigest和“DH”KeyAgreement对象的实例。

附录A包含已经标准化的用于Java环境的名称列表。 有些提供商可能会选择也包含也指向相同算法的别名。 例如,“SHA256”算法可能被称为“SHA-256”。 应用程序应该使用标准名称而不是别名,因为不是所有的提供者都可以用同样的方法来命名算法名称。

注意:算法名称不区分大小写。 例如,以下所有调用都是等同的:

MessageDigest.getInstance(“SHA256”)
MessageDigest.getInstance(“sha256”)
MessageDigest.getInstance(“sHa256”)

如果没有指定提供程序,getInstance将搜索已注册的提供程序,以获得与指定算法关联的请求的加密服务的实现。 在任何给定的Java虚拟机(JVM)中,提供程序都是以给定的优先顺序安装的,如果没有请求特定的提供程序,搜索提供程序列表的顺序就会被搜索到。 例如,假设在JVM,PROVIDER_1和PROVIDER_2中安装了两个提供程序。 假设:

PROVIDER_1实现SHA-256和DESede。
PROVIDER_1拥有优先顺序1(最高优先级)。
PROVIDER_2使用DSA,SHA-256,RC5和RSA实现SHA256。
PROVIDER_2具有优先顺序2。
现在让我们看看三种情况:

如果我们正在寻找一个SHA-256实现,那么这两个提供者都提供这样的实现。 由于PROVIDER_1具有最高优先级并且首先被搜索,所以PROVIDER_1实现被返回。
如果我们正在寻找SHA256withDSA签名算法,则首先搜索PROVIDER_1。 没有找到实现,因此搜索了PROVIDER_2。 由于实现被发现,它被返回。
假设我们正在寻找一个SHA256withRSA签名算法。 由于没有安装的提供者实现它,抛出了NoSuchAlgorithmException。

JDK自带的Providers及其引擎类和算法参考列表

安装Providers

为了使用Provider,必须首先安装加密服务提供程序,然后静态或动态注册。 Sun发行版提供了多种Sun提供程序(SUN,SunJCE,SunJSSE,SunRsaSign等),已经安装并注册。

安装Provider类

有两种可能的方法来安装Provider类:

? 在普通的Java classpath中
在classpath的任何位置放置一个包含Provider类的zip或JAR文件。 一些算法类型(Cipher)要求提供者是一个签名的Jar文件。
? 作为已安装/捆绑的扩展
如果将提供程序置于标准扩展目录中,则该提供程序将被视为已安装的扩展程序。 在JDK中,这将位于:

1.Solaris, Linux, or Mac OS X: JAVA_HOME/lib/ext
2.Windows:JAVA_HOME\lib\ext

JAVA_HOME是指安装运行时软件的目录,它是Java运行时环境(JRE)的顶层目录或Java JDK软件中的jre目录。 例如,如果在Solaris上将JDK 6安装在名为/home/user1/JDK1.6.0的目录中或在Microsoft Windows上的名为C:\ Java \ JDK1.6.0的目录中,则需要将JAR文件安装到 以下目录:

Solaris, Linux, or Mac OS X: /home/user1/JDK1.6.0/jre/lib/ext
Windows: C:\JDK1.6.0\jre\lib\ext

静态注册

配置文件位于以下位置:

Solaris, Linux, or Mac OS X: JAVA_HOME/lib/security/java.security
Windows: JAVA_HOME\lib\security\java.security
对于每个注册的提供者,这个文件应该有以下形式的表单:

security.provider.n=masterClassName

这声明了一个提供者,并且指定了它的首选顺序n。 首选顺序是提供者搜索请求的算法的顺序(当没有请求特定的提供者时)。 顺序以1为基础:1是最优先的,然后是2,依此类推。

masterClassName必须指定提供者的主类的完全限定名称。 提供者的文档将指定它的主类。 这个类总是Provider类的一个子类。 子类构造函数设置Java加密API所需的各种属性的值,以查找提供者实现的算法或其他工具。

JDK标配自动安装和配置的提供程序,如“SUN”和“SunJCE”。 “SUN”提供者的主类是sun.security.provider包中的SUN类,相应的java.security文件条目如下:

security.provider.5=sun.security.provider.Sun

要利用另一个JCA提供者,请添加一条引用备用提供者的行,指定首选顺序(如果需要,对其他提供者的订单进行相应的调整)。

假设CompanyX的提供者的主类是com.companyx.provider.ProviderX,并且你想把这个提供者配置成第八个最优先的。 为此,您可以将以下行添加到java.security文件中:

security.provider.8=com.companyx.provider.ProviderX
动态注册

要动态注册提供者,应用程序调用Security类中的addProvider或insertProviderAt方法。 这种类型的注册在VM实例中不是永久性的,只能通过具有适当权限的“可信任”程序完成。

设置Provider权限

当使用加密提供者(即提供Cipher,KeyAgreement,KeyGenerator,Mac或SecretKeyFactory的实现的提供者),并且提供者不是已安装的扩展时可能需要授予使用JCA的applet或应用程序时的权限 。 默认的系统策略配置文件授予安装的扩展的所有权限(即安装在扩展目录中),因此不需要授予安装的扩展的权限。

将要使用的每个提供商的供应商的文档应该包括所需的权限以及如何授予这些权限的信息。 例如,如果提供程序不是已安装的扩展程序并安装了安全管理器,则可能需要以下权限:

java.lang.RuntimePermission“getProtectionDomain”获取类保护域。
java.security.SecurityPermission“putProviderProperty.{name}”设置提供程序属性,其中{name}由实际提供程序名称替换。
例如,下面给出了一个样例语句,该语句授予名称为“MyJCE”且代码位于myjce_provider.jar中的提供程序的权限。 在这个例子中,假设myjce_provider.jar文件位于/ localWork目录中。

grant codeBase "file:/localWork/myjce_provider.jar" {
    permission java.lang.RuntimePermission "getProtectionDomain";
    permission java.security.SecurityPermission
        "putProviderProperty.MyJCE";
 };

Provider类方法

每个Provider类实例都有一个(当前区分大小写的)名称,一个版本号以及提供者及其服务的字符串描述。 您可以通过调用以下方法来查询提供程序实例以获取此信息:

public String getName()
public double getVersion()
public String getInfo()

Security类

Security类管理已安装的提供程序和安全性属性。 只包含静态方法,不会被实例化。 用于添加或删除提供者以及设置安全属性的方法只能由受信任的程序执行。 受信任的程序是指:

不在安全管理器下运行的本地应用程序
具有执行指定方法权限的应用程序

如果确定代码被信任以执行尝试的操作(例如添加提供者),则要求该应用程序被授予适当的特定操作权限。 JDK安装的策略配置文件指定来自指定代码源的代码允许哪些权限(哪些类型的系统资源访问)被允许。 请参阅下面的“默认策略实施和策略文件语法”和“https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-spec.doc.html”文件来了解权限设置。

正在执行的代码总是被认为来自特定的代码源。 代码源不仅包括源代码的位置(URL),还包括对可能用于签名代码的私钥对应的任何公钥的引用。 代码源中的公钥由用户密钥库中的别名引用。

在策略配置文件中,代码源由两个组件表示:代码库(URL)和别名(以signedBy开头),其中别名名称标识包含必须用于验证的公钥的密钥库条目 代码的签名。

以下是一个示例策略配置文件:

grant codeBase “file:/home/sysadmin/”, signedBy “sysadmin” {
permission java.security.SecurityPermission “insertProvider.“; permission java.security.SecurityPermission “removeProvider.“;
permission java.security.SecurityPermission “putProviderProperty.*”;
};

此配置文件指定从本地文件系统上/ home / sysadmin /目录下的已签名JAR文件加载的代码可以添加或删除提供程序或设置提供程序属性。 (请注意,可以使用用户密钥库中的别名sysadmin引用的公钥来验证JAR文件的签名。)

代码源(或两者)的组件可能会省略。 下面是一个代码库被省略的配置文件的例子:

grant signedBy “sysadmin” {
permission java.security.SecurityPermission “insertProvider.“; permission java.security.SecurityPermission “removeProvider.“;
};

如果此策略有效,那么由sysadmin签名的JAR文件中的代码可以添加/删除提供程序,而不管JAR文件的来源在哪里。

下面是没有签名者的例子:

grant codeBase “file:/home/sysadmin/” {
permission java.security.SecurityPermission “insertProvider.“; permission java.security.SecurityPermission “removeProvider.“;
};
在这种情况下,来自本地文件系统/ home / sysadmin /目录中任何地方的代码都可以添加/删除提供程序。 代码不需要签名。

不包括codeBase和signedBy的例子是:

grant { permission java.security.SecurityPermission “insertProvider.“; permission java.security.SecurityPermission “removeProvider.“; };

在这里,在缺少两个代码源组件的情况下,任何代码(无论它来自何处,是否签名,谁签名)都可以添加/删除提供程序。

管理Providers

下表总结了Security类中的方法,您可以使用它来查询安装了哪些提供程序,以及在运行时安装或删除提供程序。

查询Provider

增加Provider

删除Provider

JAVA Security Provider 简介 (JAVA安全服务提供者)

发表评论

邮箱地址不会被公开。 必填项已用*标注

二十 一 − = 14

滚动到顶部