jca使用_使用JCA的密码学–提供者中的服务

jca使用

Java密码体系结构(JCA)是一个可扩展的框架,使您能够使用执行加密操作。 JCA还促进实现独立性(程序不应该在乎谁提供加密服务)和实现互操作性(程序不应该与特定加密服务的特定提供者联系在一起)。

JCA允许将众多密码服务(例如密码,密钥生成器,消息摘要)捆绑到java.security.Provider类中,并声明式地注册在特殊文件(java.security)中,或者通过java.security.Security类以编程方式进行注册(方法'addProvider')。

尽管JCA是标准,但是不同的JDK实施JCA的方式有所不同。 在Sun / Oracle和IBM JDK之间,IBM JDK比Oracle更“有序”。 例如,IBM的超级提供程序(com.ibm.crypto.provider.IBMJCE)实现以下密钥库格式:JCEKS,PKCS12KS(PKCS12),JKS。 Oracle JDK将密钥库格式实现“传播”到以下提供程序中:

  • sun.security.provider.Sun – JKS
  • com.sun.crypto.provider.SunJCE – JCEKS
  • com.sun.net.ssl.internal.ssl.Provider – PKCS12

尽管流行的建议是编写不指向特定Provider类的应用程序,但是在某些用例中,需要应用程序/程序确切了解Provider类提供的服务。 当支持可能与特定JDK(例如与IBM JDK捆绑在一起的WebSphere)紧密耦合的多个应用程序服务器时,此要求变得更加普遍。 我通常使用Tomcat + Oracle JDK进行开发(更轻便,更快),但是我的测试/生产设置是WebSphere + IBM JDK。 为了使事情更加复杂,我的项目需要使用硬件安全模块(HSM),该模块通过提供程序类com.ncipher.provider.km.nCipherKM使用JCA API。 因此,当我在家时(无法访问HSM),我想继续编写代码,但至少要在JDK提供程序上对代码进行测试。 然后,在将代码提交到源代码管理之前,我可以切换为使用nCipherKM提供程序进行另一轮单元测试。

通常的假设是,一个提供程序类就足够了,例如对于IBM JDK来说是IBMJCE,对于Oracle JDK是SunJCE。 因此,通常的解决方案是实现一个指定一个提供程序的类,并使用反射来避免由于“未找到类”而导致的编译错误:

//For nShield HSM
Class c = Class.forName('com.ncipher.provider.km.nCipherKM');
Provider provider = (Provider)c.newInstance();

//For Oracle JDK
Class c = Class.forName('com.sun.crypto.provider.SunJCE');
Provider provider = (Provider)c.newInstance();

//For IBM JDK
Class c = Class.forName('com.ibm.crypto.provider.IBMJCE');
Provider provider = (Provider)c.newInstance();

这种设计是可以的,直到遇到在Oracle JDK上运行某些单元测试用例的NoSuchAlgorithmException错误。 我使用的算法是RSA,这是一种常见算法! 怎么可能,文档说支持RSA! 相同的测试用例在IBM JDK上运行良好。

经过进一步的调查,我感到非常沮丧的是,SunJCE提供程序没有用于RSA的KeyPairGenerator服务的实现。 但是,可以在提供程序类sun.security.rsa.SunRsaSign中找到实现。 因此,“ 1提供者全部提供”的假设被打破了。 但是由于有了JCA的开放API,在请求Service实例时可以传递Provider对象,例如

KeyGenerator kgen = KeyGenerator.getInstance('AES', provider);

为了帮助检查各种Provider对象,我提供了一个JUnit测试,以漂亮地打印出JDK中每个已注册Provider实例的各种服务。

package org.gizmo.jca;

import java.security.Provider;
import java.security.Provider.Service;
import java.security.Security;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.crypto.KeyGenerator;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test;

public class CryptoTests {

 @Test
 public void testBouncyCastleProvider() throws Exception {
  Provider p = new BouncyCastleProvider();
  String info = p.getInfo();
  System.out.println(p.getClass() + ' - ' + info);
  printServices(p);
 }

 @Test
 public void testProviders() throws Exception {

  Provider[] providers = Security.getProviders();
  for(Provider p : providers) {
   String info = p.getInfo();
   System.out.println(p.getClass() + ' - ' + info);
   printServices(p);
  }
 }

 private void printServices(Provider p) {
  SortedSet

                       services = new TreeSet

                       (new ProviderServiceComparator());
  services.addAll(p.getServices());

  for(Service service : services) {
   String algo = service.getAlgorithm();
   System.out.println('==> Service: ' + service.getType() + ' - ' + algo);
  }
 }

 /**
  * This is to sort the various Services to make it easier on the eyes...
  */
 private class ProviderServiceComparator implements Comparator

                         {

  @Override
  public int compare(Service object1, Service object2) {
   String s1 = object1.getType() + object1.getAlgorithm();
   String s2 = object2.getType() + object2.getAlgorithm();;

   return s1.compareTo(s2);
  }

 }
}

无论如何,如果您使用的算法是通用的并且足够强大,可以满足您的需求,那么可以使用BouncyCastle提供程序。 它在所有JDK(针对IBM和Oracle进行了测试)上都能很好地工作。 BouncyCastle不支持JKS或JCEKS密钥库格式,但是如果您不太挑剔,则BC密钥库格式可以正常工作。 BouncyCastle也是开源的,可以免费包含在您的应用程序中。

提示 :JKS密钥库无法存储SecretKeys。 您可以尝试做功课

希望本文能启发您进一步探索JCA,或者至少在与JCA合作时意识到“幸福的无知”的陷阱。

参考: YK研讨会的博客中, 使用JCA的密码学-来自我们JCG合作伙伴 Allen Julia的“ 提供者中的服务”

翻译自: https://www.javacodegeeks.com/2013/03/cryptography-using-jca-services-in-providers.html

jca使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值