4.2.2 扩充算法支持
对于Bouncy Castle提供的扩充算法支持,我们有两种方案可选:
1)配置方式。通过配置JRE环境,使其作为提供者(Provider)提供相应的算法支持,在代码实现层面只需指定要扩展的算法名称。
2)调用方式。在调用Java API初始化相应的密钥工厂、密钥生成器等引擎类之前,通过代码将Bouncy Castle提供者引入,获得扩展算法支持。
1.配置方式
配置Bouncy Castle并不复杂,有点类似于4.1节中权限文件的配置,需要在%JDK_Home%和%JRE_Home%目录中做相应调整。
我们以%JDK_Home%目录配置为例。
❑使用步骤
首先,我们需要修改配置文件(java.security)。
在第3章中提到配置%JDK_Home%\jre\lib\security\java.security文件,通过加入支持的方式获得更多的算法支持。
在这个文件中,我们可以很清晰地看到Java 6中有如下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
Java 7很快就要问世了,作者查看了该文件的相应配置,并无变化。
上述这些配置是按照以下方式来配置的:
security.provider.<n>=<className>
很显然,为了加入Bouncy Castle加密组件的安全提供者只需要这样做:
增加BouncyCastleProvider
security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
最后,我们需要将bcprov-ext-jdk16-143.jar文件导入。
切换至%JDK_Home%\jre\lib\ext目录下,我们能够看到sunjce_provider.jar这个文件。SunJCE就是由这个文件提供的。同理,要将Bouncy Castle加密组件扩展包导入其中,只需要将4.2.1节中获得的bcprov-ext-jdk16-143.jar文件放到这里即可。
%JRE_Home%目录的相应配置与上述%JDK_Home%目录配置相类似。
对应修改%JRE_Home%\lib\security\java.security文件,并将bcprov-ext-jdk16-143.jar文件放置到%JRE_Home%\lib\ext目录中即可。
❑应用举例
Java 6不支持MD4算法,做了上述配置后,如果要使用MD4算法可参考如下代码:
/**
*MD4加密
*@param data
*@return
*@throws Exception
*/
public static byte[]encodeMD4(byte[]data)throws Exception{
MessageDigest md=MessageDigest.getInstance("MD4");
md.update(data);
return md.digest();
}
这是一种对使用者透明的使用方式,你无须关心MD4算法的提供者是谁,代码很清晰。
2.调用方式
有时候,我们需要通过明显的代码调用方式引入支持者,这完全依赖于Security类的addProvider()方法,详见3.2节。
❑使用步骤
首先,我们需要将bcprov-jdk16-143.jar文件导入工程。相信读者对于这一步操作一定都不陌生,这里就不详细介绍了。
接着,我们需要将以下两个类导入(import)你的代码中:
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
当然,如果你使用Eclipse,可以在下述代码写完后,使用快捷键Ctrl+Shift+O直接导入所需类。
最后,我们只需要在初始化密钥工厂、密钥生成器等引擎类之前,调用如下代码:
//加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
或者,在初始化密钥工厂、密钥生成器等引擎类时,采用如下方式:
MessageDigest md=MessageDigest.getInstance("MD4","BC");
每个提供者都有简称,Bouncy Castle提供者简称“BC”,因此我们可以通过上述方式使用BouncyCastleProvider。
执行以下代码,我们可以获得Bouncy Castle提供者的算法详细描述。
Provider provider=Security.getProvider("BC");
System.err.println(provider);
for(Map.Entry<Object, Object>entry:provider.entrySet()){
System.err.println(entry.getKey()+"-"+entry.getValue());
}
在控制台中我们可以看到以下内容:
BC version 1.43
Alg.Alias.Signature.SHA224withCVC-ECDSA-SHA224WITHCVC-ECDSA
AlgorithmParameters.DES-org.bouncycastle.jce.provider.JDKAlgorithm
Parameters$IVAlgorithmParameters
KeyGenerator.2.16.840.1.101.3.4.22-org.bouncycastle.jce.provider.
symmetric.AES$KeyGen192
Alg.Alias.Cipher.RSA//ISO9796-1PADDING-RSA/ISO9796-1
AlgorithmParameterGenerator.NOEKEON-org.bouncycastle.jce.provider.
symmetric.Noekeon$AlgParamGen
Alg.Alias.Cipher.RSA//NOPADDING-RSA
Alg.Alias.Mac.IDEA-IDEAMAC
Alg.Alias.AlgorithmParameters.PBEWITHSHAAND3-KEYTRIPLEDES-PKCS12PBE
Alg.Alias.Mac.HMAC/SHA1-HMACSHA1
Alg.Alias.AlgorithmParameterGenerator.1.2.410.200004.1.4-SEED
AlgorithmParameterGenerator.ELGAMAL-org.bouncycastle.jce.provider.
JDKAlgorithmParameterGenerator$ElGamal
……
上述内容并未完全展现Bouncy Castle所支持的算法,本文做了简要摘录。
通常我们也可以通过上述方式检查系统支持的加密算法。
❑应用举例
Java 6未能支持MD4算法,也未能支持SHA-224算法。依照本文显式调用代码的方式,需要将bcprov-jdk16-143.jar文件导入工程,同时导入相关类(Security和BouncyCastleProvider),并通过Security类的addProvider()方法将BouncyCastleProvider类导入,见如下代码:
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
//……省略
/**
*SHA-224加密
*
*@param data
*@return
*@throws Exception
*/
public static byte[]encodeSHA224(byte[]data)throws Exception{
//加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
MessageDigest md=MessageDigest.getInstance("SHA-224");
md.update(data);
return md.digest();
}
多了几行代码,多少有点别扭。但这种方式让人心知肚明,很清楚自己使用了哪些类。
3.两种方式对比
配置和调用两种方法都有可取之处:前者对代码无需改动,只需提供Bouncy Castle支持的算法名称,但开发者需要知道Bouncy Castle已作为提供者部署在JRE中,也就是说这种方式需要依赖环境;后者需要对代码做改动,将Bouncy Castle作为提供者在代码中调用,但对环境依赖程度较小。
作者对于这两种方式并没有一个绝对的评价,它们各有特色。读者可根据需要,选择合适的方式获得扩展算法支持。
为了引起读者的注意,避免不必要的误导,本文在后续内容中将采用第2种方式介绍Bouncy Castle相关扩展算法。