Loading

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);
    }
  }
View Code

直接修改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);
    }
  }

}
View Code

新建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);
  }
}
View Code

新建测试类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));
    
  }
}
View Code

三、所有遇到的问题

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
View Code

 

具体classloader可以看http://blog.csdn.net/xyang81/article/details/7292380

 

   

   

posted @ 2017-12-27 14:09  Gsealy  阅读(3716)  评论(0编辑  收藏  举报