bouncycastle中添加HMAC-SM3支持
一、
最近看完了PKCS#5中的内容,总结一下自己添加HMAC-SM3中遇到的问题和解决方法。
大概通读BC java源码以后,开始上手修改。
在SM3.java中添加如下代码:
/** * SM3 HashMac */ public static class HashMac extends BaseMac { public HashMac() { super(new HMac(new SM3Digest())); } } public static class KeyGenerator extends BaseKeyGenerator { public KeyGenerator() { super("HMACSM3", 256, new CipherKeyGenerator()); } } public static class Mappings extends DigestAlgorithmProvider { private static final String PREFIX = SM3.class.getName(); public Mappings() {} @Override public void configure(ConfigurableProvider provider) { addHMACAlgorithm(provider, "SM3", PREFIX + "$HashMac", PREFIX + "$KeyGenerator"); addHMACAlias(provider, "SM3", GMObjectIdentifiers.hmac_sm3); } }
直接修改BC源码有一个问题,就是打包后无法使用java信任的签名签证。
所以找新的方法。。。
二、
新建项目->
新建SM3.java文件
import org.bouncycastle.asn1.gm.GMObjectIdentifiers; import org.bouncycastle.crypto.CipherKeyGenerator; import org.bouncycastle.crypto.digests.SM3Digest; import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator; import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac; public class SM3 { private SM3() {} /** * SM3 HashMac */ public static class HashMac extends BaseMac { public HashMac() { super(new HMac(new SM3Digest())); } } public static class KeyGenerator extends BaseKeyGenerator { public KeyGenerator() { super("HMACSM3", 256, new CipherKeyGenerator()); } } public static class Mappings extends DigestAlgorithmProvider { private static final String PREFIX = SM3.class.getName(); public Mappings() {} @Override public void configure(ConfigurableProvider provider) { addHMACAlgorithm(provider, "SM3", PREFIX + "$HashMac", PREFIX + "$KeyGenerator"); addHMACAlias(provider, "SM3", GMObjectIdentifiers.hmac_sm3); } } }
新建DigestAlgorithmProvider.java文件
import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; import org.bouncycastle.jcajce.provider.util.AlgorithmProvider; abstract class DigestAlgorithmProvider extends AlgorithmProvider { protected void addHMACAlgorithm(ConfigurableProvider provider, String algorithm, String algorithmClassName, String keyGeneratorClassName) { String mainName = "HMAC" + algorithm; provider.addAlgorithm("Mac." + mainName, algorithmClassName); provider.addAlgorithm("Alg.Alias.Mac.HMAC-" + algorithm, mainName); provider.addAlgorithm("Alg.Alias.Mac.HMAC/" + algorithm, mainName); provider.addAlgorithm("KeyGenerator." + mainName, keyGeneratorClassName); provider.addAlgorithm("Alg.Alias.KeyGenerator.HMAC-" + algorithm, mainName); provider.addAlgorithm("Alg.Alias.KeyGenerator.HMAC/" + algorithm, mainName); } protected void addHMACAlias(ConfigurableProvider provider, String algorithm, ASN1ObjectIdentifier oid) { String mainName = "HMAC" + algorithm; provider.addAlgorithm("Alg.Alias.Mac." + oid, mainName); provider.addAlgorithm("Alg.Alias.KeyGenerator." + oid, mainName); } }
新建测试类HmacTest.java
import java.security.MessageDigest; import java.security.Security; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; public class HmacTest { static byte[] keyBytes = Hex.decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); static byte[] message = Hex.decode("4869205468657265"); public static void main(String[] args) throws Exception { BouncyCastleProvider bcp = new BouncyCastleProvider(); Security.addProvider(bcp); new SM3.Mappings().configure(bcp); for (String s : Security.getAlgorithms("Mac")) { if (s.contains("HMACSM3")) { System.out.println(true); break; } } HmacTest hmactest = new HmacTest(); hmactest.testHMac("HMAC-SM3"); } public void testHMac(String hmacName) throws Exception { SecretKey key = new SecretKeySpec(keyBytes, hmacName); byte[] out,out1; // SM3 MessageDigest sm3 = MessageDigest.getInstance("SM3", "BC"); out1 = sm3.digest(message); System.out.println(Hex.toHexString(out1)); // HMAC-SM3 Mac mac = Mac.getInstance(hmacName, "BC"); mac.init(key); mac.reset(); mac.update(message, 0, message.length); out = mac.doFinal(); System.out.println(Hex.toHexString(out)); } }
三、所有遇到的问题
1、abstract class DigestAlgorithmProvider
2、bcprov.jar不能放到java/jre/ext中,因为会loadSM3$Hmac.class,不然会报下面的exception。所以jar要和class使用相同的classloader。
Exception in thread "main" java.security.NoSuchAlgorithmException: class configured for Mac (provider: BC) cannot be found. at java.security.Provider$Service.getImplClass(Provider.java:1649) at java.security.Provider$Service.newInstance(Provider.java:1592) at sun.security.jca.GetInstance.getInstance(GetInstance.java:236) at javax.crypto.JceSecurity.getInstance(JceSecurity.java:103) at javax.crypto.Mac.getInstance(Mac.java:222) at cn.com.infosec.HmacSM3.HmacTest.testHMac(HmacTest.java:37) at cn.com.infosec.HmacSM3.HmacTest.main(HmacTest.java:30) Caused by: java.lang.ClassNotFoundException: com.gsealy.HmacSM3.SM3X$HashMac at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.security.Provider$Service.getImplClass(Provider.java:1636) ... 6 more
具体classloader可以看http://blog.csdn.net/xyang81/article/details/7292380