3.2 java.security包详解

java. security包为安全框架提供类和接口。对该包有所了解的读者一定知道,这只是探索Java加密世界的第一步。通过该包中的Java实现,仅仅能够完成消息摘要算法的实现(消息摘要处理的MessageDigest、DigestInputStream和DigestOutputStream类),并且其源代码是可见的。而要实现真正的加密与解密实现,需要参考javax.crypto包中的内容。当然,这个包中的源代码内容是不可见的。

对于该包中与本书相关程度较少的Java API内容(如java.security.Permission类,与JAAS相关)本书不做介绍。如果读者对这些内容有兴趣,请参考相应的Java API的内容。

3.2.1 Provider

Provider类实现了Java安全性的一部分或全部,我们称它为提供者,如下所示:


//提供者抽象类

public abstract class Provider

extends Properties


Provider类可能实现的服务包括:

❑算法(如DSA、RSA、MD5或SHA-1)。

❑密钥的生成、转换和管理设施(如用于特定于算法的密钥)。

每个提供者都有一个名称和一个版本号,并且在它每次装入运行时中进行配置。

❑方法详述

在实际开发中,很少会直接使用Provider类,我们通常使用的是以下几种方法:


//返回此提供者的名称,如SunRsaSign表示该提供者的名称。

public String getName()

//返回此提供者的版本号,如1.5表示该提供者的版本号。

public double getVersion()

/返回此提供者的信息串。如Sun RSA signature provider表示这是一个用于RSA算法的数字签名提供者。/

public String getInfo()


Provider类覆盖了Object类的以下方法,用以输出自身提供者信息:


/返回包含此提供者的名称和版本号的字符串。如SunRsaSign version 1.5表示提供者名称为SunRsaSign,其版本号为1.5/

public String toString()


Provider类继承于Properties类,并覆盖了Properties类的几种常用方法。

我们先来看一下和线程安全相关的方法。

我们可以通过读取输入流的信息,载入提供者相关信息,如下所示:


//从输入流中读取属性列表(键和元素对)。

public synchronized void load(InputStream inStream)


我们也可以通过下述方法添加提供者相关信息:


//设置键属性,使其具有指定的值。

public synchronized Object put(Object key, Object value)


//将指定Map中所有映射关系复制到此提供者中。

public synchronized void putAll(Map<?,?>t)


我们可以通过如下方法获得当前提供者的相关信息:


//返回此提供者中所包含的属性项的一个不可修改的Set视图。

public synchronized Set<Map.Entry<Object, Object>>entrySet()


我们可以通过下述方法,清理提供者的相关信息:


//移除键属性(及其相应的值)

public synchronized Object remove(Object key)


如果使用如下方法,将清理掉有关提供者所支持的全部算法信息:


//清除此提供者,使其不再包含用来查找由该提供者实现的设施的属性。

public synchronized void clear()


接下来,我们来了解一下非线程安全相关的方法。

Provider类是Properties类的子类,提供了相应的键值操作方法。

以下两个方法均通过给定键获得相应的值:


//返回指定键所映射到的值,如果此映射不包含此键的映射,则返回null。

public Object get(Object key)

//用指定的键在此属性列表中搜索属性。

public String getProperty(String key)


以下两个方法可以用枚举的方式获得相应的键值信息:


//返回此散列表中的键的枚举。

public Enumeration<Object>keys()

//返回此散列表中的值的枚举。

public Enumeration<Object>elements()


通过以下方法可以获得集合方式的键值信息:


//返回此提供者中所包含的属性键的一个不可修改的Set视图。

public Set<Object>keySet()

//返回此提供者中所包含的属性值的一个不可修改的Collection视图。

public Collection<Object>values()


Provider类覆盖上述Properties类方法的目的在于确保程序有足够的权限执行相应的操作。这方面涉及安全管理器的概念,已超出本书所讨论的范畴,有兴趣的读者可以了解SecurityManager类,它位于java.lang包内。

自Java 5开始,Provider类中加入了内部类—Service类。Service类封装了服务的属性,并提供一个用于获得该服务的实现实例的工厂方法。以下为Provider类对Service类的调用支持:


//安全服务的描述。

public static class Provider.Service

//获取描述此算法或别名的指定类型的此提供者实现的服务。

public synchronized Provider.Service getService(String type, String algorithm)

//获取此提供者支持的所有服务的一个不可修改的Set。

public synchronized Set<Provider.Service>getServices()


在这里讲述Provider类,目的在于引导大家了解“提供者”这一概念,故不对Service类做过多讲述。在Java的安全提供者体系结构中,安全提供者可能不是来自Sun本身。不同的算法可能需要由不同的提供者提供,甚至其提供者本身属于第三方。图3-3是作者所使用的Java开发环境下的Provider类及其子类。

相信大家看到位于sun.security.provider包中的Sun类时并不感到陌生。当大家看到位于org.bouncycastle.jce.provider包中的BouncyCastleProvider类时,一定会感到有些疑惑。从包名结构来看,这不像是由Sun提供的JCE引擎提供者。没错,这是由第三方开源组织BouncyCastle(http://www.bouncycastle.org/)来提供的。有关于Bouncy Castle加密组件配置及使用,请参考本书第4章相关内容。

figure_0053_0021

图 3-3 Provier类及其子类

那么,在Java 6的环境中都有哪些提供者呢?

查看%JDK_HOME%\jre\lib\security目录,用记事本打开java.security文件。我们会发现这个Properties文件中可以找到以下9种安全提供者:


security.provider.1=sun.security.provider.Sun

security.provider.2=sun.security.rsa.SunRsaSign

security.provider.3=com.sun.net.ssl.internal.ssl.Provider

security.provider.4=com.sun.crypto.provider.SunJCE

security.provider.5=sun.security.jgss.SunProvider

security.provider.6=com.sun.security.sasl.Provider

security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI

security.provider.8=sun.security.smartcardio.SunPCSC

security.provider.9=sun.security.mscapi.SunMSCAPI


上述这些配置是按照以下方式来配置的:


security.provider.<n>=<className>


很显然,为了加入Bouncy Castle加密组件的安全提供者只需要这样做:


增加BouncyCastleProvider

security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider


有关如何配置Bouncy Castle加密组件,请参考本书第4章相关内容。Provider类的常用方法调用基本上是和Security类结合在一起的,有关Provider类方法的调用将在下一节中展示。