Monday, December 23, 2013

JCA - Java Cryptography Architecture Overview

JCA是Java关于加密解密以及方法摘要等一系列相关操作的API。JCA本身并不包含任何实现。它只是提供了API接口,供服务提供者进行实现。另一方面JCA又进行了服务的抽象。使得在开发过程中,不需要关心服务的具体实现。比如,我想使用SHA-256算法,对一段消息进行消息摘要。我只需要向JCA发出请求:“我需要一个实现了SHA-256算法的消息摘要服务对象”。JCA会根据特定的算法寻找对应实现了这个算法的服务类,并实例化其对象,返回给开发者。

在JCA中分别有几种不同的类:Engine类,SPI类,Provider类。一下会分别解释这几种类的作用以及关系。

Engine类
Engine类是供外部使用某种特定服务的类。比如,用于消息摘要的MessageDigest类;用于生成随机数的SecureRandom类;用于加密的Cipher类等等。它并不完成具体的功能,而是将所有的操作,通过方法调用的方式,转发到它所依赖的Spi类中,并由Spi类来完成功能。

在使用Engine类的时候有一些通用的规则:
  1. Engine类无法直接通过构造方法来实例化。只能通过调用其静态的getInstance方法获得实例。调用getInstance方法时,需要一个算法名称和一个可选的Provider。 
  2. 拿到Engine类的实例之后,可能需要调用它的Init方法(根据不同的Engine类可能有不同Init方法),对这个Engine对象进行初始化。不同的Engine类,需要不同的初始化参数。 
  3. 调用特定Engine相关的一些方法,执行需要的操作。这一步差异较大,具体情况,具体分析。(doFinal, digest 等...) 

SPI(Service Provider Interface) 类
提供某种服务的特定算法实现。他们都继承了对应的XxxSpi接口。比如,采用MD5算法进行消息摘要的MD5类和采用SHA256算法进行消息摘要的SHA2类,继承了MessageDigestSpi;采用AES算法进行数据加密的AESCipher类和采用DES算法进行数据加密的DESCipher类,继承了CipherSpi。
根据上面Engine类的描述,Engine类会把实际的操作委托给SPI类来完成。

Provider类
首先要区分下Provider和Provider类。实际上可以将Provider理解为一个或一组jar包。这些jar包中包含了一些实现好的SPI类。这些jar包可能是Java安装包中自带的,也可能是某些组织为了使用一些特定的算法,而自己开发的,也可能是从网上下载的第三方jar包。无论渠道是怎样的,每一组jar包就称为一个 Provider。那么Provider类就是用于描述和初始化这个Provide的。比如告知JCE这个Provide中提供了哪些服务,以及实现了特定服务的哪些算法等。因此每一组可以被称为Provider的jar包中,都会包含一个用于描述这个Provider的Provider类。

Engine/SPI/Provider之间的关系
  • Provider类描述了Provider本身(name, version...),以及它所包含的SPI,JCA会从Provider类中获取这些信息;
  • Engine类依赖于SPI类来完成功能,每一个Engine类内部都会有一个以Spi结尾的属性。Engine类就是通过这个对象来调用Spi中的方法的;
  • 当向JCA请求一个Engine时(调用getInstace),JCA会根据请求时的参数,并根据Provider类中提供的信息,找到对应的SPI类,并实例化之。将SPI对象装配到Engine对象中返回。从而供外部调用Engine类中的方法时,进行操作转发。
Built-in Provider
在JDK的安装文件中,包含了11个内置的Provider:SunPKCS11, SUN, SunRsaSign, SunJSSE, SunJCE, SunJGSS, SunSASL, XMLDSig, SunPCSC, SunMSCAPI, SunEC。关于每种Provider中提供了什么服务,请参见Java的官方文档

这就是JCA的一个简单的描述,只有正确理解了这个通用的架构,才能更好的理解Java Security。

No comments :

Post a Comment