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章相关内容。
图 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类方法的调用将在下一节中展示。