java生成pfx证书[通俗易懂]

2022-09-06 11:34:48 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。package com.zrsf.cert;

import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Vector; import java.util.Map.Entry;

import sun.security.util.ObjectIdentifier; import sun.security.x509.AlgorithmId; import sun.security.x509.CertAndKeyGen; import sun.security.x509.CertificateAlgorithmId; import sun.security.x509.CertificateExtensions; import sun.security.x509.CertificateSerialNumber; import sun.security.x509.CertificateValidity; import sun.security.x509.CertificateVersion; import sun.security.x509.CertificateX509Key; import sun.security.x509.ExtendedKeyUsageExtension; import sun.security.x509.KeyIdentifier; import sun.security.x509.KeyUsageExtension; import sun.security.x509.SerialNumber; import sun.security.x509.SubjectKeyIdentifierExtension; import sun.security.x509.X500Name; import sun.security.x509.X500Signer; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertInfo;

public class GenX509Cert {

private SecureRandom sr = new SecureRandom();

private String root = “Root”;// 根证书前缀 private static String rootUser = “签名服务器”;// 证书颁发者

public GenX509Cert() { try { sr = SecureRandom.getInstance(“SHA1PRNG”, “SUN”); } catch (Exception e) { System.err.println(“实例化SecureRandom出错:” e.getMessage()); } }

public void createCert(X509Certificate certificate, PrivateKey rootPrivKey, KeyPair kp, String certPath, String user, String password, String sbh, String ip) throws Exception { byte certbytes[] = certificate.getEncoded(); X509CertImpl x509certimpl = new X509CertImpl(certbytes);

X509CertInfo x509certinfo = (X509CertInfo) x509certimpl .get(“x509.info”);

x509certinfo.set(“key”, new CertificateX509Key(kp.getPublic()));

CertificateExtensions certificateextensions = new CertificateExtensions(); certificateextensions.set(“SubjectKeyIdentifier”, new SubjectKeyIdentifierExtension((new KeyIdentifier(kp .getPublic())).getIdentifier())); x509certinfo.set(“extensions”, certificateextensions);

// 设置issuer域 X500Name issuer = new X500Name(“CN=” rootUser “,OU=hackwp,O=wp,L=BJ,S=BJ,C=CN”); x509certinfo.set(“issuer.dname”, issuer); X500Name subject = new X500Name(“CN=” user “, OU=wps, O=wps, L=BJ, ST=BJ, C=CN”); x509certinfo.set(“subject.dname”, subject);

Signature signature = Signature.getInstance(“MD5WithRSA”); signature.initSign(kp.getPrivate()); X500Signer signer = new X500Signer(signature, issuer);

AlgorithmId algorithmid = signer.getAlgorithmId(); x509certinfo .set(“algorithmID”, new CertificateAlgorithmId(algorithmid));

Date bdate = new Date(); Date edate = new Date(); // 天 小时 分 秒 毫秒 edate.setTime(bdate.getTime() 3650L * 24L * 60L * 60L * 1000L); // validity为有效时间长度 单位为秒 CertificateValidity certificatevalidity = new CertificateValidity( bdate, edate); x509certinfo.set(“validity”, certificatevalidity); // 设置有效期域(包含开始时间和到期时间)域名等同与x509certinfo.VALIDITY x509certinfo.set(“serialNumber”, new CertificateSerialNumber( (int) (new Date().getTime() / 1000L))); // 设置序列号域 CertificateVersion cv = new CertificateVersion(CertificateVersion.V3); x509certinfo.set(X509CertInfo.VERSION, cv); // 设置版本号 只有v1 ,v2,v3这几个合法值 /** *以上是证书的基本信息 如果要添加用户扩展信息 则比较麻烦 首先要确定version必须是v3否则不行 然后按照以下步骤 **/

String userData = “Digital Signature, Non-Repudiation, Key Encipherment, Data Encipherment (f0)”;

byte l = (byte) userData.length();// 数据总长17位 byte f = 0x04; byte[] bs = new byte[userData.length() 2]; bs[0] = f; bs[1] = l; for (int i = 2; i < bs.length; i ) { bs[i] = (byte) userData.charAt(i – 2); }

KeyUsageExtension keyUsage = new KeyUsageExtension(); keyUsage.set(KeyUsageExtension.DIGITAL_SIGNATURE, true); keyUsage.set(KeyUsageExtension.NON_REPUDIATION, true); keyUsage.set(KeyUsageExtension.KEY_ENCIPHERMENT, true); keyUsage.set(KeyUsageExtension.DATA_ENCIPHERMENT, true);

// 增强密钥用法 ObjectIdentifier ekeyOid = new ObjectIdentifier(new int[] { 1, 3, 6, 1, 5, 5, 7, 3, 3 }); Vector<ObjectIdentifier> vkeyOid = new Vector<ObjectIdentifier>(); vkeyOid.add(ekeyOid); ExtendedKeyUsageExtension exKeyUsage = new ExtendedKeyUsageExtension( vkeyOid);

CertificateExtensions exts = new CertificateExtensions();

exts.set(“keyUsage”, keyUsage); exts.set(“extendedKeyUsage”, exKeyUsage);

// 如果有多个extension则都放入CertificateExtensions 类中, x509certinfo.set(X509CertInfo.EXTENSIONS, exts);

X509CertImpl x509certimpl1 = new X509CertImpl(x509certinfo); SerialNumber sn = new SerialNumber(new BigInteger(ip System.currentTimeMillis())); x509certimpl1.set(X509CertImpl.SERIAL_ID, sn);// 设置证书序列号 x509certimpl1.sign(rootPrivKey, “MD5WithRSA”);// 使用另一个证书的私钥来签名此证书 这里使用 // md5散列 用rsa来加密 Certificate[] certChain = { x509certimpl1 }; savePfx(Util.certCA, kp.getPrivate(), password, certChain, certPath);

// 生成文件 x509certimpl1.verify(certificate.getPublicKey(), null); }

/** * 保存pfx文件,里面包括公钥,私钥,证书链别名 * * @param alias * @param privKey * @param pwd * @param certChain * @param filepath * @throws Exception */ public void savePfx(String alias, PrivateKey privKey, String pwd, Certificate[] certChain, String filepath) throws Exception { FileOutputStream out = null; try { KeyStore outputKeyStore = KeyStore.getInstance(“pkcs12”); outputKeyStore.load(null, pwd.toCharArray()); outputKeyStore.setKeyEntry(alias, privKey, pwd.toCharArray(), certChain); out = new FileOutputStream(filepath); outputKeyStore.store(out, pwd.toCharArray()); } finally { if (out != null) out.close(); }

}

/** * 生成用户证书 * * @param sbh * 纳税人识别号(文件名,不包含后缀) * @param user * 证书使用者 * @param path * 证书保存路径(不包括文件名),如要保存在D盘的home目录下则输入:D:/home * @param password * 证书密码 * @param ip * 客户端请求的ip * @return map里面包含两个key,一个code,一个msg,如果code等于0000则为生成成功,如果code不等于0000则为生成失败, * msg里面保存失败原因 */ public Map<String, String> createCA(String sbh, String user, String path, String password, String ip) { Map<String, String> map = new HashMap<String, String>(); if (sbh == null || “”.equals(sbh)) { map.put(“code”, “-1”); map.put(“msg”, “纳税人识别号不能为空”); return map; } if (user == null || “”.equals(user)) { map.put(“code”, “-1”); map.put(“msg”, “证书使用者不能为空”); return map; } if (path == null || “”.equals(path)) { map.put(“code”, “-1”); map.put(“msg”, “保存路径不能为空”); return map; } if (password == null || “”.equals(password)) { map.put(“code”, “-1”); map.put(“msg”, “证书密码不能为空”); return map; } if (!Util.ipCheck(ip)) {// 验证IP地址是否合法 map.put(“code”, “-1”); map.put(“msg”, “IP地址不合法”); return map; } if(!new File(path).exists()){ map.put(“code”, “5555”); map.put(“msg”, “保存文件的目录不存在”); return map; } String rootPath = path File.separator root sbh “.pfx”; String certPath = path File.separator sbh “.pfx”; File file = new File(rootPath); if (file.exists()) { map.put(“code”, “6666”); map.put(“msg”, “文件已存在”); return map; } try { CertAndKeyGen cak = new CertAndKeyGen(“RSA”, “MD5WithRSA”, null); // 参数分别为 公钥算法 签名算法 providername(因为不知道确切的 只好使用null 既使用默认的provider) cak.generate(1024); cak.setRandom(sr); // 生成一对key 参数为key的长度 对于rsa不能小于512 X500Name subject = new X500Name( “CN=root,OU=root,O=wp,L=BJ,S=BJ,C=CN”); // subject name X509Certificate certificate = cak.getSelfCertificate(subject, new Date(), 365L * 24L * 60L * 60L * 1000L * 5L);

X509Certificate[] certs = { certificate };

savePfx(Util.rootCA, cak.getPrivateKey(), password, certs, rootPath); ip = Util.getIpNum(ip); signCert(rootPath, certPath, user, password, sbh, ip); map.put(“code”, “0000”); map.put(“msg”, “用户证书生成成功”); return map; } catch (Exception e) { if (file != null) { file.delete(); } File file2 = new File(certPath); if (file2.exists()) file2.delete(); map.put(“code”, “9999”); map.put(“msg”, “生成用户证书发生异常:” e.getMessage()); return map; } }

/** * * @param rootPath * 根证书路径 * @param certPath * 用户证书路径 * @param user * 证书使用者 * @param password * 证书密码 * @param sbh * 纳税人识别号 * @param ip * 请求地址的ip * @throws Exception */ public void signCert(String rootPath, String certPath, String user, String password, String sbh, String ip) throws Exception { FileInputStream ksfis = null; try { KeyStore ks = KeyStore.getInstance(“pkcs12”);

ksfis = new FileInputStream(rootPath); char[] storePwd = password.toCharArray(); char[] keyPwd = password.toCharArray();

ks.load(ksfis, storePwd);

// 从密钥仓库得到私钥 PrivateKey privK = (PrivateKey) ks.getKey(Util.rootCA, keyPwd);

X509Certificate certificate = (X509Certificate) ks .getCertificate(Util.rootCA);

createCert(certificate, privK, genKey(), certPath, user, password, sbh, ip); } finally { if (ksfis != null) ksfis.close(); } }

public KeyPair genKey() throws NoSuchAlgorithmException { KeyPairGenerator kpg = KeyPairGenerator.getInstance(“RSA”); kpg.initialize(1024, sr); KeyPair kp = kpg.generateKeyPair(); return kp; }

/** * 获取证书序列号和公钥 * * @param path * 证读取证书的路径 * @param pass * 读取证书的密码 * @return */ public Map<String, String> getCertMessage(String path, String pass) { Map<String, String> map = new HashMap<String, String>(); KeyStore ks; FileInputStream fis = null; if (pass == null || “”.equals(pass) || path == null || “”.equals(path)) { map.put(“code”, “-1”); map.put(“msg”, “参数错误”); return map; } try { ks = KeyStore.getInstance(“PKCS12”); fis = new FileInputStream(path);

char[] nPassword = null; if ((pass == null) || pass.trim().equals(“”)) { nPassword = null; } else { nPassword = pass.toCharArray(); } ks.load(fis, nPassword);

X509Certificate cert = (X509Certificate) ks .getCertificate(Util.certCA); PublicKey pubkey = cert.getPublicKey();

byte pb[] = Serializer.serialize(pubkey); map.put(“code”, “0000”); map.put(“msg”, “数据返回成功”); map.put(“certNumber”, cert.getSerialNumber().toString()); map.put(“cert”, Base64Utils.encode(pb)); return map; } catch (FileNotFoundException e) { map.put(“code”, “1111”); map.put(“msg”, “文件没有找到:” e.getMessage()); return map; } catch (CertificateException e) { map.put(“code”, “2222”); map.put(“msg”, “读取证书异常:” e.getMessage()); return map; } catch (IOException e) { map.put(“code”, “4444”); map.put(“msg”, “IO异常:” e.getMessage()); return map; } catch (Exception e) { map.put(“code”, “9999”); map.put(“msg”, “未知异常:” e.getMessage()); return map; }finally{ if(fis!=null) try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } }

/** * 签名数据 * * @param path * 读取证书路径 * @param pass * 读取证书密码 * @param data * 待签名数据 * @return */ public Map<String, String> signData(String path, String pass, String data) { Map<String, String> map = new HashMap<String, String>(); KeyStore ks; FileInputStream fis = null; if (pass == null || “”.equals(pass) || path == null || “”.equals(path) || data == null || “”.equals(data)) { map.put(“code”, “-1”); map.put(“msg”, “参数错误”); return map; } try { ks = KeyStore.getInstance(“PKCS12”);

fis = new FileInputStream(path);

char[] nPassword = null; if ((pass == null) || pass.trim().equals(“”)) { nPassword = null; } else { nPassword = pass.toCharArray(); } ks.load(fis, nPassword); X509Certificate cert = (X509Certificate) ks.getCertificate(Util.certCA);

PrivateKey prikey = (PrivateKey) ks.getKey(Util.certCA, nPassword);

Signature sig = Signature.getInstance(“MD5WithRSA”); sig.initSign(prikey); sig.update(data.getBytes(“UTF-8”)); byte b[] = sig.sign(); map.put(“code”, “0000”); map.put(“msg”, “数据返回成功”); map.put(“certNumber”, cert.getSerialNumber().toString()); map.put(“sign”, Base64Utils.encode(b)); return map; } catch (FileNotFoundException e) { map.put(“code”, “1111”); map.put(“msg”, “文件没有找到:” e.getMessage()); return map; } catch (CertificateException e) { map.put(“code”, “2222”); map.put(“msg”, “读取证书异常:” e.getMessage()); return map; } catch (NoSuchAlgorithmException e) { map.put(“code”, “2222”); map.put(“msg”, “读取证书异常:” e.getMessage()); return map; } catch (SignatureException e) { map.put(“code”, “3333”); map.put(“msg”, “签名异常:” e.getMessage()); return map; } catch (IOException e) { map.put(“code”, “4444”); map.put(“msg”, “IO异常:” e.getMessage()); return map; } catch (Exception e) { map.put(“code”, “9999”); map.put(“msg”, “未知异常:” e.getMessage()); return map; } finally { if (fis != null) try { fis.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } }

public void verify(String key,String sign,String signData) throws Exception{ byte []pb = Base64Utils.decode(key); PublicKey pk = (PublicKey) Serializer.unserialize(pb); Signature sig2=Signature.getInstance(“MD5WithRSA”); sig2.initVerify(pk); sig2.update(sign.getBytes(“UTF-8”)); System.out.println(“验签结果是:” sig2.verify(Base64Utils.decode(signData))); } public static void main(String[] args) { try { GenX509Cert gcert = new GenX509Cert(); String data = “adowdn@#&kajdk”; Map<String, String> map = gcert.createCA(“133456”, “小科”, “e:”, “123456”, “10.26.27.28”); System.out.println(map.get(“code”) “t” map.get(“msg”)); Map<String, String> map1 = gcert.getCertMessage(“e:/133456.pfx”, “123456”); for (Entry<String, String> e : map1.entrySet()) { System.out.println(e.getKey() “–>” e.getValue()); } Map<String, String> map2 = gcert.signData(“e:/133456.pfx”, “123456”, data); for (Entry<String, String> e : map2.entrySet()) { System.out.println(e.getKey() “–>” e.getValue()); } gcert.verify(map1.get(“cert”), data, map2.get(“sign”)); } catch (Exception e) { e.printStackTrace(); } }

}

package com.zrsf.cert;

import java.io.IOException;

import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder;

public class Base64Utils { /** * 解码 * @param requestString * @return * @throws IOException */ public static byte[] decode(String requestString) throws IOException{ return new BASE64Decoder().decodeBuffer(requestString); }

/* * 编码 */ public static String encode(byte[] bytes) throws IOException{ BASE64Encoder enc = new BASE64Encoder(); String encStr =enc.encode(bytes); return encStr; }

}

package com.zrsf.cert;

import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream;

/** * * @ClassName Serializer */ public final class Serializer { /** * 序列化。 * @param object 需要序列化的对象。 * @return 字节数组。 */ public static final byte[] serialize(Object object) { ObjectOutputStream oos = null; ByteArrayOutputStream baos = null; try { baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(object); return baos.toByteArray(); } catch(Exception ex) { System.err.println(“序列化对象失败”); } finally { if(oos != null) { try { oos.close(); }catch (IOException e) { e.printStackTrace(); } } if(baos != null) { try { baos.close(); }catch (IOException e) { e.printStackTrace(); } } } return null; }

/** * 反序列化。 * @param bytes 字节数组。 * @return 反序列化后的对象。 */ public static final Object unserialize(byte[] bytes) { ByteArrayInputStream bais = null; ObjectInputStream ois = null; try { bais = new ByteArrayInputStream(bytes); ois = new ObjectInputStream(bais); return ois.readObject(); } catch(Exception ex) { System.err.println(“反序列化对象失败”); } finally { if(ois != null) { try { ois.close(); }catch (IOException e) { e.printStackTrace(); } } if(bais != null) { try { bais.close(); }catch (IOException e) { e.printStackTrace(); } } } return null; } }

package com.zrsf.cert;

import java.security.SecureRandom;

public class Util {

public static String rootCA = “RootCA”; public static String certCA = “client”;

/** * 生成三位随机数 * @return */ public static String getRandomNum(){ SecureRandom sr = new SecureRandom(); return “” sr.nextInt(10) sr.nextInt(10) sr.nextInt(10); }

/** * 验证ip是否合法 * @param ip ip地址 * @return ip合法返回true,否则返回false */ public static boolean ipCheck(String ip) { if (ip != null && !ip.isEmpty()) { String regex = “^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|[1-9])\.” “(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.” “(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.” “(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|[1-9])$”; if (ip.matches(regex)) { return true; } else { return false; } } return false; } /** * 得到ip的数字,不足三位的在后面补0,调用ipCheck方法之后再调用此方法 * @param ip * @return */ public static String getIpNum(String ip){ StringBuffer sb = new StringBuffer(); String len[] = ip.split(“\.”); for(int i = 0;i<len.length;i ){ String s = len[i]; if(s.length()==3){ sb.append(s); }else if(s.length()==2){ sb.append(s).append(“0”); }else if(s.length()==1){ sb.append(s).append(“00”); } } return sb.toString(); } }

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/136361.html原文链接:https://javaforall.cn

0 人点赞