USBKEY全解析

您所在的位置:网站首页 saab发动机号在哪里 USBKEY全解析

USBKEY全解析

2023-11-24 02:46| 来源: 网络整理| 查看: 265

网上资料关于JAVA操作硬件USBKEY的例子比较少,本篇使用主要实现2个功能:

1    java实现向USBKEY导入证书

2    java调用USBKEY证书签名

对USBKEY陌生的同学请参考:https://blog.csdn.net/liujoi/article/details/106150546

本篇需要使用:bcpkix-jdk15on-160.jar、bcprov-ext-jdk15on-160.jar,完整源码见附件。

package org.liuy.pkcs11; import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.Provider; import java.security.SecureRandom; import java.security.Security; import java.security.Signature; import java.security.SignatureException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.List; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.ExtendedKeyUsage; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.x509.X509V3CertificateGenerator; import sun.misc.BASE64Encoder; import sun.security.pkcs11.SunPKCS11; import sun.security.pkcs11.wrapper.CK_ATTRIBUTE; import sun.security.pkcs11.wrapper.CK_INFO; import sun.security.pkcs11.wrapper.CK_SESSION_INFO; import sun.security.pkcs11.wrapper.CK_SLOT_INFO; import sun.security.pkcs11.wrapper.CK_TOKEN_INFO; import sun.security.pkcs11.wrapper.PKCS11; import sun.security.pkcs11.wrapper.PKCS11Constants; import sun.security.pkcs11.wrapper.PKCS11Exception; /**  * 使用PKCS11 对硬件USBKEY:下发证书、签名、打印硬件基本信息等功能  *   * @author liuy  *  */ public class Pkcs11Util {              protected PKCS11 myPKCS11Module_;       protected long token_ = -1L;          /**      * 初始化库文件,必须首先加载      * @param libPath    pkcs11库的路径:windows和linux都可以      * @throws IOException      * @throws PKCS11Exception      */     public Pkcs11Util(String libPath) throws IOException, PKCS11Exception     {         myPKCS11Module_ = PKCS11.getInstance(libPath, "C_GetFunctionList", null, false);      }          /**      * 获取Cryptoki的通用信息      * @throws PKCS11Exception      */     public CK_INFO getInfo()  throws PKCS11Exception     {             CK_INFO moduleInfo = myPKCS11Module_.C_GetInfo();             return moduleInfo;      }               /**      * 获取 槽信息      * @return      * @throws PKCS11Exception      */     public List getSlotInfo() throws PKCS11Exception    {           List  list= new ArrayList();           long[] slotIDs = myPKCS11Module_.C_GetSlotList(false);           for (int i=0; i < slotIDs.length; i++) {             CK_SLOT_INFO slotInfo = myPKCS11Module_.C_GetSlotInfo(slotIDs[i]);             list.add(slotInfo);           }           return list;     }           /**       * 获取硬件信息       * @return       * @throws PKCS11Exception       */      public List  getTokenInfo() throws PKCS11Exception      {         List  list= new ArrayList();          long[] tokenIDs = myPKCS11Module_.C_GetSlotList(true);         for (int i=0; i < tokenIDs.length; i++) {           CK_TOKEN_INFO tokenInfo = myPKCS11Module_.C_GetTokenInfo(tokenIDs[i]);           list.add(tokenInfo);           if (token_ == -1L) {               token_ = tokenIDs[i];             }         }         return list;      }          /**      * PKCS11 写入证书      * @param cert      * @param label      * @param id      * @return      * @throws PKCS11Exception       *       * @throws CertificateEncodingException       */     public void uploadCertificate(X509Certificate cert, String label, String id) throws PKCS11Exception, CertificateEncodingException {         long session_ = myPKCS11Module_.C_OpenSession(token_,PKCS11Constants.CKF_RW_SESSION | PKCS11Constants.CKF_SERIAL_SESSION, null, null);         CK_SESSION_INFO sessionInfo = myPKCS11Module_.C_GetSessionInfo(session_);         System.out.println(sessionInfo);                  CK_ATTRIBUTE[] certificate = new CK_ATTRIBUTE[9]; //        certificate[0] = new CK_ATTRIBUTE(PKCS11Constants.CKA_CLASS, PKCS11Constants.CKO_CERTIFICATE); //        certificate[1] = new CK_ATTRIBUTE(PKCS11Constants.CKA_TOKEN, true); //        certificate[2] = new CK_ATTRIBUTE(PKCS11Constants.CKA_PRIVATE, false); //        certificate[3] = new CK_ATTRIBUTE(PKCS11Constants.CKA_LABEL, label.toCharArray()); //        certificate[4] = new CK_ATTRIBUTE(PKCS11Constants.CKA_SUBJECT, cert.getSubjectX500Principal().getEncoded()); //        certificate[5] = new CK_ATTRIBUTE(PKCS11Constants.CKA_ID, StringUtil.hexStringToByte(id)); //        certificate[6] = new CK_ATTRIBUTE(PKCS11Constants.CKA_ISSUER, cert.getIssuerX500Principal().getEncoded()); //        certificate[7] = new CK_ATTRIBUTE(PKCS11Constants.CKA_SERIAL_NUMBER, cert.getSerialNumber().toByteArray()); //        certificate[8] = new CK_ATTRIBUTE(PKCS11Constants.CKA_VALUE, cert.getEncoded()); //        myPKCS11Module_.C_CreateObject(session_, certificate); //        myPKCS11Module_.C_CloseSession(token_);     }          /**      * 导入证书      * @param cfgPath   配置文件路径       * @param pin       USBKEY密码      * @throws InvalidKeyException      * @throws KeyStoreException      * @throws NoSuchAlgorithmException      * @throws CertificateException      * @throws NoSuchProviderException      * @throws SignatureException      * @throws IllegalStateException      * @throws IOException      */     public void  importCert(String  cfgPath,String pin) throws InvalidKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, NoSuchProviderException, SignatureException, IllegalStateException, IOException     {         Provider p = new SunPKCS11(cfgPath);         importCert(p,pin);     }               /***      *        * 导入证书,可以动态导入证书       * @param cfgPath   配置文件路径       * @param pin       USBKEY密码      * @throws InvalidKeyException      * @throws KeyStoreException      * @throws NoSuchAlgorithmException      * @throws CertificateException      * @throws NoSuchProviderException      * @throws SignatureException      * @throws IllegalStateException      * @throws IOException      */     public void  importCert(ByteArrayInputStream confStream,String pin) throws InvalidKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, NoSuchProviderException, SignatureException, IllegalStateException, IOException     {         Provider p = new SunPKCS11(confStream);         importCert(p,pin);     }               /**      * 使用sunPKCS11实现导入      * @param cfgPath   配置文件路径       * @param pin       USBKEY密码      * @throws KeyStoreException       * @throws IOException       * @throws CertificateException       * @throws NoSuchAlgorithmException       * @throws IllegalStateException       * @throws SignatureException       * @throws NoSuchProviderException       * @throws InvalidKeyException       */     private void  importCert(Provider p,String pin) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, InvalidKeyException, NoSuchProviderException, SignatureException, IllegalStateException     {          if (-1 == Security.addProvider(p)) {              throw new RuntimeException("could not add security provider");          }          //pin U盾的密码          char[] upin = pin.toCharArray();          KeyStore ks = KeyStore.getInstance("PKCS11", p);          ks.load(null, upin);          //产品密钥,一般使用PKCS10创建          SecureRandom sr = new SecureRandom();          KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", p);          keyGen.initialize(2048, sr);          KeyPair keyPair = keyGen.generateKeyPair();          PrivateKey pk = keyPair.getPrivate();          X509Certificate[] chain = generateV3Certificate(keyPair);          //alias 条目可以根据项目创建,这里防止不重复简单的获取时间          String alias=String.valueOf(System.currentTimeMillis());          ks.setKeyEntry(alias, pk,null, chain);          ks.store(null);                   System.out.println("OK");     }          /**      * USBKEY签名      * @param cfgPath  配置文件路径      * @param data     签名数据      * @param pin      UBKEY密码      * @throws KeyStoreException      * @throws NoSuchAlgorithmException      * @throws CertificateException      * @throws IOException      * @throws UnrecoverableKeyException      * @throws InvalidKeyException      * @throws SignatureException      */      public void  sign(String  cfgPath,String data,String pin) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException, InvalidKeyException, SignatureException     {         //CSP //        BouncyCastleProvider providerBC = new BouncyCastleProvider(); //        Security.addProvider(providerBC); //        SunMSCAPI providerMSCAPI = new SunMSCAPI(); //        Security.addProvider(providerMSCAPI); //        KeyStore ks = KeyStore.getInstance("Windows-MY","SunMSCAPI"); //        ks.load(null, null);                  //P11         SunPKCS11 providerMSCAPI = new SunPKCS11(cfgPath);         Provider a = providerMSCAPI;         Security.addProvider(a);                  KeyStore ks = KeyStore.getInstance("PKCS11");         ks.load(null, pin.toCharArray());                  Enumeration aliases = ks.aliases();         while (aliases.hasMoreElements())          {             String alias = aliases.nextElement();             System.out.println("alias:" + alias+":");                  X509Certificate x509 = (X509Certificate) ks.getCertificate(alias);             PrivateKey pk=(PrivateKey)ks.getKey(alias, null);             byte[]  pkBy=pk.getEncoded();                          // 构建签名             Signature signature = Signature.getInstance(x509.getSigAlgName());             signature.initSign(pk);             signature.update(data.getBytes());             byte[] sign=signature.sign();                          System.out.println(Base64.toBase64String(sign));         }     }          /**      * 生产证书      * @param pair      * @return      * @throws InvalidKeyException      * @throws NoSuchProviderException      * @throws SignatureException      * @throws CertificateEncodingException      * @throws IllegalStateException      * @throws NoSuchAlgorithmException      */     public  X509Certificate[] generateV3Certificate(KeyPair pair) throws InvalidKeyException, NoSuchProviderException, SignatureException, CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException {                  Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());         X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();         certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));         certGen.setIssuerDN(new X500Principal("CN=Test Certificate"));         certGen.setNotBefore(new Date(System.currentTimeMillis() - 10000));         certGen.setNotAfter(new Date(System.currentTimeMillis() + 10000));         certGen.setSubjectDN(new X500Principal("CN=Test Certificate"));         certGen.setPublicKey(pair.getPublic());         certGen.setSignatureAlgorithm("SHA256WithRSA");         certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));         certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment));         certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_serverAuth));         certGen.addExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(new GeneralName(GeneralName.rfc822Name, "[email protected]")));         X509Certificate[] chain = new X509Certificate[1];         chain[0] = certGen.generate(pair.getPrivate());         return chain;     }          public static void main(String[] args) throws Exception     {                String realPath = Pkcs11Util.class.getClassLoader().getResource("").getFile();        java.io.File file = new java.io.File(realPath);        realPath = file.getCanonicalPath();        String libPath=realPath+"/ShuttleCsp11_3003_15.dll";                  Pkcs11Util  p11=new Pkcs11Util(libPath);         CK_INFO ck_info=p11.getInfo();         System.out.println("接口版本号:"+ck_info.cryptokiVersion);         System.out.println("接口提供厂家:"+String.valueOf(ck_info.manufacturerID));         System.out.println();                  List slotList=p11.getSlotInfo();         for(int i=0; i < slotList.size(); i++)         {             CK_SLOT_INFO slot_info=slotList.get(i);             System.out.println("设备描述:"+String.valueOf(slot_info.slotDescription));              System.out.println("设备厂家:"+String.valueOf(slot_info.manufacturerID));              System.out.println("硬件标识:"+slot_info.flags);             System.out.println("硬件编号:"+slot_info.hardwareVersion);             System.out.println("固件版本:"+slot_info.hardwareVersion);             System.out.println();         }                  List tokenList=p11.getTokenInfo();         for(int i=0; i < tokenList.size(); i++)         {             CK_TOKEN_INFO token_info=tokenList.get(i);             System.out.println("应用标记:"+String.valueOf(token_info.label));              System.out.println("设备厂家:"+String.valueOf(token_info.manufacturerID));              System.out.println("设备类型:"+String.valueOf(token_info.model));             System.out.println("设备序列号:"+String.valueOf(token_info.serialNumber));             System.out.println("状态标识:"+token_info.flags);             System.out.println("最大会话数:"+token_info.ulMaxSessionCount);             System.out.println("当前会话数:"+token_info.ulSessionCount);             System.out.println("PIN最大长度:"+token_info.ulMaxPinLen);             System.out.println("PIN最小长度:"+token_info.ulMinPinLen);             System.out.println("PIN最小长度:"+token_info.ulMinPinLen);             System.out.println("公有区域总空间:"+token_info.ulTotalPublicMemory);             System.out.println("公有区域剩余空间:"+token_info.ulFreePublicMemory);             System.out.println("私有区域总空间:"+token_info.ulTotalPrivateMemory);             System.out.println("私有区域剩余空间:"+token_info.ulFreePrivateMemory);             System.out.println("硬件版本:"+token_info.hardwareVersion);             System.out.println();         }                      //测试KEY用的是:飞天诚信epass3003的标准产品           //淘宝地址:https://detail.tmall.com/item.htm?id=43722580737           StringBuffer setP11Conf=new StringBuffer();           setP11Conf.append("name=epass3003 \n");           //如果是linux,对应加载so文件           setP11Conf.append("library="+libPath+" \n");           //电脑上插了多个的时候需要重新设置           setP11Conf.append("slot=1 \n");           setP11Conf.append("attributes(generate, *, *) = { CKA_TOKEN = true }  \n");           setP11Conf.append("attributes(generate, CKO_CERTIFICATE, *) = { CKA_PRIVATE = false }  \n");           setP11Conf.append("attributes(generate, CKO_PUBLIC_KEY, *) = { CKA_PRIVATE = false }  \n");                   byte[] pkcs11ConfigBytes = setP11Conf.toString().getBytes();           ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11ConfigBytes); //          p11.importCert(confStream, "123456");                      String cfgPath=realPath+"/epass3003.cfg";           p11.sign(cfgPath, "123", "123456");     } }

实际项目中,u盾生产PKCS10请求给CA公司,再由CA公司颁发证书导入;应用的时候可以先记录alias生产P10之后,获取证书在根据alias导入

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3