java生成PFX证书

package zrh4;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;


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() throws NoSuchAlgorithmException,
NoSuchProviderException {
sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
}


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> createRootCA(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;
}
String rootPath = path + File.separator + root + sbh + ".pfx";
String certPath = path + File.separator + sbh + ".pfx";
File file = new File(rootPath);
if (file.exists()) {
System.out.println("文件已存在");
map.put("code", "-1");
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();
}
System.out.println("");
File file2 = new File(certPath);
if(file2.exists())
file2.delete();
map.put("code", "-1");
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;
}


public static void main(String[] args) {
try {
GenX509Cert gcert = new GenX509Cert();
Map<String,String> map = gcert.createRootCA("133456","小科","e:","123456","10.26.27.28");
System.out.println(map.get("code")+"\t"+map.get("msg"));
} catch (Exception e) {
e.printStackTrace();
}
}

}

        //验签

public static void signMethod(){
try{
final String KEYSTORE_FILE     = "e:" + File.separator
+ "133456.pfx";
       final String KEYSTORE_PASSWORD = "123456";
       final String KEYSTORE_ALIAS    = "client";
           KeyStore ks = KeyStore.getInstance("PKCS12");
           FileInputStream fis = new FileInputStream(KEYSTORE_FILE);


           char[] nPassword = null;
           if ((KEYSTORE_PASSWORD == null) || KEYSTORE_PASSWORD.trim().equals("")) {
               nPassword = null;
           } else{
               nPassword = KEYSTORE_PASSWORD.toCharArray();
           }
           ks.load(fis, nPassword);
           fis.close();


           PrivateKey prikey = (PrivateKey) ks.getKey(KEYSTORE_ALIAS, nPassword);
           X509Certificate cert = (X509Certificate) ks.getCertificate(KEYSTORE_ALIAS);
           PublicKey pubkey = cert.getPublicKey();


           String data = "sign data";
           System.out.println("证书序列号:"+cert.getSerialNumber());
           System.out.println("cert = " + cert);
           System.out.println("public key = " + pubkey);
           System.out.println("private key = " + prikey);
           Signature sig=Signature.getInstance("MD5WithRSA");
           sig.initSign(prikey);
           sig.update(data.getBytes("UTF-8"));
           byte b[] = sig.sign();
           String afterSign = Base64Util.base64encoder(b);
           System.out.println("签名结果是:"+afterSign);
           String file = "e:/k.k";
           byte pb[] = Serializer.serialize(pubkey);
           String p = Base64Utils.encode(pb);
           certWrite(p, file);
           p = fileRead(file);
           pb = Base64Utils.decode(p);
           PublicKey pk = (PublicKey) Serializer.unserialize(pb);
           Signature sig2=Signature.getInstance("MD5WithRSA");
           sig2.initVerify(pk);
           sig2.update(data.getBytes("UTF-8"));
           System.out.println("验签结果是:"+sig2.verify(b));
}catch(Exception ex){
ex.printStackTrace();
}
}

public static void certWrite(String key, String filename)
throws IOException {
FileWriter fw = new FileWriter(filename);
fw.write(key);
fw.close();
}


public static String fileRead(String file) throws IOException{
InputStreamReader is = new FileReader(file);
BufferedReader br = new BufferedReader(is);
String str = "",len = "";
while((len=br.readLine())!=null){
str+=len;
}
br.close();
is.close();
return str;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值