大家好,又见面了,我是你们的朋友全栈君。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();
}
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/136361.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...