- 論壇徽章:
- 0
|
java.security包為安全框架提供類(lèi)和接口。對(duì)該包有所了解的讀者一定知道,這只是探索Java加密世界的第一步。通過(guò)該包中的Java實(shí)現(xiàn),僅僅能夠完成消息摘要算法的實(shí)現(xiàn)(消息摘要處理的MessageDigest、DigestInputStream和DigestOutputStream類(lèi)),并且其源代碼是可見(jiàn)的。而要實(shí)現(xiàn)真正的加密與解密實(shí)現(xiàn),需要參考javax.crypto包中的內(nèi)容。當(dāng)然,這個(gè)包中的源代碼內(nèi)容是不可見(jiàn)的。對(duì)于該包中與本書(shū)相關(guān)程度較少的Java API內(nèi)容(如java.security.Permission類(lèi),與JAAS相關(guān))本書(shū)不做介紹。如果讀者對(duì)這些內(nèi)容有興趣,請(qǐng)參考相應(yīng)的Java API的內(nèi)容。
3.2.1 Provider
Provider類(lèi)實(shí)現(xiàn)了 Java 安全性的一部分或全部,我們稱(chēng)它為提供者,如下所示:
// 提供者抽象類(lèi)
public abstract class Provider
extends Properties
Provider類(lèi)可能實(shí)現(xiàn)的服務(wù)包括:
? 算法(如DSA、RSA、MD5或SHA-1)。
? 密鑰的生成、轉(zhuǎn)換和管理設(shè)施(如用于特定于算法的密鑰)。
每個(gè)提供者都有一個(gè)名稱(chēng)和一個(gè)版本號(hào),并且在它每次裝入運(yùn)行時(shí)中進(jìn)行配置。
? 方法詳述
在實(shí)際開(kāi)發(fā)中,很少會(huì)直接使用Provider類(lèi),我們通常使用的是以下幾種方法:
// 返回此提供者的名稱(chēng),如 SunRsaSign 表示該提供者的名稱(chēng)。
public String getName()
// 返回此提供者的版本號(hào),如1.5表示該提供者的版本號(hào)。
public double getVersion()
/* 返回此提供者的信息串。如Sun RSA signature provider表示這是一個(gè)
用于RSA算法的數(shù)字簽名提供者。*/
public String getInfo()
Provider類(lèi)覆蓋了Object類(lèi)的以下方法,用以輸出自身提供者信息:
/* 返回包含此提供者的名稱(chēng)和版本號(hào)的字符串。如SunRsaSign version 1.5
表示提供者名稱(chēng)為SunRsaSign,其版本號(hào)為1.5*/
public String toString()
Provider類(lèi)繼承于Properties類(lèi),并覆蓋了Properties類(lèi)的幾種常用方法。
我們先來(lái)看一下和線程安全相關(guān)的方法。
我們可以通過(guò)讀取輸入流的信息,載入提供者相關(guān)信息,如下所示:
// 從輸入流中讀取屬性列表(鍵和元素對(duì))。
public synchronized void load(InputStream inStream)
我們也可以通過(guò)下述方法添加提供者相關(guān)信息:
// 設(shè)置鍵屬性,使其具有指定的值。
public synchronized Object put(Object key, Object value)
// 將指定 Map 中所有映射關(guān)系復(fù)制到此提供者中。
public synchronized void putAll(Map<?,?> t)
我們可以通過(guò)如下方法獲得當(dāng)前提供者的相關(guān)信息:
// 返回此提供者中所包含的屬性項(xiàng)的一個(gè)不可修改的 Set 視圖。
public synchronized Set<Map.Entry<Object,Object>> entrySet()
我們可以通過(guò)下述方法,清理提供者的相關(guān)信息:
// 移除鍵屬性(及其相應(yīng)的值)
public synchronized Object remove(Object key)
如果使用如下方法,將清理掉有關(guān)提供者所支持的全部算法信息:
// 清除此提供者,使其不再包含用來(lái)查找由該提供者實(shí)現(xiàn)的設(shè)施的屬性。
public synchronized void clear()
接下來(lái),我們來(lái)了解一下非線程安全相關(guān)的方法。
Provider類(lèi)是Properties類(lèi)的子類(lèi),提供了相應(yīng)的鍵值操作方法。
以下兩個(gè)方法均通過(guò)給定鍵獲得相應(yīng)的值:
// 返回指定鍵所映射到的值,如果此映射不包含此鍵的映射,則返回 null。
public Object get(Object key)
// 用指定的鍵在此屬性列表中搜索屬性。
public String getProperty(String key)
以下兩個(gè)方法可以用枚舉的方式獲得相應(yīng)的鍵值信息:
// 返回此散列表中的鍵的枚舉。
public Enumeration<Object> keys()
// 返回此散列表中的值的枚舉。
public Enumeration<Object> elements()
通過(guò)以下方法可以獲得集合方式的鍵值信息:
// 返回此提供者中所包含的屬性鍵的一個(gè)不可修改的 Set 視圖。
public Set<Object> keySet()
// 返回此提供者中所包含的屬性值的一個(gè)不可修改的 Collection 視圖。
public Collection<Object> values()
Provider類(lèi)覆蓋上述Properties類(lèi)方法的目的在于確保程序有足夠的權(quán)限執(zhí)行相應(yīng)的操作。這
方面涉及安全管理器的概念,已超出本書(shū)所討論的范疇,有興趣的讀者可以了解SecurityManager
類(lèi),它位于java.lang包內(nèi)。
自Java 5開(kāi)始,Provider類(lèi)中加入了內(nèi)部類(lèi)—Service類(lèi)。Service類(lèi)封裝了服務(wù)的屬性,并
提供一個(gè)用于獲得該服務(wù)的實(shí)現(xiàn)實(shí)例的工廠方法。以下為Provider類(lèi)對(duì)Service類(lèi)的調(diào)用支持:
// 安全服務(wù)的描述。
public static class Provider.Service
// 獲取描述此算法或別名的指定類(lèi)型的此提供者實(shí)現(xiàn)的服務(wù)。
public synchronized Provider.Service getService(String type, String algorithm)
// 獲取此提供者支持的所有服務(wù)的一個(gè)不可修改的 Set。
public synchronized Set< rovider.Service> getServices()
在這里講述Provider類(lèi),目的在于引導(dǎo)大家了解“提供者”這一概念,故不對(duì)Service類(lèi)做
過(guò)多講述。在Java的安全提供者體系結(jié)構(gòu)中,安全提供者可能不是來(lái)自Sun本身。不同的算法
可能需要由不同的提供者提供,甚至其提供者本身屬于第三方。圖3-3是作者所使用的Java開(kāi)發(fā)
環(huán)境下的Provider類(lèi)及其子類(lèi)。
相信大家看到位于sun.security.provider包中的Sun類(lèi)時(shí)并不感到陌生。當(dāng)大家看到位于
org.bouncycastle.jce.provider包中的BouncyCastleProvider類(lèi)時(shí),一定會(huì)感到有些疑惑。從包名
結(jié)構(gòu)來(lái)看,這不像是由 Sun提供的 JCE引擎提供者。沒(méi)錯(cuò),這是由第三方開(kāi)源組織 Bouncy
Castle(http://www.bouncycastle.org/)來(lái)提供的。
那么,在Java 6的環(huán)境中都有哪些提供者呢?
java編程查看%JDK_HOME%\jre\lib\security目錄,用記事本打開(kāi)java.security文件。我們會(huì)發(fā)現(xiàn)這
個(gè)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
上述這些配置是按照以下方式來(lái)配置的:
security.provider.<n>=<className>
很顯然,為了加入Bouncy Castle加密組件的安全提供者只需要這樣做:
#增加BouncyCastleProvider
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
調(diào)用基本上是和Security類(lèi)結(jié)合在一起的,有關(guān)Provider類(lèi)方法的調(diào)用將在下一節(jié)中展示。
3.2.2 Security
Security類(lèi)的任務(wù)就是管理Java 程序中所用到的提供者類(lèi)。Security類(lèi)是一個(gè)終態(tài)類(lèi),除了
它的私有構(gòu)造方法,其余均為靜態(tài)方法。
// 管理提供者
public final class Security
extends Object
? 方法詳述
Security類(lèi)最主要的工作就是對(duì)提供者的管理。
我們可以通過(guò)如下方法向系統(tǒng)中追加一個(gè)新的提供者:
// 將提供者添加到下一個(gè)可用位置。在提供者數(shù)組尾部追加新的提供者。
public static int addProvider(Provider provider)
或者,我們直接指定這個(gè)提供者位于提供者列表中的位置,請(qǐng)看如下方法:
// 在指定的位置添加新的提供者。位置計(jì)數(shù)從1開(kāi)始。
public static int insertProviderAt(Provider provider, int position)
這里有一個(gè)優(yōu)先使用的問(wèn)題,也就是說(shuō)位置與優(yōu)先級(jí)成正比,提供者位置越靠前,優(yōu)先級(jí)
越高。
能夠向系統(tǒng)添加提供者,就能將其移除系統(tǒng),可以使用如下方法:
// 移除帶有指定名稱(chēng)的提供者。其余提供者在提供者數(shù)組中的位置將可能上移。
public static void removeProvider(String name)
當(dāng)然,移除時(shí)需要提供提供者的縮寫(xiě)名稱(chēng),如縮寫(xiě)B(tài)C指的是Bouncy Castle提供者。
與移除方法相類(lèi)似,從系統(tǒng)中獲得一個(gè)提供者可使用如下方法:
// 返回使用指定的名稱(chēng)安裝的提供者(如果有)。
public static Provider getProvider(String name)
當(dāng)然,也可以使用如下方法直接獲得全部提供者:
// 返回包含所有已安裝的提供者的數(shù)組(拷貝)。
public static Provider[] getProviders()
在獲得全部提供者的前提下,我們也可以對(duì)提供者做一些過(guò)濾,可使用如下方法:
/* 返回包含滿(mǎn)足指定的選擇標(biāo)準(zhǔn)的所有已安裝的提供者的數(shù)組(拷貝),如果尚未安裝此類(lèi)提供者,則返回 null。*/
public static Provider[] getProviders(Map<String,String> filter)
/* 返回包含滿(mǎn)足指定的選擇標(biāo)準(zhǔn)的所有已安裝的提供者的數(shù)組(拷貝),如果尚未安裝此類(lèi)提供者,則返回 null。*/
public static Provider[] getProviders(String filter)
大家對(duì)%JDK_HOME%\jre\lib\security\java.security文件中的配置應(yīng)該還有些印象吧?以下
方法可以用來(lái)設(shè)置該文件的相關(guān)配置:
//設(shè)置安全屬性值。
public static void setProperty(String key, String datum)
//獲取安全屬性值
public static String getProperty(String key)
要取到j(luò)ava.security文件中security.provider.1對(duì)應(yīng)的值(sun.security.provider.Sun),或者對(duì)
它進(jìn)行設(shè)置就可以使用上述方法來(lái)實(shí)現(xiàn)。
除此之外,我們還可以通過(guò)下述方法獲得指定加密服務(wù)所對(duì)應(yīng)的可用算法或類(lèi)型的名稱(chēng):
/* 返回Set視圖,這些Set視圖中的字符串包含了指定的 Java 加密服務(wù)的所有可用算法或類(lèi)型的名稱(chēng)(例
如,Signature、MessageDigest、Cipher、Mac、KeyStore)。*/
public static Set<String> getAlgorithms(String serviceName)
|
|