`
m635674608
  • 浏览: 4923822 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

jce 中的Provider

    博客分类:
  • java
 
阅读更多

谁应阅读本文件

相关文档

术语的注意事项

发动机类和相应的SPI类

步骤来实施并集成一个供应商

示例代码的注意事项

寻找供应商JAR文件:基础知识

确定供应商的JAR文件的URL

创建一个jar文件的JAR文件

验证提供者的JAR文件:基础知识

验证设置

JAR文件签名检查

验证签名

确保签名者的信任

获得的证书列表

确定每一个签名者,并确定如果一个人被信任

myJCE 示例代码的注意事项

进一步的实施细则和要求

别名

服务的相互依赖性

默认初始化

默认密钥对生成参数要求

的 Provider.Service

签名格式

DSA接口和其所需的实现

RSA接口和其所需的实现

的Diffie-Hellman接口和其所需的实现

其他算法类型的接口

算法参数规范接口和类

重点规格主要工厂所需的接口和类

秘密密钥生成

确保出口能力

附录A:Sun 提供商大师班的

附录B:了SunJCE 提供商大师班

附录C: 的java.security属性文件


介绍

Java平台定义了一组API,跨越主要安全领域,包括密码,公钥基础设施,认证,安全通信和访问控制。这些API使开发人员能够轻松地集成到他们的应用程序代码的安全性。他们的目的是围绕下列原则:

  1. 实施独立的

    应用程序不需要自己来实现安全。相反,他们可以要求从Java平台的安全服务。安全服务提供商(见下文),这是通过一个标准接口连接到Java平台实现。应用程序可能依赖于多个独立的供应商的安全功能。
  2. 实现的互操作性

    提供跨应用程序进行互操作。具体来说,应用程序没有绑定到一个特定的供应商,和提供者未绑定到一个特定的应用程序。
  3. 算法的可扩展

    Java平台包括了一些内置的供应商,实施了一套基本的安全服务,被广泛使用的今天。然而,一些应用程序可能依赖于新兴标准尚未实施,或专有服务。Java平台支持安装自定义实现这样的服务提供商。

à 加密服务供应商(供应商)是指一个包(或一组)包JDK安全API的一个子集的加密方面,提供一个具体的实施。

java.security.Provider类封装了一个安全的概念,在Java平台提供商。指定供应商的名称,并列出了安全服务,它实现。多个供应商可能会在同一时间进行配置,并列出优先顺序。当安全性服务被请求时,优先级最高的实现该服务的提供者已被选中。

图1和图2说明了这些选项,一个MD5信息摘要执行请求。这两个数字表明3个供应商,实现消息摘要算法。提供者排列优先由左到右(1-3)。在图1中,应用程序请求的MD5算法实现不指定提供者名称。优先顺序和实现从第一供应商,供应特定算法,ProviderB,则返回的搜索提供商。在图2中,应用程序请求从一个特定的供应商,ProviderC MD5算法的实现。这一次返回从该供应商的实施,,即使提供商,拥有更高的优先顺序,ProviderB还提供一个MD5的实现。

<Image of the General JCA Architecture>

图1:提供搜索图2:特定的供应商要求

图1和图2说明了这些选项,一个MD5信息摘要执行请求。这两个数字表明3个供应商,实现消息摘要算法。提供者排列优先由左到右(1-3)。在图1中,应用程序请求的MD5算法实现不指定提供者名称。优先顺序和实现从第一供应商,供应特定算法,ProviderB,则返回的搜索提供商。在图2中,应用程序请求从一个特定的供应商,ProviderC MD5算法的实现。这一次返回从该供应商的实施,,即使提供商,拥有更高的优先顺序,ProviderB还提供一个MD5的实现。

每个安装有一个或多个提供包安装。客户可以配置的运行时间与不同的供应商,并为他们每个人指定的优先顺序优先顺序是搜索提供商的顺序没有特别的要求提供所请求的算法。

Sun版本的Java运行时环境标配一个默认的供应商,名为“SUN”。其他的Java运行时环境不一定提供“SUN”提供。

谁应阅读本文件

只需要使用Java安全API来访问现有的加密算法和其他服务的程序员 需要阅读本文件。

本文档的目的是为有经验的程序员,希望创建自己的提供程序包提供加密服务的实现。它记录了你需要做什么让你的算法和其他服务,为了您的供应商整合到Java Java安全API的客户端请求时,可以发现他们。

相关文档

本文档假定您已经阅读了Java加密体系结构参考指南

它记录了包安全API中包含的各种类和接口。

术语的注意事项

  • 在JDK 1.4之前,JCE是一个捆绑式的产品,正因为如此,JCA和JCE经常提到作为单独的,不同的组件。JCE现在捆绑在JDK的区别正在变得越来越明显。由于共同控制实体使用相同的架构的JCA,JCE应更恰当地想到了对JCA的一个子集。
  • JCA内JDK包括两个软件组件:
    • 框架,定义并支持加密服务提供商提供实现。该框架包括软件包,比如 java.security中javax.crypto的, javax.crypto.spec,和 方法javax.crypto.interfaces的
    • 实际提供 了SunJCE太阳SunRsaSign其中包含实际的加密实现。

JCA本身的条款,是指在本文档中,JCA框架。每当这个文件注意到一个特定的JCA提供者,它会明确地提到由提 ​​供者的名称。

发动机类和相应的服务提供者接口类

引擎类定义一个抽象的方式(没有具体的实施)的加密服务。

一个加密服务总是与一个特定的算法或类型。它可以提供加密操作(如数字签名或消息摘要,密码或密钥协商协议);生成或提供加密操作所需的加密材料(钥匙或参数);或生成数据对象(密钥库或证书)封装加密键(它可以用来在一个加密操作)以安全的方式。

例如,这里有四个引擎类:

  • 签名类提供访问数字签名算法的功能。
  • 一个DSA KeyFactory方法类的initSign或initVerify时方法中使用的格式提供DSA私钥或公钥(从它的编码或透明规范),分别的DSA签名对象。
  • 密码类提供了访问功能的加密算法(如DES)
  • KeyAgreement类提供了访问一个密钥协商协议的功能(如的Diffie-Hellman)

Java加密体系结构包括类,包括安全包,涉及到加密,包括引擎类。用户的API请求,并利用引擎类的实例来进行相应的操作。JDK中定义了以下引擎类:

  • 报文摘 -用于计算指定数据的消息摘要(哈希)。
  • 签名 -用于数据签名和验证数字签名。
  • KeyPairGenerator的 -用来生成一对公钥和私钥,适合指定的算法。
  • KeyFactory方法 -用不透明加密密钥类型重点转换密钥规范 (底层密钥材料的透明表示),反之亦然。
  • 密钥库 -用于创建和管理 密钥库密钥仓库是密钥数据库。keystore中的私有密钥与它们相关联的证书链,对应的公钥进行验证。密钥库也包含来自可信任实体的证书。
  • CertificateFactory -用于创建公钥证书和证书撤销列表(CRL)。
  • 的AlgorithmParameters -用于管理特定算法的参数,包括参数的编码和解码。
  • AlgorithmParameterGenerator -用于生成一组的参数,适合于指定的算法。
  • 的SecureRandom -用于产生随机或伪随机数。
  • </ <B> 密码用于一些特定的数据进行加密或解密。
  • KeyAgreement </ <B>:用于执行的一个关键协议(密钥交换)协议2或更多方之间。
  • KeyGenerator的 </ <B>:用于生成适合指定算法的秘密(对称)键。
  • MAC </ <B>:用于计算 消息认证码的一些指定的数据。
  • SecretKeyFactory </ <B>:用于转换的SecretKey类型的不透明加密密钥, 密钥规范(底层密钥材料的透明表示),反之亦然。
  • ExemptionMechanism </ <B>:用于提供诸如一键恢复关键减弱密钥托管,或任何其他的(自定义)的豁免机制的豁免机制的功能可能授出更强的加密能力比那些不使用豁免机制的应用程序或applet。但是,请注意,加密限制,不再需要对大多数国家,从而豁免机制,只可用于在那几个国家的政府授权的限制。

注:发电机创建对象的全新的内容,而一个工厂创建对象从现有的材料(例如,编码)。


发动机类提供一种特定类型的加密服务(独立于特定的加密算法)的功能的接口。它定义了 应用程序编程接口(API),允许应用程序访问特定类型的加密服务,它提供了方法。实际的实现(从一个或多个提供者)的特定算法。例如,签名引擎类提供访问数字签名算法的功能。SignatureSpi中的子类(见下段)提供的实际实现将是一种特定的签名算法,如SHA1与RSA,DSA,SHA1或MD5与RSA。

引擎类所提供的应用程序接口来实现一个服务提供程序接口(SPI) 也就是说,每个引擎类,有一个相应的抽象SPI类,它定义了服务提供者接口方法,加密服务提供商必须实现。

引擎类,“API对象”,封装(作为一个私有字段)的一个实例相应的SPI类,“SPI对象”,一个实例。所有的API方法API对象被宣布为“最后的”,并实现封装的SPI对象调用相应的SPI方法。引擎类的一个实例(以及其相应的SPI类)调用引擎类的getInstance工厂方法创建

每个SPI类的名称,相应的引擎类,然后由“SPI”是相同的。例如,签名引擎类对应的SPI类SignatureSpi中类。

每个SPI类是抽象的。要提供执行特定类型的服务,并为特定的算法,提供者必须相应的SPI类的子类,并提供所有抽象方法的实现。

引擎类的另一个例子是MessageDigest类,它提供了访问一个消息摘要算法。在MessageDigestSpi子类,它的实现,可能是各种消息摘要算法,如SHA-1,MD5或MD2。

KeyFactory引擎类作为最后一个例子,支持不透明密钥转换到透明的关键指标,反之亦然。有关详细信息,由主要工厂所需的密钥规范接口和类在KeyFactorySpi子类提供的实际实现将是一种特定类型的键,例如,DSA公钥和私钥。

步骤来实施并集成一个供应商

按照下面的步骤来实现供应商和集成到JCA框架:

第1步:写你的服务实现代码

你需要做的第一件事就是写代码,你要支持的加密服务提供算法的具体实现。

需要注意的是你的供应商可能会提供加密服务的实现,已经可以在一个或多个安全组件的JDK。

对于没有定义的加密服务JCA(例如,签名和消息摘要),请参阅Java加密体系结构参考指南

对于每一个你想实现的加密服务,建立适当的SPI类的一个子类。JCA定义以下发动机类:

  • SignatureSpi中
  • MessageDigestSpi
  • KeyPairGeneratorSpi
  • SecureRandomSpi
  • AlgorithmParameterGeneratorSpi
  • AlgorithmParametersSpi
  • KeyFactorySpi
  • CertificateFactorySpi
  • KeyStoreSpi
  • CipherSpi
  • KeyAgreementSpi
  • KeyGeneratorSpi
  • MacSpi
  • SecretKeyFactorySpi
  • ExemptionMechanismSpi

(请参阅本文档中的发动机类和相应的SPI类 JCA和其他加密类的信息。)

在你的子类,你需要:

  1. 为抽象方法提供实现,他们的名字通常与发动机开始进一步的实施细则和要求,了解更多信息。
  2. 确保有一个公共的构造函数不带任何参数。这里的原因:当您的服务请求,Java安全性抬头的子类实现该服务的属性所指定的“大师班”(见第3步)。然后创建Java安全与你的子类的对象,并创建一个子类的实例的newInstance方法调用对象上 的newInstance需要你的子类有一个公共的构造函数不带任何参数。
  3. 不带参数的默认构造函数将自动生成,如果你的子类没有任何构造函数。但是,如果你的子类定义任何构造函数,你必须明确地定义一个公共的构造函数没有参数。

步骤1a:其他JCA提供加密实现的要求和建议

当实例提供者的实现(类)的 密码,KeyAgreement,KeyGenerator的MAC或 SecretKey的工厂,该框架将确定供应商的代码库(JAR文件),并验证其签名。以这种方式,JCA提供者进行认证,并确保唯一提供者签署的受信任的实体可以被插入到JCA。因此,加密提供者的一个要求是,它们必须签名,在后面的步骤中所描述的。

此外,每个供应商应进行自我完整性检查,以确保其代码的JAR文件,包含没有被操纵,企图调用提供的方法,而不是直接通过JCA。如需进一步信息,请参阅如何提供商可以做自我完整性检查

为了提供类变得无法使用,如果由一个应用程序,绕过JCA直接实例化,供应商应实现如下:

  • 宣布最终的提供者包中的所有SPI实现类应(,使他们不能派生子类),保护(SPI)的实施方法应该声明 
  • 所有加密相关的辅助类的提供者包中应该有私人包范围,使他们不能从外部提供者包访问。

对于可能出口到美国以外的供应商, CipherSpi实现必须包括实施engineGetKeySize方法,给定一个,返回键的大小。如果有限制可用的加密强度指定管辖的政策文件,每个CIPHER初始化方法调用engineGetKeySize的的 applet或应用程序正在运行的特定地点和情况允许的最大密钥大小比较的结果。如果该键的尺寸过大,初始化方法抛出一个异常。

其他可选功能,供应商可以实现

  • engineWrapengineUnwrap 方法的CipherSpi包装的关键,从一个地方到另一个地方,能够安全传输的关键。包装和拆包键 部分Java加密体系结构参考指南,提供有关包装和展开键
  • 一个或更多的豁免机制豁免机制是一些诸如一键恢复,密钥托管,或键减弱,如果执行和实施,可以使加密限制,减少使用它的应用程序(或applet)。的应用程序,利用豁免机制的要求的详细信息,请参阅如何使应用程序加密限制Java加密体系结构参考指南“豁免”

第2步:给你提供一个名称

确定你的供应商的名称。这是由客户端应用程序的名称,用于指您的供应商。

第3步:写你的大师班,提供的一个子类

第三个步骤是创建一个子类的 java.security.Provider类。

子类应该是一个最终的类,它的构造

  • 调用,指定提供者的名称(见 第2步),版本号,和一串串信息的提供者和算法支持。例如:
        超(“CryptoX”,1.0“,1.0 CryptoX提供商,实施”+
            “RSA加密和密钥对生成和DES加密。”);
    
  • 设置Java安全API查找加密服务提供商实施所需要的各种属性的值。对于每个服务提供商实施,必须有一个属性,其名称的服务类型(例如,签名,消息摘要,密码,KeyAgreement) 签名,消息摘要,KeyPairGenerator的,SecureRandom的KeyFactory方法,密钥库,CertificateFactory AlgorithmParameterGenerator的AlgorithmParameters 密码,KeyAgreement,KeyGenerator的MAC,SecretKeyFactory,或ExemptionMechanism) 接着一个句点和服务所适用的算法的名称。实现服务的类的属性值必须指定完全合格的名称。
  • 下面的列表显示了各种类型的JCA服务,被取代的algName的实际算法名称

    • algName签名。
    • MessageDigest的algName
    • KeyPairGenerator的algName
    • SecureRandom的algName中
    • AlgorithmParameterGenerator algName
    • algName的AlgorithmParameters。
    • KeyFactory方法algName中
    • CertificateFactory algName中
    • 的KeyStore algName号
    • 密码algName
    • KeyAgreement algName
    • KeyGenerator的algName
    • 的Mac。algName中
    • SecretKeyFactory algName
    • ExemptionMechanism algName

    在所有这些,除了ExemptionMechanism和 密码algName。certType 的storetype的算法,证书类型,或keystore类型是“标准”的名字。附录A的标准名称应使用Java加密体系结构参考指南“。)

    在的情况下ExemptionMechanismalgName 指的豁免机制,它可以是下列之一:KeyRecoveryKeyEscrow或 KeyWeakening的名称案例并没有关系。

    加密的情况下algName实际上可能表示一个变换,可以由一个算法的名称,一个特定的模式,和填充方案。Java加密体系结构参考指南详细请参见 附录A

    每个属性值必须是完全合格的类名实现指定算法,证书类型,或keystore类型。也就是说,它必须是包名,类名,其中两个是分开的一段。

    作为一个例子,默认的供应商,名叫实现数字签名算法(其标准名称是 SHA1的DSADSA在 sun.security.provider一类名为它的子类 供应商(这是的太阳类在 sun.security.provider包)设置 Signature.SHA1withDSA的属性,通过以下的价值 sun.security.provider.DSA

        把(“Signature.SHA1withDSA”,“sun.security.provider.DSA)
    

    下面的列表显示了更多的属性,可以被定义为各种类型的服务,实际算法取代的名称,凭证类型 的storetype certType, keystore类型和属性名使用attrname algName

    • Signature.algName [一个或多个空格] 使用attrname
    • MessageDigest.algName [一个或多个空格] 使用attrname
    • KeyPairGenerator.algName [一个或多个空格] 使用attrname
    • SecureRandom.algName [一个或多个空格] 使用attrname
    • KeyFactory.algName [一个或多个空格] 使用attrname
    • CertificateFactory.certType [一个或多个空格] 使用attrname
    • KeyStore.storeType 一个或多个空格] 使用attrname
    • AlgorithmParameterGenerator.algName [一个或多个空格]使用attrname
    • AlgorithmParameters.algName [一个或多个空格] 使用attrname
    • Cipher.algName [一个或多个空格] 使用attrname
    • KeyAgreement.algName [一个或多个空格] 使用attrname
    • KeyGenerator.algName [一个或多个空格] 使用attrname
    • Mac.algName [一个或多个空格] 使用attrname
    • SecretKeyFactory.algName [一个或多个空格] 使用attrname
    • ExemptionMechanism.algName [一个或多个空格] 使用attrname

中每个这些,algName,certType的storetype或 使用attrname的是“标准”的算法的名称,证书类型,keystore类型或属性。(见附录A中的标准名称应使用Java加密体系结构参考指南。)

对于上述格式的属性,属性的值必须是相应的属性的值。(见附录A Java加密体系结构API规范与参考为每个标准属性的定义。)

作为一个例子,名为“SUN”实现SHA1的DSA数字签名算法在软件默认的提供 在“大师班”SUN“提供者,它设置 Signature.SHA1withDSA的ImplementedIn值 软件通过以下方式:

    把(“Signature.SHA1withDSA ImplementedIn”,“软件”)

为进一步掌握类属性设置示例,请参阅附录A来查看当前Sun.java的源文件或附录B看到 了SunJCE提供商。这些文件显示太阳了SunJCE提供商如何设置属性。

步骤3.1:密码实现的附加步骤

如前所述,在密码 属性的情况下algName实际上可能代表了 转型 转型是一个字符串,描述在某些给定的输入密码对象进行的操作(或一组操作) 转换始终包括加密算法(如DES的名称 ,并可以跟随模式和填充方案。

一个转换的形式:

  • 算法/模式/填充,或
  • 算法

(在后一种情况下,使用的模式和填充方案提供特定的默认值)。例如,以下是有效的变换:

    密码C = Cipher.getInstance(“DES/CBC/PKCS5Padding); 

当请求一个块密码,在流密码的模式(例如,CFBOFB 模式的DES),客户端可以有选择地指定要被处理的比特数,在同一时间,通过追加此号码的模式名称显示在下面的样品转换:

    加密c1的= Cipher.getInstance(“DES/CFB8/NoPadding);
    加密c2的= Cipher.getInstance(“DES/OFB32/PKCS5Padding);

如果号码不遵循流加密模式,提供特定的默认。(例如,了SunJCE 提供商使用一个默认为64位)。

服务提供商可提供一个单独的类算法/模式/填充每个组合 另外,提供者可以决定提供更通用的类相对应的算法算法/模式或 算法/ /填充(注意双斜线)表示子转换,在这种情况下,自动设置所需的模式和/或填充 的getInstance 密码的方法,,调用engineSetMode和 供应商的子类CipherSpi engineSetPadding方法 

也就是说,在一个供应商主类可能有一个密码属性在下表中显示的格式之一。

 物业格式描述
密码algName 提供商的子类CipherSpi 实现algName的可插拔的模式和填充
密码。algName /模式 提供商的子类CipherSpi 实现algName的在指定的模式,采用可插拔填充
密码的algName / /填充 提供商的子类CipherSpi 实现algName的指定填充,采用可插拔模式
密码algName /模式/填充 提供商的子类CipherSpi 实现algName的指定模式填充

(见附录A标准算法名称,模式和填充方案应该使用Java加密体系结构参考指南。)

例如,一个供应商可能会提供一个子类 CipherSpi 实现DES/ECB/PKCS5Padding,1实现DES/CBC/PKCS5Padding,1实现DES/CFB/PKCS5Padding,还有一个则实现DES/OFB/PKCS5Padding的该提供商将其主类中的属性有以下密码

  • 密码DES/ECB/PKCS5Padding
  • 密码DES/CBC/PKCS5Padding
  • 密码DES/CFB/PKCS5Padding
  • 密码DES/OFB/PKCS5Padding

另一个供应商可以实现一类的每个上述模式(即,一类为ECBCBC, CFB,和一个用于OFB),一类 PKCS5Padding,和一个通用的DES类的子类从CipherSpi该提供商将其主类中的属性有以下 密码

  • DES密码。
  • DES密码。SupportedModes 例:“欧洲央行CBC CFB OFB”
  • 密码。DES SupportedPaddings 示例:“NOPADDING | PKCS5Padding”

加密引擎类的getInstance工厂方法 遵守这些规则,为了一个提供商的实施CipherSpi的实例 的形式为“ 算法 “ 的转变

  1. 检查提供程序是否已注册的一个子类 CipherSpi指定的“ 算法 “, 如果答案是肯定的,实例化这个类, 如果答案是否定的模式和填充方案的预设值(如提供者提供的)。,抛出一个NoSuchAlgorithmException 异常。



加密引擎类的getInstance工厂方法 遵守这些规则,为了一个提供商的实施CipherSpi的实例 的形式为“ 算法/模式/填充 “ 的转变

  1. 检查提供程序是否已注册为指定的“ 算法/模式/填充 “转型的一个子类 CipherSpi 如果答案是肯定的,它实例化。 如果答案是否定的,去下一个步骤。



  2. 检查提供程序是否已注册的一个子类 CipherSpi子“ 算法/模式 “ 转型 如果答案是肯定的,实例化,并在新实例上调用 engineSetPadding(填充 如果答案是否定的,去下一个步骤。



  3. 检查提供程序是否已注册的一个子类 CipherSpi子转换“ 算法/ /填充 “(注意双斜线)。 如果答案是肯定的,实例化,并在新实例上调用的 模式 engineSetMode  答案是否定的,进入到下一个步骤。



  4. 检查提供程序是否已注册的一个子类 CipherSpi子转换“ 算法 “。 如果答案是肯定的,它实例化,并在新实例上调用 engineSetMode(模式和 engineSetPadding(填充 如果答案是NO,抛出一个NoSuchAlgorithmException 例外。



第4步:编译你的代码

在你创建你的实现代码(步骤1),给你提供一个名称(步骤2),并创建主类(步骤3),使用Java编译器编译的文件。

第5步:将您的提供商在JAR文件

将提供程序代码的JAR文件中,在准备签署在下一步。对于罐子 工具的更多信息,请参阅适用于Solaris)(适用于Microsoft Windows)。

    罐子CVF <jar文件名> <列表classes,由spaces>分离

此命令创建一个具有指定名称包含指定类的JAR文件。

步骤6:可选 - 注册您的JAR文件

如果您的供应商提供的加密算法通过的 密码KeyAgreement的,KeyGenerator的,MAC,SecretKeyFactory类,你需要签署的JAR文件,以便,JCA的代码在运行时可以验证的。有关详细信息,请参见步骤1a如果你提供这种类型的实施,你可以跳过这一步。

第6.1步:获取代码签名证书

下一步是要求代码签名证书,这样就可以用它来签署您的供应商在测试之前。该证书将是很好的测试和生产。这将是有效期为5年。

下面是步骤,你应该使用代码签名证书。keytool的工具的更多信息,请参阅 密钥工具用于Solaris)(适用于Microsoft Windows)。

  1. 使用keytool将生成一个DSA密钥对,使用DSA算法作为一个例子:
        keytool的genkeypair的,别名<别名> \
            keyalg DSA密钥长度1024 \
            DNAME“CN = <公司名称> \
            OU = Java软件代码签名,\
            O = Sun公司“\
            密钥库<keystore的文件名> \
            -  storepass的长度<keystore的口令
            
    

    这将产生一个DSA密钥对(公共密钥和相关的私钥),并将其存储在指定的密钥库中的条目。公共密钥存储在一个自签名的证书。keystore条目随后可以使用指定的别名访问。

    尖括号(“<”和“>”)中的选项值表示必须提供的实际值。例如, <别名>必须更换与希望被用来指在未来新生成的密钥库条目, 必须替换为要使用的密钥存储区的名称文件名​​> <keystore任何别名。 注意:不要用尖括号包围实际值。例如,如果你想别名myTestAlias ​​,指定别 ​​名选项如下:

        别名myTestAlias​​的
    
    如果你指定一个keystore尚不存在,它将被创建。


    注:如果您键入的命令行不允许keytool的genkeypair要执行的命令(例如,如果您正在键入到Microsoft Windows DOS提示符)只要,你可以创建并执行一个纯文本批量文件中包含的命令。也就是说,新建一个文本文件,其中包含但完整的keytool的genkeypair的的 命令而已(记住键入它在一行上。)的。bat扩展名保存该文件。然后在DOS窗口中,键入文件名 ​​(其路径,如有必要)。这将导致在批处理文件中的命令被执行。


  2. 使用密钥工具生成证书签名请求。
        密钥工具的certReq别名<别名> \
            文件<csr的文件名> \
            密钥库<keystore的文件名> \
            -  storepass的长度<keystore的口令 
    
    在这里,<别名>是DSA密钥对在前面的步骤中创建的条目的别名。此命令生成一个证书签名请求(CSR),使用的PKCS#10格式。它存储指定在<csr文件名​​>的文件,其名称中的CSR 
  3. JCA代码签名证书颁发机构发送CSR,联系信息,以及其他必要的文件。 JCA代码签名认证机构的联系信息。
  4. JCA的代码签名证书颁发机构已收到您的电子邮件后,他们将通过电子邮件发送给您请求数。一旦您收到此请求的数量,你应该打印,填写并发送对CSP认证表格。请参阅 CSP的联系信息发送认证表
  5. 使用密钥工具导入从CA收到证书。 一旦你已经收到了从JCA代码签名证书颁发机构的证书,您可以使用密钥工具将它们导入到您的密钥 导入CA的证书作为“受信任的证书”: 



        keytool的进口的别名<alias CA cert>的\
            <CA证书文件文件名> \
            密钥库<keystore的文件名> \
            -  storepass的长度<keystore的口令
    
    然后导入的代码签名证书:
        密钥工具导入别名<别名> \
            文件<code-signing证书文件名> \
            密钥库<keystore的文件名> \
            -  storepass的长度<keystore的口令
    
    在这里,<别名>是,您在步骤1中生成DSA密钥对创建相同的别名。该命令取代了自签名证书,在指定的keystore项与JCA代码签名证书颁发机构签署的<别名>

现在,您在您的密钥的证书受信任的通过JCA(JCA代码签名证书颁发机构)从实体,您可以将您的供应商代码,在一个JAR文件(步骤5),然后使用该证书签名JAR文件(步骤6.2)。

步骤6.2:登录您的提供商

注册创建的JAR文件步骤五步骤6中获得的代码签名证书jarsigner工具的更多信息,请参阅jarsigner (适用于Solaris)(适用于Microsoft Windows)。

    jarsigner-密钥库<keystore的的文件名> \
        -  storepass的长度<keystore的口令\
        <jar文件名> <别名>

在这里,<别名>是别名到密钥库中的条目都包含收到JCA的代码签名认证机构(第6.1步中的命令指定相同的别名)的代码签名证书

您可以通过以下测试验证签名:

    的jarsigner验证<jar文件名> 

文本“罐验证,如果验证成功,将显示。

第7步:准备测试

接下来的步骤描述了如何安装和配置您的新的供应商,因此,它是可以通过JCA。

步骤7.1:安装提供商

为了准备测试你的供应商,你必须安装它以同样的方式,将通过希望使用它的客户。安装启用Java安全客户端请求时,他们找到你的算法实现。

安装一个供应商是在两个步骤:安装提供者包类和配置提供。

安装Provider类

你必须做的第一件事是让你的班,使他们能够请求时被发现。运送您的提供商类为一个JAR(Java归档)文件。

有两种可能的方式来安装提供类:

  • 安装JAR文件包含提供安装捆绑的扩展类 
  • 将JAR文件包含在你的CLASSPATH提供商类。

提供商JAR文件将被视为已安装扩展,如果它被放置在已安装扩展的JAR文件的标准位置:

    <java-home> / lib / ext目录的Solaris]
    <java-home> \ LIB \分机[视窗]

这里<java-home>指运行系统软件安装所在的目录,这是顶层目录的Java TM 2运行时环境(JRE)或JRE目录中的Java TM SE(JDK)软件。例如,如果你有安装了JDK 6 Solaris上的目录中的名为/ home/user1/jdk1.6.0,或在Microsoft Windows中一个名为C:\ jdk1.6.0目录,那么你需要把JAR文件安装在以下目录:

    / home/user1/jdk1.6.0/jre/lib/ext的Solaris]
    C:\ jdk1.6.0 \ JRE \ LIB \ EXT [视窗]

同样,如果您有安装JRE 6 Solaris上在一个名为/ home/user1/jre1.6.0的目录,或在Microsoft Windows目录中的名为C:\的jre1.6.0,你需要安装JAR文件在以下目录:

    / home/user1/jre1.6.0/lib/ext的Solaris]
    C:\ \ LIB \分机的jre1.6.0 [视窗]

安装扩展的更多信息,请参阅 安装的扩展

捆绑扩展的更多信息,请参阅捆绑扩展

配置提供

下一步是将提供程序添加到您的列表已批准提供。这是静态安全属性文件编辑

    <java-home> /的lib / security / java.security中的Solaris]
    <java-home> \ LIB \安全\ java.security中[视窗]

这里<java-home>指JRE的安装目录。例如,如果你有安装了JDK 6 Solaris上的一个目录名为/ home/user1/jdk1.6.0,或微软INDOWS的一个名为C:\ jdk1.6.0目录,那么你需要编辑以下文件:

    / home/user1/jdk1.6.0/jre/lib/security/java.security [的Solaris]
    C:\ jdk1.6.0 \ jre的\ LIB \安全\ java.security中[视窗]

同样,如果您有JRE 6 Solaris上安装一个名为/ home/user1/jre1.6.0,或在Windows目录中的名为C:\的jre1.6.0目录,那么你需要编辑这个文件:

    / home/user1/jre1.6.0/lib/security/java.security [的Solaris]
    C:\ \ LIB \安全\ java.security中的jre1.6.0 [视窗]

对于每一个供应商,这个文件应该有以下形式的声明:

    security.provider Ñ = masterClassName 

这宣告了一个供应商,并指定其优先级 Ñ优先顺序是搜索提供商的顺序请求的算法时,没有特定的提供要求。的命令是基于1的,图1是最优选的,其次是2,等等。

masterClassName必须指定供应商的“大师班”,您在步骤3中实现完全合格的名称这个类是始终Provider类的子类。

Java标配的与供应商名为SUNSunRsaSign 了SunJCE被自动配置为静态提供商 的java.security属性文件,内容如下:

    security.provider.2 = sun.security.provider.Sun
    security.provider.3 = sun.security.rsa.SunRsaSign
    security.provider.4 = sun.security.provider.SunJCE

提供商的主类是的太阳类在 sun.security.provider包。)

JCA提供了SunJCE Java平台所附带的其他安全相关的供应商也将自动配置为静态提供商。

要利用其他JCA提供商,添加一行注册的替代供应商,给它比的阳光和SunRsaSign商一个较低的优先顺序。

假设你的主人类是CryptoX的类在com.cryptox.provider包,您想使您的供应商的第四优选供应商。要做到这一点,编辑java.security文件中,如下所示:

    security.provider.2 = sun.security.provider.Sun
    security.provider.3 = sun.security.rsa.SunRsaSign
    security.provider.4 = com.cryptox.provider.CryptoX
    security.provider.5 = sun.security.provider.SunJCE

注:供应商也可以动态注册。要做到这一点,可以调用一个程序(如您的测试程序,写在第8步)的addProvider 或insertProviderAt的安全中的方法 这种类型的注册是不是持久的,只能通过代码被授予以下权限:

    java.security.SecurityPermission“insertProvider {名}”

{名字}与实际提供的名称取代。

例如,如果提供者的名称是“MyJCE”,如果供应商的代码是在/ localWork目录myjce_provider.jar的文件,然后在这里是一个示例策略文件授予该权限授予声明:

    授予代码库“的文件:/ localWork的/ myjce_provider.jar”{
        权限java.security.SecurityPermission的
            “insertProvider.MyJCE”;
    };

步骤7.2:设置供应商的权限

每当供应商没有安装的扩展,必须授予权限时,applet或应用程序运行,而安装一个安全管理器。通常是一个安全管理器,安装一个applet运行时,可以安装一个安全管理器的应用程序可以通过在应用程序本身的代码,或通过命令行参数。不需要被授予权限安装的扩展,因为默认的系统策略文件授予的所有权限安装的扩展。

每当一个客户端不安装作为安装的扩展您的供应商,供应商可能需要在客户环境中已授予以下权限:

  • 需要java.lang.RuntimePermission类保护域。供应商可能需要做自我完整性检查的过程中获得自己的保护域。
  • 提供者属性设置java.security.SecurityPermission

要确保工程安全管理器安装时您的供应商和提供者是不安装扩展,你需要测试这样的安装和执行环境。此外,在测试之前,你需要你的供应商和任何其他供应商,它使用授予适当的权限。例如,授予权限的提供者,其名称是的“MyJCE”,其代码是在myjce_provider.jar出现下面的示例语句 这样的声明可能会出现的政策文件中。在这个例子中,假定的 myjce_provider.jar文件只有 / localWork目录。

    授予代码库“的文件:/ localWork的/ myjce_provider.jar”{
        许可需要java.lang.RuntimePermission的“getProtectionDomain”;
        权限java.security.SecurityPermission的
            “putProviderProperty.MyJCE”;
    };

第8步:您的测试程序编写和编译

编写和编译一个或多个测试程序,测试您的供应商纳入安全API以及其算法的正确性(次)。创建任何支持所需的文件,如测试数据进行加密。

你的程序应执行的第一次测试以确保您的供应商被发现的,其名称,版本号,其他信息如预期。要做到这一点,你可以写类似下面的代码,您的提供程序名称MyPro的代 

    进口的java.security。

    提供者p值= Security.getProvider(“MyPro);

    (“MyPro提供者的名字是”+ p.getName());
    (“MyPro提供商版本#”+ p.getVersion());
    (MyPro供应商信息是“+ p.getInfo());

接下来,你应该确保你的服务被发现。举例来说,如果你实现了DES加密算法,你可以通过使用下面的代码(为“MyPro”再次以您的供应商名称)检查,以确保它的发现请求时:

    密码C = Cipher.getInstance(“DES”,的“MyPro”);

    (“我的加密算法的名称是”+ c.getAlgorithm());

的getInstance调用,如果你不指定提供者名称 ,所有已注册的供应商将被搜索,优先顺序(请参阅配置提供),直到找到实现该算法。

如果您的供应商实现的豁免机制,你应该写一个测试applet或应用程序使用的豁免机制。这样的applet /应用程序也需要签名,并且需要有与它捆绑“许可政策文件”。 如何使应用程序从Java加密体系结构参考指南创建和测试应用程序的完整信息加密限制的“豁免”

第9步:运行测试程序

运行测试程序(次)。调试你的代码,并继续测试需要。如果Java安全API似乎无法找到你的算法之一,复查上面的步骤,并确保他们全部建成。

一定要包括测试您的程序使用不同的安装选项(例如提供商安装扩展或在类路径)和执行环境(带或不带安全管理器运行)。步骤7.1安装选项进行了讨论特别是,你需要确保你的供应商时,一个安全管理器的安装和提供者是不安装扩展-因此,供应商必须具备授予它的权限,因此,你需要测试这样的安装和执行环境,授予必要的权限后,你的供应商和任何其他供应商,它使用步骤7.2中所描述的 

在测试过程中,如果您发现您的代码需要修改,进行更改,重新编译(步骤4),将更新提供程序代码在一个JAR文件(步骤6),如果有必要签署的JAR文件(步骤6.2),重新安装提供商(步骤7.1),如果需要修复或添加的权限(第7.2步),然后重新测试您的程序。根据需要重复这些步骤。

第10步:如需要申请美国政府的出口批准

提供商可能会被出口到美国以外的所有美国厂商应适用于向美国商务部工业与安全局批准出口。请参考导出律师更多信息。

注:如果您的供应商要求 Cipher.getInstance()返回的 加密对象需要进行强大的加密,不管允许用户的下载权限策略文件加密强度,你应该包括你打算cryptoPerms权限策略文件的副本捆绑在JAR文件中为您提供所需的加密强度指定适当的权限。这个文件的必要性,就像是applet和应用程序加密限制的“豁免”的规定,即必须包括cryptoPerms权限的政策文件中的JAR文件。对于这样一个文件的创建和列入的更多信息,请参阅如何使应用程序加密限制Java加密体系结构参考指南“豁免”

这里有两个,可能是有用的URL:

第11步:记录您的供应商和其支持的服务

下一步是为您的客户写文档。至少,你需要指定:

  • 名称方案应使用指您的供应商。 注:截至写这篇文章,提供者名称搜索是 区分大小写的也就是说,如果你的主类指定您的供应商名称为“CryptoX”,但用户请求“CRYPTOx”的,你的供应商将不会被发现。此行为可能会在未来发生改变,但现在使用指定确切的情况下,你一定要提醒你的客户。
  • 您的提供商所实现的算法和其他服务类型的。
  • 指示安装提供商,步骤7.1所提供的类似,除了您的供应商特定的信息和例子应该。
  • 权限您的供应商要求,如果它没有安装作为安装的扩展,如果安全管理器运行时,所描述的步骤7.2

此外,您的文件应指定其他任何默认的算法参数,如客户的兴趣。

消息摘要和MAC

对于每一个消息摘要和MAC算法,表明不论你的实现是可复制的。这技术上是没有必要的,但它可能会告诉他们中间消息精华与否或MAC是可能通过克隆客户节省一些时间和编码。谁也不知道与否Mac的实现是可复制的客户端 可以找到,尝试克隆对象和捕捉潜在的异常,如下面的例子所示:

    尝试{
        / /尝试克隆
        / *计算MAC的i1 * /
        mac.update(I1);
        byte []的doFinal i1Mac = mac.clone()();

        / *计算MAC I1和I2 * /
        mac.update(i2的);
        byte []的doFinal i12Mac = mac.clone()();

        / *计算MAC I1,I2和I3 * /
        mac.update(I3);
        byte []的i123Mac = mac.doFinal();
    }赶上(CloneNotSupportedException异常CNSE){
        / /使用方法,不涉及克隆
    } 

其中:

  • MAC MAC对象时,他们收到了他们要求通过调用Mac.getInstance的
  • 期1i2的i3的输入字节数组,并
  • 他们要分别计算哈希:
    • I1
    • I1和I2
    • I1,I2,和i3

密钥对生成

密钥对生成算法,客户端的情况下并没有明确初始化密钥对生成器(通过调用 初始化方法),每个供应商必须提供文件的默认初始化。例如,Diffie-Hellman密钥对生成了SunJCE供应商所提供的使用默认的1024位的质数模大小(密钥长度)。

主要工厂

提供者应当记录(秘密)密钥工厂支持所有的主要规格。

算法参数发电机

情况下,客户端没有显式初始化算法参数生成器(通过引擎AlgorithmParameterGenerator类的init方法调用),每个供应商必须提供文件的默认初始化。了SunJCE提供者,例如,使用一个默认的质数模数的大小生成的Diffie-Hellman参数,,太阳提供者的默认模DSA参数生成1024位的素数的大小为1024位的密钥大小

签名算法

如果实现签名算法,你应该记录编码格式,其中的签名(所产生的标志方法之一 )。例如,“SUN”提供者所提供的SHA1withDSA签名算法的签名进行编码,作为一个标准的ASN.1 SEQUENCE两个整数,RS

SecureRandom的随机数生成()算法

对于一个随机数生成算法,提供信息产生的数字是“随机”,当随机数发生器种子的质量是自注入。还要注意的SecureRandom对象(以及它的的封装SecureRandomSpi实现对象)进行反序列化时会发生什么情况:如果恢复对象的nextBytes方法(调用engineNextBytes方法封装SecureRandomSpi对象)的后续调用产生完全相同(随机)字节作为原来的对象,然后让用户知道,如果这种行为是不可取的,他们应该恢复的随机对象的种子,通过调用过setSeed 方法。

证书工厂

提供者应当记录什么类型的证书(及其版本号,如果相关),可以由工厂创建。

密钥库

提供者应当记录任何有关资料,仓库实现,如它的底层数据格式。

第12步:使你的类文件和文档提供给用户端

写作后,你的供应商软件的配置,测试,安装和记录,使文档提供给你的客户。

供应商可以如何做自我完整性检查

每个供应商应该做的自我完整性检查,以确保其代码的JAR文件,包含不被篡改,例如试图调用提供的方法,而不是直接通过JCA。提供商提供加密服务的实现(密码,KeyAgreement,KeyGenerator的MACSecretKey的工厂),必须进行数字签名,并应署名“可信”证书颁发机构颁发的证书。目前,以下两个认证机构被认为是“可信”:

  • Sun Microsystems的JCA代码签名CA,
  • IBM JCA代码签名CA。

如何获得来自Sun Microsystems的JCA代码签名CA的代码签名证书,该CA证书的详细信息,请参阅步骤6.2

获得以上认证机构的签名证书后,提供者包内嵌入自己是字 ​​节,对于自己的签名证书,例如在一个数组像bytesOfProviderCert的数组中提到的 识别每一个签名者,并确定如果一个人被信任的一节。在运行时,嵌入式的证书将被用来确定或不提供程序代码是否是正宗的。

一个供应商可以用它来检查其完整性的基本方法是:

  1. 确定提供程序代码的JAR文件,其中包含的URL,
  2. 验证JAR文件的数字签名,以确保至少一个签名者的JAR文件的每个条目的信任。

这些步骤中的每一步都在下面的章节描述:

示例代码的注意事项

寻找供应商JAR文件:基础知识

确定供应商的JAR文件的URL

创建一个jar文件的JAR文件

验证提供者的JAR文件:基础知识

验证设置

JAR文件签名检查

验证签名

确保签名者的信任

获得的证书列表

确定每一个签名者,并确定如果一个人被信任

myJCE 示例代码的注意事项




示例代码的注意事项

注:该的示例代码MyJCE.java是完整的代码示例实现这些步骤。您可以下载这段代码,供大家参考。示例代码部分注意事项的痕迹,如何实现这些概念的示例代码中。


重要注意事项:在非捆绑JCE 1.2.x版本,用的JDK 1.2.x和1.3.x的版本,提供需要包括的代码进行验证,以确保自己对JCA的完整性和真实性,他们插上JCA框架成。在JDK 6中,这不再是必要的。

一个含义是,只是写一个供应商JCE 1.2.2将无法正常工作在JDK 6中,因为供应商的的JCE框架验证检查不会工作; JCE框架代码不再提供者希望它是。如果你希望你的供应商只能使用JDK 6,它不应该有代码来验证JCE框架。另一方面,如果你希望你的供应商与JCE 1.2.2和JDK 6,然后加入条件语句。通过这种方式,供应商代码来验证JCE框架执行,只有当供应商与JCE 1.2.2运行。下面是示例代码:

    cipherCls类的Class.forName(的“javax.crypto.Cipher”);

    CodeSource的CS getCodeSource = cipherCls.getProtectionDomain()();
    (CS = NULL){
        / /验证JCE框架

    } 

寻找供应商JAR文件:基础知识

确定供应商的JAR文件的URL

提供商的JAR文件的URL,可以通过确定供应商的CodeSource的CodeSource的方法 是第一步,然后调用

    的URL providerURL =(URL)AccessController.doPrivileged(
        新PrivilegedAction的){
            公共对象的run(){
                CodeSource的CS =
                    MyJCE.class.getProtectionDomain()。getCodeSource();
                返回cs.getLocation的();
            }
        }); 

创建一个jar文件的JAR文件

一旦你有了提供商的JAR文件的URL,您可以创建一个java.util.jar.JarFile指的JAR文件。需要此实例中的验证步骤,用于提供程序的JAR文件

要创建JAR文件,首先打开一个连接到指定的URL调用openConnection方法。由于URL是一个JAR URL,类型是 java.net.JarURLConnection的这里是基本的代码:

    / /准备网址与相应的协议。
    jarURL =
        url.getProtocol(),equalsIgnoreCase。(“罐子”)?网址:
            新的URL(“罐:”+ url.toString()+“/”);

    / /检索使用的jar文件的JarURLConnection
    jar文件JF =(jar文件)AccessController.doPrivileged的的(
        的新PrivilegedExceptionAction(){
            公共对象的run()抛出异常{
                的的JarURLConnection Conn =
                    jarURL.openConnection(的JarURLConnection)();
        ...  

现在,你有一个的JarURLConnection的,你可以调用其getJarFile方法得到的JAR文件:

    / /总是得到一个新的副本,所以我们不必
    / /时,不用担心过时的文件句柄
    / /缓存的jar其他一些应用程序被关闭。
    conn.setUseCaches(假);
    JF = conn.getJarFile(); 

验证提供者的JAR文件:基础知识

一旦你已经确定为您提供的JAR文件的URL,您已经创建了一个jar文件所示,在上述步骤中提到的JAR文件,然后你可以验证文件。

基本做法是:

  1. 确保至少有一个等于每个条目的签名者的证书提供商自己的代码签名证书。
  2. JAR文件中的所有条目,并确保每一个上的签名验证正确。
  3. 确保至少有一个可以追溯到每个条目的签名者的证书到受信任的证书颁发机构。

每个步骤的示例代码,并在下面的章节描述:

验证设置

JAR文件签名检查

验证签名

确保签名者的信任

获得的证书列表

确定每一个签名者,并确定如果一个人被信任

 

验证设置

我们的做法是定义一个类JarVerifier的 JAR文件从一个给定的URL处理检索和验证的JAR文件是否与指定的证书签署。

的构造JarVerifier提供者URL作为一个参数将被用于检索的JAR文件后。

实际的jar验证实施的 验证方法,这需要作为参数提供程序代码签名证书。

    公共无效验证(x509证书targetCert)抛出IOException异常{
        / /变量jar文件'是一个jar文件创建的对象
        / /从提供者的JAR URL。
        ...
        矢量entriesVec =新的Vector(); 

基本上验证方法将通过JAR文件条目两次:第一次检查每个条目上,第二次验证签名者的签名是可信的。

注:在我们的代码片段jar文件的 变量是jar文件的对象提供商的jar文件。

JAR文件签名检查

一个真实的供应商签署的JAR文件。所以JAR文件已被篡改,如果它不签署:

    / /确保的jar文件签署。
    清单男人= jarFile.getManifest();
    (男人== NULL){
        抛出新的SecurityException(“提供商签署了”);
    } 

验证签名

下一步是要经过JAR文件中的所有条目,并确保每一个签名验证正确。验证签名的JAR文件条目的一个可行的办法是简单地读取文件。如果一个JAR文件签署, 法本身自动进行签名验证。下面是示例代码:

    / /正确确保所有条目的签名验证
    byte []的缓冲区=新的字节[8192];
    枚举项= jarFile.entries();

    而(entries.hasMoreElements()){
        的的JarEntry JE = entries.nextElement(的JarEntry)();

        / /跳过目录。
        如果(je.isDirectory())
            继续执行;

        entriesVec.addElement(JE);
        的InputStream是:= jarFile.getInputStream(JE);

        / /读取在每个罐子条目。安全异常
        / /抛出,如果一个签名/文摘检查的失败。
        INT N;
        而(组(n =头is.read(缓冲液,0,buffer.length))= -1){
            / /不要在乎
        }
        掉} is.close();
    }
    

确保签名者的信任

在上一节的代码验证签名的所有提供的JAR文件条目。正确验证的事实,他们是必需的,但是不足够的JAR文件的真实性进行验证。最后一个要求是为开发提供一个相同的实体所产生的签名。为测试签名是值得信赖的,我们可以再次通过每个条目在JAR文件中(这时候使用内置在先前步骤中的entriesVec),并为每个条目必须签署的(即,每一个项目的是不是一个目录,这是不是在META-INF目录):

  1. 获得签名者证书列表中的条目。
  2. 识别每一个证书链,并确定是否有任何受信任的证书链。证书链中的至少一个必须是可信的。

回路设置为执行以下操作:

    枚举E = entriesVec.elements();
    而(e.hasMoreElements()){
        的的JarEntry JE = e.nextElement(的JarEntry)();
        ...
    } 

获得的证书列表

JAR文件条目的JarEntry签名者的证书 可以得到简单的通过调用“ 的JarEntry getCertificates方法:

    证书[证书= je.getCertificates();

添加这行代码前面的循环设置代码,将代码添加到忽略的目录和文件的META-INF目录中,为我们提供了:

    而(e.hasMoreElements()){
        的的JarEntry JE = e.nextElement(的JarEntry)();

        / /每个文件必须签署META-INF中的文件除外。
        证书[证书= je.getCertificates();
        ((证书== NULL)| |(certs.length == 0)){
            (!je.getName()。的startsWith(“META-INF”))
                抛出新的SecurityException(
                    “提供有签名的类文件。”);
            } {
                / /检查文件是否签署预期
                / /签署者。罐子可能是由多个签名者签署。
                / /如果签名者之一是'targetCert'。
                ...
            }
        ...  

确定每一个签名者,并确定如果一个人被信任

证书由“ 的JarEntry getCertificates方法返回的数组包含一个或多个 证书链每个签名者的入门有一个链。每一个链包含一个或多个证书。链中的每个证书认证前一个证书中的公钥。

在一个链的第一个证书是签名者的证书,其中包含的公钥对应的私钥签署项目实际使用。每个后续的证书是指发行人以前的证书。由于自我完整性检查是根据签署的JAR文件是否与提供者的签名证书,信托作出决定后的第一个证书,签名者的证书。

我们需要去通过一系列的证书链,并检查各链和相关的签名者,直到我们找到一个 值得信赖的实体。对于每个JAR文件条目,签名者中的至少一个必须是可信的。被认为是“值得信赖的”,当且仅当其证书等于嵌入的提供签名证书签名者。

下面的示例代码遍历所有的证书链,嵌入的提供签名证书链中的第一个证书比较,并只返回真,如果找到一个匹配。

    从startIndex = 0;
    X509证书[J] certChain。
    布尔signedAsExpected = FALSE;

    而((certChain = getAChain(证书,从startIndex))的!= NULL){
        (certChain [0]。的等于(targetCert)){
            / /停止,因为找到一个信任的签名者。
            signedAsExpected = TRUE;
            打破;
        }

        / /继续到下一个链。
        从startIndex + = certChain.length的;
    }

    如果(signedAsExpected){
        抛出新的SecurityException(
            “提供不信任的签名者”)签署;
    }
    

getAChain方法的定义如下:

    / **
     *从指定的证书数组中提取一个证书链
     *可能包含多个证书链,从指数
     *'从startIndex'。
     * /
    私有静态x509证书:[] getAChain(
            证书[证书,INT从startIndex){

        如果(从startIndex> certs.length  -  1)
            返回null;

        INT I;
        / /一直走,直到下一个证书是不
        / /此证书的发行人。
        (I = startIndex开始; <certs.length  - 我+ +){
            (((X509证书)证书[I + 1])。getSubjectDN()。
                    等于(((X509证书)证书[])())。getIssuerDN){
                打破;
            }
        }

        / /构造并返回找到的证书链。
        certChainSize =(I-startIndex开始)+ 1;
        X509证书[] RET =新的X509证书[certChainSize];
        (J = 0; <certChainSize; J + +){
            沤[J] =(X509证书)证书[从startIndex + J];
        }
        RET;
    }
    

票据上的代码示例myJCE

示例代码,MyJCE.java,是一个样本提供者,其中有一个方法selfIntegrityChecking 进行自我完整性检查。它首先要确定自己的供应商JAR文件的URL,然后验证提供者的JAR文件的签名与嵌入的代码签名证书。

注:该方法selfIntegrityChecking 应该叫其加密引擎类的构造函数,以确保其完整性不受损害。

提供MyJCE执行完整性检查以下步骤:

  1. 确定URL访问提供商的JAR文件,使用其自己的类,MyJCE.class
  2. 实例化一个JarVerifier的提供商在步骤1中的URL对象。
  3. 创建对象的嵌入式字节数组bytesOfProviderCert的一个x509证书
  4. 调用方法来验证JarVerifier.verify提供商JAR文件中的所有条目都签署并签署了相同的证书在步骤3中实例化。

注:将检索JarVerifier的 JAR文件从给定的URL,确保签署的JAR文件,所有参赛作品的有效签名,指定的X509证书签署的条目

在一些情况下,一个安全异常被抛出 JarVerifier.verify

  • 通过验证的证书是无效(无效)。
  • 当无法从给定的URL检索JAR文件。
  • 提供者未签名。(罐子里有没有显现出来。)
  • 提供有签名的类文件。
  • 不签署提供者指定的证书。

MyJCE.java示例代码是由上面显示的代码片段。此外,它包含错误处理,示例代码签名证书字节,实例化一个X509Certificate的对象从嵌入式示例代码签名证书的字节代码

关于使用AccessController.doPrivilegeddoPrivileged的使用特权块的信息, 请参阅API

进一步的实施细则和要求

别名

对于很多加密算法和类型,有一个官方的“标准名称”的定义在附录A Java加密体系结构参考指南

例如,“MD5”RSA-MD5消息摘要算法RSA DSI RFC 1321中定义的标准名称。 DiffieHellman是标准的Diffie-Hellman密钥协议定义PKCS3算法。

在JDK中,有一个别名方案,使客户能够使用别名时,指的算法或类型,而不是其标准名称。例如,“SUN”提供者的主类(Sun.java)的别名定义算法的标准名称为“SHA1withDSA”的“SHA1/DSA”。因此,下面的语句是等价的:

    签名SIG = Signature.getInstance(“带DSA的SHA1”,“SUN”);

    签名SIG = Signature.getInstance(的“SHA1/DSA”,“SUN”);

别名可以定义在你的“大师班”(见第3步)。要定义别名,创建一个名为

    Alg.Alias ​​engineClassName.aliasName

其中engineClassName引擎类的名称(例如,签名),aliasname的是你的别名。该物业价值必须是标准算法名称(或类型)的算法(或类型)的别名。

作为一个例子,“SUN”提供者定义的别名通过下面的签名算法的标准名称为“SHA1withDSA”通过设置 有名为Alg.Alias.Signature.SHA1/DSA物业价值SHA1的DSA的 “SHA1/DSA” 

    把(“Alg.Alias​​.Signature.SHA1/DSA”,“带DSA的SHA1”);

需要注意的是,定义的别名由一个供应商只提供给该供应商,而不是任何其他供应商。因此,别名了SunJCE提供者定义只提供给 了SunJCE提供商。

服务的相互依赖性

一些算法需要使用的其他类型的算法。例如,一个PBE算法通常需要使用消息摘要算法,以改造进入一个关键的密码。

如果要实现算法,需要另一种类型的,你可以做下列操作之一:

  1. 都提供自己的实现。
  2. 让您实现一个算法使用其他类型的算法的一个实例, 包含在每一个Java SE平台安装的默认太阳的供应商,所提供的例如,如果你正在实施一个PBE算法,需要一个消息摘要算法,可以得到实施的MD5信息摘要算法通过调用一个类的实例
        MessageDigest.getInstance(“MD5”,“太阳报”)
    
  3. 让您实现一个算法使用其他类型的算法的一个实例,另一个特定的供应商所提供的。这仅仅是适当的,如果你是确保所有的客户端将使用运营商也将有安装其他供应商。
  4. 让您实现一个算法使用,另一个(不详)提供商所提供的其他类型的算法的一个实例。也就是说,你可以要求一个算法的名字,但没有指定任何特定的供应商,如
        MessageDigest.getInstance(“MD5”)
    
    这仅仅是适当的,如果你一定会有至少一个执行请求的算法(MD5),在这种情况下,您的供应商将被用于每个Java平台上安装。

下面是一些常见类型的算法的相互依存关系:

签名和消息摘要算法

签名算法往往需要使用一个消息摘要算法。例如,带DSA的SHA1签名算法需要SHA-1的消息摘要算法。

签名和伪随机数生成算法

A签名算法往往需要使用的(伪)随机数生成算法。例如,这样的算法是必需的,以便产生一个DSA签名。

密钥对的生成和消息摘要算法

一个密钥对生成算法往往需要使用一个消息摘要算法。例如,使用SHA-1的消息摘要算法生成DSA密钥。

算法参数生成消息摘要算法

算法参数生成器往往需要使用报文摘要算法。例如,使用SHA-1的消息摘要算法生成DSA参数。

密钥库和消息摘要算法

密钥库的实现往往会利用消息摘要算法来计算键控哈希(其中关键是用户提供的密码)的一个keystore完整性检查,并确保该keystore尚未被篡改。

密钥对生成算法和算法参数发电机

有时需要一个密钥对的生成算法,生成一组新的算法参数。它可以直接生成的参数,或使用一个算法参数生成器。

密钥对生成,算法参数生成,(伪)随机数生成算法

一个密钥对生成算法可能需要随机源,以生成一个新的密钥对,并可能与键相关联的一组新的参数。也就是说SecureRandom的对象所表示的随机源密钥对生成算法的执行可能会产生的关键参数本身,或者可能使用的算法参数生成器来生成,在这种情况下,它可能会或可能不会初始化算法参数发生器随机源。

算法参数发电机和算法参数

算法参数发电机 engineGenerateParameters方法必须返回一个 的AlgorithmParameters实例。

签名和密钥对生成算法或密钥工厂

如果要实现一个签名算法,将需要通过您的实现的engineInitSign的的engineInitVerify方法是有效的底层算法(如DSA密钥的DSS算法)键。您可以执行下列操作之一:

  1. 还可以创建自己的类实现适当的接口(例如从包java.security.interfaces实施的DSAPrivateKeyDSAPublicKey接口的类 ),并创建自己的密钥对生成器和/或密钥工厂,这些类型的返回键。要求的键,传递给engineInitSignengineInitVerify键您已经实现了,就是从你的密钥对生成器或密钥工厂生成的密钥类型。或者您也可以,
  2. 其他密钥对生成器或其他重要工厂接受按键,只要他们有合适的接口,使您的签名实现,以获取它所需要的信息(如私人和公共密钥和关键参数)的实例。例如,DSS签名类engineInitSign方法可以接受任何私钥是java.security.interfaces.DSAPrivateKey实例 

密钥库和密钥和证书工厂

密钥库的实现往往会利用解析keystore中存储的密钥,密钥工厂解析在密钥库中存储的证书和出厂合格证一个。

默认初始化

情况下,客户端没有显式初始化密钥对生成算法参数生成器,每一个这样的服务提供商必须提供(并记录)默认的初始化。例如,在Sun提供者使用一个默认的弹性模量为1024位的大小(强度)为生成DSA参数,“了SunJCE”提供者使用的Diffie-Hellman参数生成1024位的默认模大小(密钥大小)。

默认密钥对生成参数要求

如果实现密钥对生成,您的实现提供默认参数时所使用的客户端不指定参数。您所提供的文档(第11步)的默认参数是什么。

例如,太阳 提供的DSA密钥对生成器提供了一组预先计算p, q,和的默认值512,768,和1024位的密钥对的生成。以下的 pq值被用作1024位DSA密钥对生成的默认值:

P = fd7f5381 1d751229 52df4a9c 2eece4e7 f611b752 3cef4400 c31e3f80
    b6512669 455d4022 51fb593d 8d58fabf c5f5ba30,f6cb9b55 6cd7813b
    801d346f f26660b7 6b9950a5 a49f9fe8 047b1022 c24fbba9 d7feb7c6
    1bf83b57 e7c6a8a6 150f04fb 83f6d3c5 1ec30235 54135a16 9132f675
    f3ae2b61 d72aeff2 2203199d d14801c7

Q = 9760508f 15230bcc b292b982 a2eb840b f0581cf5

G = f7e1a085 d69b3dde cbbcab5c 36b857b9 7994afbb fa3aea82 f9574c0b
    3d078267 5159578e bad4594f e6710710 8180b449 167123e8 4c281613
    b7cf0932 8cc8a6e1 3c167a8b 547c8d28 e0a3ae1e 2bb3a675 916ea37f
    0bfa2135 62f1fb62 7a01243b cca4f1be a8519089 a883dfe1 5ae59f06,
    928b665e 807b5525 64014c3b fecf492a

这里给出pq的值,使用160位的素数生成标准产生的

SEED:8d515589 4229d5e6 89ee01e6 018a237e 2cae64cd

有了这个种子,p和 q的算法发现,当计数器92。)

Provider.Service

自推出以来,安全供应商已经公布了他们的服务信息通过适当的格式化字符串的键值对,他们把他们的哈希表项。虽然这种方法简单方便,它限制的量定制未能。其结果是,JDK 5.0引入了第二个选项,的 Provider.Service类 ​​。它提供了一种替代的方式宣传他们的服务提供商和支持额外的功能,如下所述。请注意,这除了是完全兼容较旧的方法使用字符串值的哈希表项。在JDK 5.0的提供者可以选择任何一种方法,因为它喜欢的,或者甚至同时使用在相同的时间。

一个Provider.Service对象封装了所有有关服务的信息。这是供应商提供的服务,它的类型(例如消息摘要或 签名),该算法的名称,和实现服务的类的名称。或者,它也包含此服务的替代算法名称(别名)和属性,这是一个地图(名称,值)对字符串的列表。此外,它定义了方法的newInstance()和 supportsParameter() 他们有默认的实现,但可以覆盖提供者,如果需要的话,可能是与供应商的情况下,该接口与硬件的安全令牌。

当它需要兴建新的执行实例的newInstance()方法被安全框架。默认实现使用反射来调用相应的服务类型的标准构造函数。对于所有标准服务的CertStore除外,这是无参数构造。论文病例必须是空的newInstance()constructorParameter对于服务类型的CertStore,构造函数被调用时,一个CertStoreParameters对象和 constructorParameter必须是一个非空的实例 CertStoreParameters安全提供程序可以覆盖的newInstance()的方法来实现,实现适当的实例。它可以使用直接调用或调用构造函数传递额外信息特定的提供者实例或令牌。例如,如果在系统上存在多个智能卡阅读器,它可能通过读者的信息与新创建的服务。然而,尽管定制的实现必须遵循 上述的约constructorParameter公约

supportsParameter()测试服务是否可以使用指定的参数。如果此服务不能使用参数,返回false。如果此服务可以使用参数,则返回true,如果一个快速测试是不可行的,或者如果状态未知。它是用来与某些类型的服务,由安全框架包括:排除不匹配的实现代价。目前仅定义以下标准服务:签署密码, 苹果,和KeyAgreement该 参数必须是在这些情况下,关键的一个实例例如,对于签名服务,该框架测试服务是否可以使用提供的密钥,然后实例化服务。默认实现检查的属性SupportedKeyFormats和 下文所述的SupportedKeyClasses同样,供应商可能会覆盖此方法来实现额外的测试。

SupportedKeyFormats属性是由“|”(管道)字符分隔的编码键(返回由key.getFormat() 所支持的格式的列表 例如,X.509 PKCS#8的 SupportedKeyClasses属性是由“|”字符分隔的接口的类的名称的列表。一个关键的对象被认为是可以接受的,如果它是分配给那些命名的类或接口中的至少一个。换句话说,如果密钥对象的类的一个子类,其中一个列出的类(或类本身),或者如果它实现所列出的接口。一个例子值是 “java.security.interfaces.RSAPrivateKey | java.security.interfaces.RSAPublicKey” 

四个方法已被添加到Provider类为添加和仰望服务。正如前面提到的,实施这些方法和现有的属性方法已专门设计,以确保与现有的供应商的子类。这是实现,如下所示:

如果遗留属性的方法被用于增加项目,确保Provider类属性字符串解析成等价的服务对象GetService的()来查找之前通过 同样,如果 使用putService()方法,相当于属性字符串被放置在同一时间到提供程序的哈希表。如果提供实现覆盖Provider类的任何方法,它必须确保其实施这种转换不会干扰。为了避免出现问题,我们建议实现不覆盖提供 类中的任何方法

签名格式

如果实现签名算法,您所提供的文件(步骤11)应指定 编码格式,其中的签名(所产生的标志方法之一)。

例如,SHA1的DSA签名算法由太阳提供者提供的编码的签名作为一个标准的ASN.1序列的两个ASN.1 INTEGER值: RS,在该顺序:

序列:: = {
        R INTEGER,
        Ş整数}

DSA接口和其所需的实现

Java安全API包含以下的接口(在 java.security.interfaces包)为了方便程序员实现DSA服务:

以下各节讨论了为实现这些接口的要求。

DSAKeyPairGenerator 实现

这个接口是过时的。它用于需要,使客户能提供DSA特定的参数,而不是默认的参数实施供应。然而,在Java中,它不再是必要的;一个的新KeyPairGenerator的 初始化方法,需要 AlgorithmParameterSpec的参数,使客户能够表明算法的参数。

DSAParams 实施

如果要实现一个DSA密钥对生成器,你需要一个的类实现DSAParams持有并返回PQ,和 参数。

如果你还需要落实DSAPrivateKey和 DSAPublicKey接口à DSAParams实现DSAPublicKey和 DSAPrivateKey都延长DSAKey的接口,其中包含一个getParams方法,必须返回一个 DSAParams的对象。参见更多信息DSAPrivateKey和DSAPublicKey实现

注:有一个DSAParams的执行建到JDK: java.security.spec.DSAParameterSpec类。

DSAPrivateKey 和DSAPublicKey 实现

如果实现DSA密钥对生成器或密钥工厂,你需要创建实施DSAPrivateKey 和DSAPublicKey接口的

如果实现DSA密钥对生成器,你的 generateKeyPair方法(在您的 KeyPairGeneratorSpi子类)将返回您实现这些接口的实例。

实现DSA密钥工厂如果,你 engineGeneratePrivate的方法(在您的 KeyFactorySpi子类)将返回的一个实例您的DSAPrivateKey实现,您的 engineGeneratePublic方法会返回一个实例您的DSAPublicKey实施。

此外,您的engineGetKeySpec和的 engineTranslateKey方法将期望传入的关键是一个DSAPrivateKey或 实施DSAPublicKey的一个实例。 getParams所提供的接口实现的方法是有用的,用于获得和从键中提取的参数,然后使用参数,例如,作为参数的构造函数调用以创建可用于初始化一个KeyPairGenerator的参数值的参数规格从DSAParameterSpec DSA的对象。

如果实现DSA签名算法 在您的SignatureSpi中的子类)的engineInitSign方法( 将希望传递一个 DSAPrivateKey和您的engineInitVerify 方法将希望传递一个DSAPublicKey的

请注意:DSAPublicKey和 DSAPrivateKey接口定义一个非常通用的接口,提供独立的DSA公钥和私钥,分别。engineGetKeySpec和 engineTranslateKey方法(在您的 KeyFactorySpi子类)可以进行额外的检查,如果传入的关键实际上是他们的供应商本身的实施DSAPrivateKey或 DSAPublicKey的,例如一个实例,利用提供具体的实施细节。为DSA的签名算法engineInitSign和 engineInitVerify方法(在您的 SignatureSpi中的子类)也是如此

要实施DSAPublicKey和 DSAPrivateKey接口的类需要实现什么方法,首先注意如下界面签名:

在的java.security.interfaces包:

   公共DSAPrivateKey接口扩展DSAKey
                为java.security.PrivateKey

   公共DSAPublicKey接口扩展DSAKey
                java.security.PublicKey

   公共接口DSAKey的 

java.security中包:

   公共接口私钥扩展关键

   公共公钥接口扩展关键

   公共接口密钥扩展了java.io.Serializable 

为了实现在DSAPrivateKey和 DSAPublicKey接口,就必须实现他们所定义的方法,以及它们扩展的接口,直接或间接所定义的。

因此,对于私钥,你需要提供一个类实现

  • 的getX方法从 DSAPrivateKey接口。
  • getParams方法从java.security.interfaces.DSAKey 接口“,自DSAPrivateKey扩展 DSAKey的注:getParams方法返回一个DSAParams对象,所以你还必须有一个 DSAParams 实施
  • getEncoded方法getAlgorithm 的getFormat方法从java.security.Key 接口,因为DSAPrivateKey扩展 为java.security.PrivateKey的私钥 延伸的关键

    同样,对于公共DSA密钥,你需要提供一个类实现:

    • 的getY方法从DSAPublicKey 接口。
    • getParams方法从java.security.interfaces.DSAKey 接口“,自DSAPublicKey扩展DSAKey的。注:getParams方法返回一个DSAParams 对象,所以你还必须有一个DSAParams实施
    • getEncoded方法getAlgorithm 的getFormat方法从java.security.Key 接口,因为DSAPublicKey扩展 java.security.PublicKey的,和公钥 延伸的关键

RSA接口和其所需的实现

Java安全API包含以下的接口(在 java.security.interfaces包)为了方便程序员实现RSA服务:

以下各节讨论了为实现这些接口的要求。

RSAPrivateKey , RSAPrivateCrtKeyRSAPublicKey 实现

如果实现的RSA密钥对生成器或密钥工厂,您需要创建实施RSAPrivateKey (和/或RSAPrivateCrtKey的)和 RSAPublicKey接口的RSAPrivateCrtKey是一个RSA私钥的接口,使用中国剩余定理(CRT)表示。)

如果你实现一个RSA密钥对生成器,你的 generateKeyPair方法(在您的 KeyPairGeneratorSpi子类)将返回您实现这些接口的实例。

如果你实现一个RSA密钥工厂, engineGeneratePrivate方法(在您的 KeyFactorySpi子类)将返回一个实例的RSAPrivateKey(或RSAPrivateCrtKey)的实施,并您的engineGeneratePublic方法会返回一个实例您的RSAPublicKey 实施。

此外,您的engineGetKeySpec和的 engineTranslateKey方法将期望传入的关键, RSAPrivateCrtKey RSAPrivateKeyRSAPublicKey 实现的一个实例

如果实现的RSA签名算法,您的 engineInitSign方法(在您的 SignatureSpi中的子类)将希望传递要么是RSAPrivateKey的或一个RSAPrivateCrtKey,和您的engineInitVerify方法将希望传递RSAPublicKey的

请注意, RSAPrivateKey RSAPublicKeyRSAPrivateCrtKey 接口定义了一个非常通用的接口,提供独立的RSA公钥和私钥。engineGetKeySpec和 engineTranslateKey方法(在您的 KeyFactorySpi子类)可以进行额外的检查,如果传入的关键实际上是他们的供应商本身的实施, RSAPrivateCrtKey RSAPrivateKeyRSAPublicKey的,例如一个实例,利用提供具体的实施细节。同样是真正的RSA签名算法 engineInitSign engineInitVerify的 方法(在您的SignatureSpi中的子类)。

要实施RSAPublicKey, RSAPrivateKeyRSAPrivateCrtKey 接口的类需要实现什么方法,首先注意如下界面签名:

在的java.security.interfaces包:

    公共RSAPrivateKey接口扩展为java.security.PrivateKey的

    公共RSAPrivateCrtKey接口扩展RSAPrivateKey的

    公共RSAPublicKey接口扩展java.security.PublicKey的

java.security中包:

    公共接口私钥扩展关键

    公共公钥接口扩展关键

    公共接口密钥扩展了java.io.Serializable

为了贯彻落实RSAPrivateKey, RSAPrivateCrtKeyRSAPublicKey 接口,就必须实现他们所定义的方法,以及它们扩展的接口,直接或间接所定义的。

因此,对于RSA私钥,你需要提供一个类实现:

  • 方法从 RSAPrivateKey接口getModulusgetPrivateExponent
  • getEncoded方法getAlgorithm 的getFormat方法从java.security.Key 接口,因为RSAPrivateKey扩展 为java.security.PrivateKey的私钥 延伸的关键

同样,对于RSA私钥使用中国剩余定理(CRT)表示,你需要提供一个类实现:

  • 所有上面列出的方法,因为RSAPrivateCrtKey扩展 java.security.interfaces.RSAPrivateKey的 RSA私钥 
  • getPublicExponent getPrimeP, getPrimeQ, getPrimeExponentQ getPrimeExponentP,的getCrtCoefficient 方法从 RSAPrivateKey接口。

公共RSA密钥,你需要提供一个类实现:

  • 方法从RSAPublicKey 接口getModulusgetPublicExponent
  • getEncoded方法getAlgorithm 的getFormat方法从java.security.Key 接口,因为RSAPublicKey扩展 java.security.PublicKey的,和公钥 延伸的关键

,JCA包含一些的AlgorithmParameterSpec 实现为最经常使用的加密算法和密钥协议算法参数。如果您正在操作JCA提供了不同类型的算法的算法参数,应该是,你将需要为这种类型的算法提供适当自己的 AlgorithmParameterSpec实现的。

的Diffie-Hellman接口和其所需的实现

JCA包含下列接口(中的 方法javax.crypto.interfaces包),为方便程序员实现的Diffie-Hellman服务:

以下各节讨论了为实现这些接口的要求。

DHPrivateKey 和DHPublicKey 实现

如果实现的Diffie-Hellman密钥对生成器或密钥工厂,你需要创建实施DHPrivateKeyDHPublicKey 接口的类 

如果实现的Diffie-Hellman密钥对生成器,你的 generateKeyPair方法(在您的 KeyPairGeneratorSpi子类)将返回您实现这些接口的实例。

如果实现的Diffie-Hellman密钥工厂,你 engineGeneratePrivate的方法(在您的 KeyFactorySpi子类)将返回的一个实例您的DHPrivateKey实现,您的 engineGeneratePublic方法会返回一个实例您的DHPublicKey实施。

此外,您的engineGetKeySpec和的 engineTranslateKey方法将期望传入的关键是一个DHPrivateKey或 实施DHPublicKey的一个实例 用于获得和从键中提取的参数所提供的接口实现getParams方法是有用的。然后,您可以使用的参数,例如,作为参数到 DHParameterSpec的构造函数调用来创建一个参数规格使用的Diffie-Hellman 初始化KeyPairGenerator对象中的参数值 

如果你实现Diffie-Hellman密钥协议算法,您的engineInit时方法(您的 KeyAgreementSpi子类)会期望,通过 DHPrivateKey您的engineDoPhase 方法将希望传递一个DHPublicKey

注:DHPublicKey和 DHPrivateKey接口定义一个非常通用的,独立于供应接口的Diffie-Hellman公钥和私钥。engineGetKeySpec和 engineTranslateKey方法(在您的 KeyFactorySpi子类)可以进行额外的检查,如果传入的关键实际上是他们的供应商本身的实施DHPrivateKey或 DHPublicKey的,例如一个实例,利用提供具体的实施细节。同样是真实的Diffie-Hellman算法engineInit时的engineDoPhase方法(您的 KeyAgreementSpi子类)。

要实施DHPublicKey和 DHPrivateKey接口的类需要实现什么方法,首先注意如下界面签名:

方法javax.crypto.interfaces包:

    公共接口,为java.security.PrivateKey DHPrivateKey延伸DHKey

    公共DHPublicKey接口扩展,java.security.PublicKey DHKey

    公共接口DHKey的 

java.security中包:

    公共接口私钥扩展关键

    公共公钥接口扩展关键

    公共接口密钥扩展了java.io.Serializable 

为贯彻落实DHPrivateKey和 DHPublicKey接口,就必须实现他们所定义的方法,以及它们扩展的接口,直接或间接所定义的。

因此,对于私钥,你需要提供一个类实现:

  • 的getX方法从DHPrivateKey 接口。
  • getParams方法从javax.crypto.interfaces.DHKey 接口“,自DHPrivateKey扩展 DHKey的
  • getEncoded方法getAlgorithm 的getFormat方法从java.security.Key 接口,因为DHPrivateKey扩展 为java.security.PrivateKey的私钥 延伸的关键

同样,对于公众的Diffie-Hellman密钥,你需要提供一个类实现:

  • 的getY方法从DHPublicKey 接口。
  • getParams方法从javax.crypto.interfaces.DHKey 接口“,自DHPublicKey扩展 DHKey的
  • getEncoded方法getAlgorithm 的getFormat方法从java.security.Key 接口,因为DHPublicKey扩展 java.security.PublicKey的,和公钥 延伸的关键

其他算法类型的接口

如上所述,Java安全API包含为方便实施服务,如DSA,RSA和ECC的程序员的接口。如果有不支持API的服务,你需要定义你自己的API。

如果要实现密钥对生成不同的算法,你应该创建一个接口与一个或多个 客户端可以调用的初始化方法时,他们要提供特定算法要使用的参数,而不是默认的参数实施供应。的子类KeyPairGeneratorSpi的,应实现这个接口。

对于没有直接API支持的算法,它是建议你创建类似的接口和实现类。你的公钥接口扩展的公钥 界面。同样,你的私钥接口应该延长的 私钥 界面。

算法参数规范接口和类

算法参数规范是一种透明的代表性的算法中使用的参数集。

参数à 透明表示意味着,您可以访问每个值,通过 相应规范类中定义的方法之一(例如, DSAParameterSpec定义getP的, getQgetG方法,访问的p,q和g参数,分别)。

这是对比与不透明表示,所提供的AlgorithmParameters引擎类,你有没有直达的关键材料值,你只能得到相关的算法参数设置的名称(通过 getAlgorithm)和某种编码参数集(通过getEncoded方法)。

如果您提供的AlgorithmParametersSpi, AlgorithmParameterGeneratorSpi或 KeyPairGeneratorSpi实施,你必须利用的AlgorithmParameterSpec接口,因为这些类包含采取一个AlgorithmParameterSpec参数的方法 这种方法需要确定实际执行已经通过该接口,并采取相应的行动。

JCA的的AlgorithmParameterSpec 实现了最常用的数字签名,加密算法和密钥协议算法参数包含了一些如果您正在操作JCA提供了不同类型的算法的算法参数,应该是,你将需要为这种类型的算法提供适当自己的AlgorithmParameterSpec实现的。

Java定义了下面的算法参数规范接口和类在java.security.spec和的 javax.crypto.spec包:

 AlgorithmParameterSpec接口

AlgorithmParameterSpec到一个透明的接口规范的加密参数。

此接口不包含任何方法或常量。其唯一的目的就是组(并为其提供类型安全)所有的参数规格。所有的参数规范都必须实现这个接口。

 DSAParameterSpec

这个类(实现 AlgorithmParameterSpecDSAParams 接口)指定使用的DSA算法的参数集。它有以下几种方法:

    公共:BigInteger的getP()

    公共:BigInteger的getQ()

    公共:BigInteger的getG()

这些方法返回的DSA算法参数:对素数 P,次贷q,和基地 

许多类型的DSA服务会发现这类有用的-例如,它是利用DSA签名,密钥对生成算法的参数生成器,和太阳提供商实施的算法参数的类作为一个具体的例子,算法参数的实施必须包括执行的getParameterSpec的方法,该方法返回一个AlgorithmParameterSpecDSA算法参数实现由Sun提供的返回一个实例的 DSAParameterSpec类的。

 IvParameterSpec 类

这个类的(实现在 AlgorithmParameterSpec接口)指定用于在反馈模式用密码的初始化向量(IV)。

方法描述
IvParameterSpec方法
字节[] getIV() 返回初始化向量(IV)。

 OAEPParameterSpec 类

这个类的(实现在 AlgorithmParameterSpec接口)指定用于在反馈模式用密码的初始化向量(IV)。

方法描述
IvParameterSpec方法
字节[] getIV() 返回初始化向量(IV)。

 PBEParameterSpec 类

这个类(实现的 AlgorithmParameterSpec接口)指定一组使用基于密码的加密算法(PBE)的参数。

方法描述
PBEParameterSpec方法
getIterationCount() 返回的迭代计数。
byte []的getSalt() 返回盐。

 RC2ParameterSpec 类

这个类(实现的 AlgorithmParameterSpec接口)指定一组与RC2算法使用的参数。

方法描述
RC2ParameterSpec方法
摘要boolean equals(Object obj)在 测试指定的对象,这个对象之间的平等。
int getEffectiveKeyBits的() 返回位有效密钥大小。
字节[] getIV() 返回IV或空,如果不包含此参数设置的IV。
诠释了hashCode() 计算对象的哈希码值。

 RC5ParameterSpec 类

这个类(实现的 AlgorithmParameterSpec接口)指定RC5算法使用的参数的集合。

方法描述
RC5ParameterSpec方法
摘要boolean equals(Object obj)在 测试指定的对象,这个对象之间的平等。
字节[] getIV() 返回IV或空,如果不包含此参数设置的IV。
int getRounds的() 返回的回合数。
整型的getVersion() 返回的版本。
int getWordSize的() 返回位的字长。
诠释了hashCode() 计算对象的哈希码值。

 DHParameterSpec 类

这个类的(实现在 AlgorithmParameterSpec接口)指定使用的Diffie-Hellman算法的参数的集合。

方法描述
DHParameterSpec方法
的BigInteger getG() 返回基地发生器
诠释getL() 返回位,的随机指数(私有值)的大小
的BigInteger getP() 返回质数模数p

会发现这类有用的Diffie-Hellman服务的多种类型的,例如,它是由Diffie-Hellman密钥协议,密钥对生成器,算法参数生成器,和了SunJCE“提供者实施的算法参数的类。作为一个具体的例子,算法参数的实施必须包括执行的getParameterSpec的 方法,该方法返回一个AlgorithmParameterSpec的Diffie-Hellman算法参数的实施提供了SunJCE“返回一个实例的DHParameterSpec 类的。

重点规格主要工厂所需的接口和类

密钥工厂提供不透明密钥(密钥类型)和关键指标之间的双向转换如果您实现一键工厂,因此,你需要了解和利用的关键指标。在某些情况下,你还需要实现自己的关键规格。

进一步了解的关键指标,在Java中提供的接口和类,以及密钥工厂的规格要求,提供如下。

主要规格是构成了关键的密钥材料的透明表示。如果密钥存储在硬件设备,其规格可能包含的信息,有助于识别设备上的关键。

à 透明表示意味着,你可以单独访问每个密钥的物质价值,通过获取相应规范类中定义的方法之一 例如, java.security.spec。 DSAPrivateKeySpec定义 的getX getPgetQ和 方法getG,访问私钥 x和用于计算密钥的DSA算法参数:次贷的数p ,q,基地ĝ

这是对比的一个的不透明表示,所定义的关键接口,你有没有直接访问到的参数字段。换句话说,“不透明”表示让你有限的访问密钥-只是重点接口定义的三种方法:getAlgorithm 的getFormat,和getEncoded方法

A键可以指定一个特定算法的方式,或与算法无关的编码格式(如ASN.1)。例如,DSA私钥可以用它的分量x, Q,和g(见DSAPrivateKeySpec来指定 ,或者它可以被指定为使用它的DER编码( 参见 PKCS8EncodedKeySpec )。

Java定义了以下主要规范的接口和类在java.security.spec和的 javax.crypto.spec包:

KeySpec 接口

此接口不包含任何方法或常量。其唯一的目的是为了组(并为其提供类型安全)所有关键规格。所有密钥规范都必须实现这个接口。

Java提供了几个类实现 和 X509EncodedKeySpec

如果您的提供商使用的JDK已经不提供相应的KeySpec类的关键类型(例如, Your_PublicKey_type和 Your_PrivateKey_type,有两种可能的方案,其中一个需要你实现你自己的密钥规范:

  1. 如果您的用户将永远不会有访问特定的关键物质价值的密钥类型,你不会有任何KeySpec提供 密钥类型, 在这种情况下,您的用户将始终通过提供适当的KeyPairGenerator的创建 Your_PublicKey_type和 Your_PrivateKey_type的键 您的供应商该键的类型。如果他们要存储供以后使用生成的密钥,他们检索键的编码(使用 的getEncoded方法的关键接口)。当他们想要创建一个Your_PublicKey_type或 Your_PrivateKey_type键编码(例如,为了初始化一个签名的对象进行签名或验证),他们 从编码创建一个实例的 X509EncodedKeySpecPKCS8EncodedKeySpec,养活它提供适当 KeyFactory您的供应商,算法,其generatePublic的generatePrivate方法将返回请求的 公钥(实例 Your_PublicKey_type)或私钥(实例Your_PrivateKey_type)对象,分别。

  2. 如果你预期需要为用户访问特定的关键物质价值的密钥类型,或构造一个密钥的密钥类型,从关键材料和相关的参数值,而不是从它的编码(如在上述情况下),你必须指定新 KeySpec类(类实现 KeySpec接口)与适当的构造方法,并获得返回密钥类型的关键材料领域和相关参数值的方法。您将指定这些类以类似的方式是通过 在JDK 6中提供的类的 DSAPrivateKeySpec到DSAPublicKeySpec的您需要运送这些类以及与您的供应商类,例如,作为您的服务提供商JAR文件的一部分。

 DSAPrivateKeySpec 类

这个类(它实现KeySpec界面),指定DSA私钥及其相关的参数。它有以下几种方法:

DSAPrivateKeySpec方法描述
公众的BigInteger的getX() 返回私人密钥x。
公共:BigInteger的getP() 返回素数p。
公共:BigInteger的getQ() 返回亚质数q。
公共:BigInteger的getG() 返回基数g。

这些方法返回私钥x和用于计算密钥的DSA算法参数:对素数 P,次贷q,和基地 

 到DSAPublicKeySpec 类

这个类(它实现KeySpec界面),指定其相关的参数的DSA公钥。它有以下几种方法:

到DSAPublicKeySpec方法描述
公共BigInteger的杰蒂() 返回公共密钥y。
公共:BigInteger的getP() 返回素数p。
公共:BigInteger的getQ() 返回亚质数q。
公共:BigInteger的getG() 返回基数g。

这些方法返回的公钥Ÿ,用于计算密钥的DSA算法参数:对素数 P,次贷q,和基地 

 RSAPrivateKeySpec 类

这个类(它实现KeySpec界面),指定一个RSA私钥。它有以下几种方法:

RSAPrivateKeySpec方法描述
公共:BigInteger的getModulus() 返回的弹性模量。
公共:BigInteger的getPrivateExponent() 返回私有幂。

这些方法返回RSA模数Ñ和私人指数的ð值构成RSA私钥。

 RSAPrivateCrtKeySpec 类

这个的类(延伸RSAPrivateKeySpec类)指定一个RSA私钥,PKCS#1标准中定义的,使用中国剩余定理(CRT)信息值。它有以下几种方法(继承从其超类RSAPrivateKeySpec的方法,除了):

RSAPrivateCrtKeySpec方法描述
公共:BigInteger的getPublicExponent() 返回公共指数。
公共:BigInteger的getPrimeP() 返回黄金P.
公共:BigInteger的getPrimeQ() 返回总理问:
公共:BigInteger的getPrimeExponentP() 返回primeExponentP。
公共:BigInteger的getPrimeExponentQ() 返回primeExponentQ。
公共的BigInteger getCrtCoefficient的() 返回crtCoefficient。

这些方法返回的公共指数ê CRT信息整数的素因子p的模Ñ的首要因素q的 ND MOD指数(P-1) D MOD指数 (Q-1) 中国剩余定理系数(逆的q)模p

在逻辑上由一个RSA私钥只有模数和私人指数。CRT值的存在的目的是为了提高效率。

 RSAPublicKeySpec 类

这个类(它实现KeySpec界面),指定的RSA公钥。它有以下几种方法:

RSAPublicKeySpec方法描述
公共:BigInteger的getModulus() 返回的弹性模量。
公共:BigInteger的getPublicExponent() 返回公共指数。

这些方法返回RSA模数Ñ和公共指数的Ë值构成的RSA公钥。

EncodedKeySpec的 类

这个抽象类(它实现KeySpec界面),代表了编码格式的公钥或私钥。

EncodedKeySpec的方法描述
公共抽象的byte []的getEncoded() 返回编码的关键。
公共抽象字符串的getFormat() 返回的编码格式的名称。

JDK 6中提供了两个类实施 EncodedKeySpec的接口:PKCS8EncodedKeySpecX509EncodedKeySpec如果需要,您可以提供自己EncodedKeySpec的那些或其他类型的关键编码的实现。

 PKCS8EncodedKeySpec

是一个子类EncodedKeySpec的这一类,它代表一个私有密钥的DER编码,按照指定的格式在PKCS#8标准。

的getEncoded方法返回的PKCS#8标准编码的密钥字节。其 GetFormat方法返回字符串“PKCS#8”。

 X509EncodedKeySpec 类

是一个子类EncodedKeySpec的这一类,它代表一个公钥或私钥的DER编码,根据X.509标准中指定的格式。

的getEncoded方法返回的关键字节,根据X.509标准进行编码。GetFormat 方法返回字符串“X.509”。DHPublicKeySpec DHPrivateKeySpec, DESKeySpecDESedeKeySpecPBEKeySpecSecretKeySpec

 DHPrivateKeySpec 类

这个类(它实现KeySpec 接口)指定的Diffie-Hellman私钥及其相关的参数。

DHPrivateKeySpec方法描述
的BigInteger getG() 返回基地发生器
的BigInteger getP() 返回质数模数p
的BigInteger的getX() 返回私有 x 

 DHPublicKeySpec 类

这个类(它实现KeySpec 接口)指定的Diffie-Hellman公钥其相关的参数。

DHPublicKeySpec方法描述
的BigInteger getG() 返回基地发生器
的BigInteger getP() 返回质数模数p
BigInteger的杰蒂() 返回的公共价值Y

 DESKeySpec 类

这个类(它实现KeySpec 接口)指定的DES密钥。

DESKeySpec方法描述
字节[]的getKey() 返回的DES密钥字节。
静态布尔isParityAdjusted的(字节[]键,int offset)在 检查给定的DES密钥内容是奇偶调整。
静态:布尔isWeak(的byte []键,诠释抵消) 检查如果给定的DES密钥材料是弱或者半弱。

 DESedeKeySpec 类

这个类(它实现KeySpec 接口)指定一个DES-EDE(三重DES)键。

DESedeKeySpec方法描述
字节[]的getKey() 返回的DES-EDE密钥。
静态布尔isParityAdjusted的(字节[]键,int offset)在 如果给定的DES-EDE密钥的检查是平价调整。

 PBEKeySpec 类

这个类实现了KeySpec 接口。用户选择的密码,可以使用基于密码的加密(PBE),密码可以被看作是一种类型的原始密钥材料。使用这个类的加密机制可以得到一个加密密钥,从原始密钥材料。

PBEKeySpec方法描述
无效clearPassword 清除密码的内部副本。
诠释getIterationCount的 返回迭代计数或0,如果没有指定。
诠释第getKeyLength号 返回所述待导出密钥长度或0,如果没有指定。
的char []忘记密码 返回的密码的副本。
byte []的getSalt 如果没有指定的盐或空返回一个副本。

 SecretKeySpec 类

这个类实现了KeySpec 接口。,因为它也实现SecretKey的 接口,它可以被用来构造一个SecretKey的 对象,而无需在一个提供独立的方式,即,通过一家提供基于SecretKeyFactory的

SecretKeySpec方法描述
摘要boolean equals(Object obj)在 表示是否有其他的对象是“平等”这一项。
弦乐getAlgorithm() 返回与此密钥关联的算法的名称。
为byte []的getEncoded() 返回这个秘密的关键的关键材料。
弦乐的getFormat() 返回此秘密密钥的编码格式的名称。
诠释了hashCode() 计算对象的哈希码值。

秘密密钥生成

如果您提供密钥发生器(子类 javax.crypto.KeyGeneratorSpi)的一个特定的密钥算法,你可以将生成的密钥对象(必须的一个实例 javax.crypto.SecretKey,见engineGenerateKey)通过以下方法之一:

  • 您可以实现一个类的实例代表秘密密钥关联的算法与密钥生成。你的密钥生成器实现该类的实例返回。这种方法是有用的,如果你的密钥生成器生成的密钥提供特定的属性。
  • 你的密钥生成器返回的SecretKeySpec,其中已经实现了javax.crypto.SecretKey的 接口的一个实例您可以通过键(原始)字节,并与您的密钥生成的SecretKeySpec构造函数相关联的密钥算法的名称 这种方法是非常有用的,如果底层(原始)密钥字节可以表示为一个字节数组,有没有关键参数与它们相关联。

添加新的对象标识符

以下信息适用于供应商提供一种算法,没有被列为附录标准算法之一 Java加密体系结构参考指南

从OID映射名称

有时JCA需要实例化的算法的标识符(例如,编码的证书),由定义包括的对象标识符(OID),该算法的加密算法的实现。例如,为了验证签名X.509证书,JCA确定签名算法的签名算法的标识符,证书中编码,该算法实例Signature对象,初始化签名验证对象。

JCA找到你的算法,你必须提供你的算法的对象标识符作为你的算法在供应商主文件的别名项目。

    把(“Alg.Alias​​。<engine_type> .1.2.3.4.5.6.7.8”
        “<algorithm_alias_name>”);

需要注意的是,如果你的算法被称为下一个以上的对象标识符,你需要创建一个别名条目为每个对象的标识符,它被称为。

JCA需要执行此类型的映射的一个例子是,当你的算法(“  “)是一个签名算法和用户运行keytool的命令,并指定(签字)算法的别名。

    %keytool的genkeypair sigalg 1.2.3.4.5.6.7.8

在这种情况下,您的供应商主文件应包含以下条目:

    把(“Signature.Foo”,“com.xyz.MyFooSignatureImpl”);
    把(Alg.Alias​​.Signature.1.2.3.4.5.6.7.8“,”富“);

这种类型的映射进行的其他例子有:(1)当你的算法是一个KeyType的算法和程序解析证书(使用X.509实施的,太阳提供商)和提取公钥证书,以初始化签名对象进行核查,及(2)当 keytool的用户尝试访问一个私钥KeyType的(例如,要进行数字签名)后,产生相应的密钥对。在这些情况下,您的供应商主文件应包含以下条目:

    把(“KeyFactory.Foo”,“com.xyz.MyFooKeyFactoryImpl”);
    把(Alg.Alias​​.KeyFactory.1.2.3.4.5.6.7.8“,”富“);

从名称映射到OID

如果JCA需要进行逆映射(即从你的算法的名称及其相关的OID),您需要提供以下形式的别名项目应该知道你的算法的OID之一:

    把(“Alg.Alias​​.Signature.OID.1.2.3.4.5.6.7.8”,“MySigAlg”);

在不止一个对象标识符,如果你的算法被称为前缀的首选之一,“OID”。

JCA需要进行这种映射的一个例子是当用户运行keytool将在任何模式下,需要一个sigalg选项。例如,当 调用-genkeypair 的certreq命令,用户可以指定您的算法(签字) sigalg选项。

确保出口能力

JCA的一个关键特征是JCA框架和出口能力的提供商的加密实现,如果某些条件得到满足。

由于进口控制限制由少数几个国家的政府,管辖的政策文件从Sun Microsystems指定“强”,但有限的加密,可以使用附带的JDK 6。一个“无限”的版本,这些文件表明没有限制的加密强度是那些生活在有资格的国家(这是大多数国家)。但是,只有“强”的版本可以被导入到这些国家的政府的授权限制。JCA框架将强制安装的司法管辖区的政策文件中规定的限制。

正如其他地方,你可以写你的供应商软件仅仅只是一个版本,实现最大强度的加密技术。它是由JCA,而不是你的供应商,执行任何司法管辖区的政策文件规定的限制可​​用于小应用程序/应用程序在不同的地方加密算法和加密强度最大。

您的供应商,以使其能够插入JCA必须满足的条件有以下几种:

  • 每个SPI实现类的构造应做自我完整性检查,所描述的供应商可以如何做自我完整性检查
  • 应书面提供程序代码provider类这样一种方式,变得无法使用,如果由一个应用程序,绕过JCA直接实例化。步骤1:写步骤来实施并集成提供部分服务实现代码
  • 提供者包必须签署JCA框架信任的实体。(见步骤6.1步骤6.2)的供应商可能会出口到美国以外的美国厂商首先需要申请美国政府的出口审批。(见第10步)。

附录A:Sun提供商大师班的

以下是经过编辑的版本,其中包含名为太阳一类主类的供应商,名为 太阳的Sun.java文件

正如所有的大师班,这个类是提供的一个子类 它指定由太阳 提供商提供的所有服务实现的类名和包位置此信息用于 查找的各种算法和其他服务的请求时,引擎类的getInstance方法。

提供此代码作为一个供应商主类的一个例子。

/ *
 * @(#)Sun.java 1.28 99/05/27
 *
 版权所有(c)1996年,1998年,Oracle和/或其联属公司。保留所有权利。
 *
 *源代码和二进制形式再分发和使用,有或无
 *修改,允许符合下列条件
 *满足:
 *
 *  - 再分发源代码时必须保留上述版权
 *声明,本条件列表及以下免责声明。
 *
 *  - 以二进制形式再分发必须复制上述版权
 *通知,此条件列表和以下免责声明
 *分布提供的文档和/或其他材料。
 *
 *  - 本Oracle或名称与它的名字
 *贡献者可用于认可或推广衍生产品
 *未经事先书面许可,本软件。
 *
 *本软件提供,版权所有者和贡献者“
 *“任何明示或暗示的担保,包括但不限于,
 *为特定的适销性和适用性的暗示担保
 *目的被否认。在任何情况下,著作权人或者与
 *贡献者均不对任何直接的,间接的,附带的,特殊的,
 *惩罚性的或后果性的损失(包括但不限于,
 *替代商品或服务的采购,使用损失,数据或
 *利润或业务中断),无论起因和任何理论
 *责任,无论是在合同,严格责任或侵权行为(包括
 *疏忽或其他原因)而引起的任何一路输出,使用本
 *软件,即使已被告知发生此类损害的可能性。
 *
 * /

包sun.security.provider;

进口java.io. *;
进口java.util中。
进口的java.security。

/ **
 *太阳安全提供商。
 *
 * @作者本杰明·雷诺
 *
 * @版本1.28,99年5月27日
 * /

/ **
 定义SUN商。
 *
 *支持的算法,他们的名字:
 *
 *  -  SHA消息摘要方案FIPS 180-1描述。
 *别名SHA SHA-1和SHA1。
 *
 *  -  SHA1的DSA签名方案FIPS 186中​​描述。
 *(SHA DSA使用SHA-1的变化没有1:FIPS 186)。
 *别名SHA1的DSA是DSA,DSS,SHA / DSA,SHA-1/DSA,SHA1/DSA,
 * SHAwithDSA DSAWithSHA1,并且对象
 *标识符字符串的“OID.1.3.14.3.2.13”,“OID.1.3.14.3.2.27”
 *“OID.1.2.840.10040.4.3。
 *
 *  -  DSA密钥生成方案中所描述的FIPS 186。
 * DSA别名包括OID字符串“OID.1.3.14.3.2.12”
 *和“OID.1.2.840.10040.4.1”。
 *
 *  -  MD5是在RFC 1321中描述的消息摘要计划。
 *有没有别名为MD5。
 * /

公开最终的类太阳提供商{

    私人静态最终的String =“SUN”信息+
    “(DSA密钥/参数生成DSA签署”+
    “SHA-1,MD5摘要SecureRandom的X.509证书; JKS密钥库)”;

    公共Sun(){
        / *我们是太阳提供商* /
        超(“太阳”,1.2,INFO);

        AccessController.doPrivileged(新java.security.PrivilegedAction的(){
            公共对象的run(){

                / *
                 *签名引擎
                 * /
                把(“Signature.SHA1withDSA”,“sun.security.provider.DSA”);

                把(“Alg.Alias​​.Signature.DSA”,“带DSA的SHA1”);
                把(“Alg.Alias​​.Signature.DSS”,“带DSA的SHA1”);
                把(“Alg.Alias​​.Signature.SHA / DSA”,“带DSA的SHA1”);
                把(“Alg.Alias​​.Signature.SHA-1/DSA”,“带DSA的SHA1”);
                把(“Alg.Alias​​.Signature.SHA1/DSA”,“带DSA的SHA1”);
                把(“Alg.Alias​​.Signature.SHAwithDSA”,“带DSA的SHA1”);
                把(“Alg.Alias​​.Signature.DSAWithSHA1”,“带DSA的SHA1”);
                把(“Alg.Alias​​.Signature.OID.1.2.840.10040.4.3”,
                    “SHA1的DSA”);
                把(“Alg.Alias​​.Signature.1.2.840.10040.4.3”,“带DSA的SHA1”);
                把(“Alg.Alias​​.Signature.1.3.14.3.2.13”,“带DSA的SHA1”);
                把(“Alg.Alias​​.Signature.1.3.14.3.2.27”,“带DSA的SHA1”);

                / *
                 *密钥对发电机引擎
                 * /
                把(的“KeyPairGenerator.DSA”
                    “sun.security.provider.DSAKeyPairGenerator”);
                把(“Alg.Alias​​.KeyPairGenerator.OID.1.2.840.10040.4.1”,“DSA”);
                put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
                put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");

                /*
                 * Digest engines
                 */
                put("MessageDigest.MD5", "sun.security.provider.MD5");
                put("MessageDigest.SHA", "sun.security.provider.SHA");

                put("Alg.Alias.MessageDigest.SHA-1", "SHA");
                put("Alg.Alias.MessageDigest.SHA1", "SHA");

                /*
                 * Algorithm Parameter Generator engines
                 */
                put("AlgorithmParameterGenerator.DSA",
                    "sun.security.provider.DSAParameterGenerator");

                /*
                 * Algorithm Parameter engines
                 */
                put("AlgorithmParameters.DSA",
                    "sun.security.provider.DSAParameters");
                put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.12", "DSA");
                put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1", "DSA");

                /*
                 * Key factories
                 */
                put("KeyFactory.DSA", "sun.security.provider.DSAKeyFactory");
                put("Alg.Alias.KeyFactory.1.3.14.3.2.12", "DSA");
                put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA");

                /*
                 * SecureRandom
                 */
                 put("SecureRandom.SHA1PRNG",
                     "sun.security.provider.SecureRandom");

                /*
                 * Certificates
                 */
                put("CertificateFactory.X509",
                    "sun.security.provider.X509Factory");
                put("Alg.Alias.CertificateFactory.X.509", "X509");

                /*
                 * KeyStore
                 */
                put("KeyStore.JKS", "sun.security.provider.JavaKeyStore");

                /*
                 * KeySize
                 */
                put("Signature.SHA1withDSA KeySize", "1024");
                put("KeyPairGenerator.DSA KeySize", "1024");
                put("AlgorithmParameterGenerator.DSA KeySize", "1024");

                /*
                 * Implementation type: software or hardware
                 */
                put("Signature.SHA1withDSA ImplementedIn", "Software");
                put("KeyPairGenerator.DSA ImplementedIn", "Software");
                put("MessageDigest.MD5 ImplementedIn", "Software");
                put("MessageDigest.SHA ImplementedIn", "Software");
                put("AlgorithmParameterGenerator.DSA ImplementedIn",
                    "Software");
                put("AlgorithmParameters.DSA ImplementedIn", "Software");
                put("KeyFactory.DSA ImplementedIn", "Software");
                put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
                put("CertificateFactory.X509 ImplementedIn", "Software");
                put("KeyStore.JKS ImplementedIn", "Software");

                return null;
            }
        });
    }
}

Appendix B: The SunJCE Provider Master Class

Below is an edited version of the SunJCE.java file, which contains a class named SunJCE that is the master class for the provider named SunJCE.

As with all master classes, this class is a subclass of Provider. It specifies the class names and package locations of all the cryptographic service implementations supplied by the SunJCE provider. This information is used by the getInstance methods of the engine classes to look up the various algorithms and other services when they are requested.

This code is supplied as an example of a provider master class.

/*
 * @(#)SunJCE.java      1.73 05/12/13
 *
 * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle or the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.sun.crypto.provider;

import java.security.*;
import java.security.cert.*;
import java.net.URL;
import java.io.ByteArrayInputStream;

/**
 * The "SunJCE" Cryptographic Service Provider.
 *
 * @author Jan Luehe
 * @author Sharon Liu
 *
 * @version 1.73, 12/13/05
 */

/**
 * Defines the "SunJCE" provider.
 *
 * Supported algorithms and their names:
 *
 * ...edited for space...
 *
 */

public final class SunJCE extends Provider {

    private static final String info = "SunJCE Provider " +
    "(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, "
    + "Diffie-Hellman, HMAC)";

    private static final String OID_PKCS5_MD5_DES = "1.2.840.113549.1.5.3";
    private static final String OID_PKCS3 = "1.2.840.113549.1.3.1";

    public SunJCE() {
        /* We are the "SunJCE" provider */
        super("SunJCE", 1.6d, info);

        final String BLOCK_MODES = "ECB|CBC|PCBC|CTR|CTS|CFB|OFB" +
            "|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64" +
            "|OFB8|OFB16|OFB24|OFB32|OFB40|OFB48|OFB56|OFB64";
        final String BLOCK_MODES128 = BLOCK_MODES +
            "|CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128" +
            "|OFB72|OFB80|OFB88|OFB96|OFB104|OFB112|OFB120|OFB128";
        final String BLOCK_PADS = "NOPADDING|PKCS5PADDING|ISO10126PADDING";

        AccessController.doPrivileged(new java.security.PrivilegedAction() {
                public Object run() {

                /*
                 * Cipher engines
                 */
                put("Cipher.RSA", "com.sun.crypto.provider.RSACipher");
                put("Cipher.RSA SupportedModes", "ECB");
                put("Cipher.RSA SupportedPaddings",
                        "NOPADDING|PKCS1PADDING|OAEPWITHMD5ANDMGF1PADDING"
                        + "|OAEPWITHSHA1ANDMGF1PADDING"
                        + "|OAEPWITHSHA-1ANDMGF1PADDING"
                        + "|OAEPWITHSHA-256ANDMGF1PADDING"
                        + "|OAEPWITHSHA-384ANDMGF1PADDING"
                        + "|OAEPWITHSHA-512ANDMGF1PADDING");
                put("Cipher.RSA SupportedKeyClasses",
                        "java.security.interfaces.RSAPublicKey" +
                        "|java.security.interfaces.RSAPrivateKey");

                put("Cipher.PBEWithMD5AndDES",
                    "com.sun.crypto.provider.PBEWithMD5AndDESCipher");
                put("Alg.Alias.Cipher.OID."+OID_PKCS5_MD5_DES,
                    "PBEWithMD5AndDES");
                put("Alg.Alias.Cipher."+OID_PKCS5_MD5_DES,
                    "PBEWithMD5AndDES");

                put("Cipher.AES", "com.sun.crypto.provider.AESCipher");
                put("Alg.Alias.Cipher.Rijndael", "AES");
                put("Cipher.AES SupportedModes", BLOCK_MODES128);
                put("Cipher.AES SupportedPaddings", BLOCK_PADS);
                put("Cipher.AES SupportedKeyFormats", "RAW");

                put("Cipher.AESWrap", "com.sun.crypto.provider.AESWrapCipher");
                put("Cipher.AESWrap SupportedModes", "ECB");
                put("Cipher.AESWrap SupportedPaddings", "NOPADDING");
                put("Cipher.AESWrap SupportedKeyFormats", "RAW");

                put("Cipher.ARCFOUR",
                    "com.sun.crypto.provider.ARCFOURCipher");
                put("Alg.Alias.Cipher.RC4", "ARCFOUR");
                put("Cipher.ARCFOUR SupportedModes", "ECB");
                put("Cipher.ARCFOUR SupportedPaddings", "NOPADDING");
                put("Cipher.ARCFOUR SupportedKeyFormats", "RAW");

                /*
                 *  Key(pair) Generator engines
                 */
                put("KeyGenerator.AES",
                    "com.sun.crypto.provider.AESKeyGenerator");
                put("Alg.Alias.KeyGenerator.Rijndael", "AES");

                put("KeyGenerator.ARCFOUR",
                    "com.sun.crypto.provider.KeyGeneratorCore$" +
                    "ARCFOURKeyGenerator");
                put("Alg.Alias.KeyGenerator.RC4", "ARCFOUR");

                put("KeyGenerator.HmacMD5",
                    "com.sun.crypto.provider.HmacMD5KeyGenerator");

                put("KeyGenerator.HmacSHA256",
                    "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA256KG");

                put("KeyPairGenerator.DiffieHellman",
                    "com.sun.crypto.provider.DHKeyPairGenerator");
                put("Alg.Alias.KeyPairGenerator.DH", "DiffieHellman");
                put("Alg.Alias.KeyPairGenerator.OID."+OID_PKCS3,
                    "DiffieHellman");
                put("Alg.Alias.KeyPairGenerator."+OID_PKCS3,
                    "DiffieHellman");

                /*
                 * Algorithm parameter generation engines
                 */
                put("AlgorithmParameterGenerator.DiffieHellman",
                    "com.sun.crypto.provider.DHParameterGenerator");
                put("Alg.Alias.AlgorithmParameterGenerator.DH",
                    "DiffieHellman");
                put("Alg.Alias.AlgorithmParameterGenerator.OID."+OID_PKCS3,
                    "DiffieHellman");
                put("Alg.Alias.AlgorithmParameterGenerator."+OID_PKCS3,
                    "DiffieHellman");

                /*
                 * Key Agreement engines
                 */
                put("KeyAgreement.DiffieHellman",
                    "com.sun.crypto.provider.DHKeyAgreement");
                put("Alg.Alias.KeyAgreement.DH", "DiffieHellman");
                put("Alg.Alias.KeyAgreement.OID."+OID_PKCS3, "DiffieHellman");
                put("Alg.Alias.KeyAgreement."+OID_PKCS3, "DiffieHellman");

                put("KeyAgreement.DiffieHellman SupportedKeyClasses",
                    "javax.crypto.interfaces.DHPublicKey" +
                    "|javax.crypto.interfaces.DHPrivateKey");

                /*
                 * Algorithm Parameter engines
                 */
                put("AlgorithmParameters.DiffieHellman",
                    "com.sun.crypto.provider.DHParameters");
                put("Alg.Alias.AlgorithmParameters.DH", "DiffieHellman");
                put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS3,
                    "DiffieHellman");
                put("Alg.Alias.AlgorithmParameters."+OID_PKCS3,
                    "DiffieHellman");

                put("AlgorithmParameters.PBEWithMD5AndDES",
                    "com.sun.crypto.provider.PBEParameters");
                put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS5_MD5_DES,
                    "PBEWithMD5AndDES");
                put("Alg.Alias.AlgorithmParameters."+OID_PKCS5_MD5_DES,
                    "PBEWithMD5AndDES");

                put("AlgorithmParameters.OAEP",
                    "com.sun.crypto.provider.OAEPParameters");

                /*
                 * Key factories
                 */
                put("KeyFactory.DiffieHellman",
                    "com.sun.crypto.provider.DHKeyFactory");
                put("Alg.Alias.KeyFactory.DH", "DiffieHellman");
                put("Alg.Alias.KeyFactory.OID."+OID_PKCS3,
                    "DiffieHellman");
                put("Alg.Alias.KeyFactory."+OID_PKCS3, "DiffieHellman");

                /*
                 * Secret-key factories
                 */
                put("SecretKeyFactory.PBEWithMD5AndDES",
                    "com.sun.crypto.provider.PBEKeyFactory$PBEWithMD5AndDES"
                    );
                put("Alg.Alias.SecretKeyFactory.OID."+OID_PKCS5_MD5_DES,
                    "PBEWithMD5AndDES");
                put("Alg.Alias.SecretKeyFactory."+OID_PKCS5_MD5_DES,
                    "PBEWithMD5AndDES");

                /*
                 * MAC
                 */
                put("Mac.HmacMD5", "com.sun.crypto.provider.HmacMD5");
                put("Mac.HmacSHA256",
                    "com.sun.crypto.provider.HmacCore$HmacSHA256");

                put("Mac.HmacMD5 SupportedKeyFormats", "RAW");
                put("Mac.HmacSHA256 SupportedKeyFormats", "RAW");

                /*
                 * KeyStore
                 */
                put("KeyStore.JCEKS", "com.sun.crypto.provider.JceKeyStore");

                return null;
            }
        });
    }
}
 

Appendix C: The java.security.properties File

Below is part of the java.security file that shows the default list of installed providers. It appears in every JRE installation. The file also contains other entries, but for brevity, we show only part of the file here. See the complete file at:

<java-home>/lib/security/java.security     [Solaris]
<java-home>\lib\security\java.security     [Win32]

Here <java-home> refers to the directory where the JRE was installed.

See Step 5 for an example of adding information about your provider to this file.

#
# This is the "master security properties file".
#
# In this file, various security properties are set for use by
# java.security classes. This is where users can statically register
# Cryptography Package Providers ("providers" for short). The term
# "provider" refers to a package or set of packages that supply a
# concrete implementation of a subset of the cryptography aspects of
# the Java Security API. A provider may, for example, implement one or
# more digital signature algorithms or message digest algorithms.
#
# Each provider must implement a subclass of the Provider class.
# To register a provider in this master security properties file,
# specify the Provider subclass name and priority in the format
#
#    security.provider.<n>=<className>
#
# This declares a provider, and specifies its preference
# order n. The preference order is the order in which providers are
# searched for requested algorithms (when no specific provider is
# requested). The order is 1-based; 1 is the most preferred, followed
# by 2, and so on.
#
# <className> must specify the subclass of the Provider class whose
# constructor sets the values of various properties that are required
# for the Java Security API to look up the algorithms or other
# facilities implemented by the provider.
#
# There must be at least one provider specification in java.security.
# There is a default provider that comes standard with the JDK. It
# is called the "SUN" provider, and its Provider subclass
# named Sun appears in the sun.security.provider package. Thus, the
# "SUN" provider is registered via the following:
#
#    security.provider.1=sun.security.provider.Sun
#
# (The number 1 is used for the default provider.)
#
# Note: Providers can be dynamically registered instead by calls to
# either the addProvider or insertProviderAt method in the Security
# class.

#
# List of providers and their preference orders (see above):
#

security.provider.1=sun.security.pkcs11.SunPKCS11 \
    ${java.home}/lib/security/sunpkcs11-solaris.cfg
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC

# Rest of file deleted
http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/HowToImplAProvider.html#Steps
 
Oracle and/or its affiliates
Java Technology

Copyright © 1993, 2011, Oracle and/or its affiliates. All rights reserved.

Contact Us

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics