USBKEY全解析 |
您所在的位置:网站首页 › saab发动机号在哪里 › USBKEY全解析 |
网上资料关于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 |