您的位置:首页 > 编程语言 > Java开发

java 代码生成数字证书

2010-02-25 16:32 435 查看
http://liuleijsjx.javaeye.com/blog/422343

本人刚写的学习心得 希望能有所帮助

/**

*代码实例 通过反编译查看keytool的java code获得的数字证书的内部生成方法

*推荐使用jdk1.5

**/

1。首先生成selfcert

CertAndKeyGen cak = new CertAndKeyGen("RSA","MD5WithRSA",null);

//参数分别为 公钥算法 签名算法 providername(因为不知道确切的 只好使用null 既使用默认的provider)

cak.generate(1024);

//生成一对key 参数为key的长度 对于rsa不能小于512

X500Name subject = new X500Name("CN=simic,o=shanghai");

//subject name

X509Certificate certificate = cak.getSelfCertificate(subject,10);

// 后一个long型参数代表从现在开始的有效期 单位为秒(如果不想从现在开始算 可以在后面改这个域)

BASE64Encoder base64
= new BASE64Encoder();

FileOutputStream fos = new FileOutputStream(new File("d://test.crt"));

base64.encodeBuffer(certificate.getEncoded(), fos);

//生成cert文件 base64加密 当然也可以不加密

2。生成非自签的cert

首先按照1走一遍生成一个自签证书

byte certbytes[] = certificate.getEncoded();

X509CertImpl x509certimpl = new X509CertImpl(certbytes);

X509CertInfo x509certinfo = (X509CertInfo)x509certimpl.get("x509.info");

X500Name issuer = new X500Name("CN=fatal,o=shanghai");

x509certinfo.set("issuer.dname",issuer);

//设置issuer域

Date bdate = new Date();

Date edate = new Date();

edate.setTime(bdate.getTime() + validity * 1000L * 24L * 60L * 60L);

//validity为有效时间长度 单位为秒

CertificateValidity certificatevalidity = new CertificateValidity(bdate,
edate);

x509certinfo.set("validity", certificatevalidity);

//设置有效期域(包含开始时间和到期时间)域名等同与x509certinfo.VALIDITY

x509certinfo.set("serialNumber", new
CertificateSerialNumber((int)(date.getTime() / 1000L)));

//设置序列号域

CertificateVersion cv = new CertificateVersion(CertificateVersion.V3);

x509certinfo.set(X509CertInfo.VERSION,cv);

//设置版本号 只有v1 ,v2,v3这几个合法值

/**

*以上是证书的基本信息 如果要添加用户扩展信息 则比较麻烦 首先要确定version必须是v3否则不行 然后按照以下步骤

**/

ObjectIdentifier oid = new ObjectIdentifier(new int[]{1,22});

//生成扩展域的id 是个int数组 第1位最大2 第2位最大39 最多可以几位不明....

byte l = 0x11;//数据总长17位

byte f = 0x04;

String userData = "hohohohohahahahah";

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);

}

Extension ext = new Extension(oid,true,bs);

// 生成一个extension对象 参数分别为 oid,是否关键扩展,byte[]型的内容值

//其中内容的格式比较怪异 第一位是flag 这里取4暂时没出错 估计用来说明数据的用处的 第2位是后面的实际数据的长度,然后就是数据

CertificateExtensions exts = new CertificateExtensions();

exts.set("aa",ext);

//如果有多个extension则都放入CertificateExtensions 类中,

x509certinfo.set(X509CertInfo.EXTENSIONS,exts);

//设置extensions域

X509CertImpl x509certimpl1 = new X509CertImpl(x509certinfo);

x509certimpl1.sign(cak1.getPrivateKey(), "MD5WithRSA");

//使用另一个证书的私钥来签名此证书 这里使用 md5散列 用rsa来加密

BASE64Encoder base64 = new BASE64Encoder();

FileOutputStream fos = new FileOutputStream(new File("d://test.crt"));

base64.encodeBuffer(x509certimpl1.getEncoded(), fos);

//生成文件

x509certimpl1.verify(cak.getPublicKey(),null);

//使用某个证书的公钥验证证书 如果验证不通过 则会抛错

很多地方没仔细测过 可能有不正确之处还请多包涵

==========================代码2==================================
http://www.blogjava.net/neumqp/archive/2006/03/02/33211.html
keytool -genkey -dname "CN=demo, OU=softDept, O=company,
L=puddong,S=shanghai, C=cn" -alias demo -keyalg RSA -keysize 1024
-keystore demoKeystore -validity 3650 -storepass storePwd -keypass
demoPwd

生成保存公钥和私钥的密钥仓库,保存在demoKeystore文件中。这里storepass 和 keypass 不要有java
正则表达式中的特殊字符,否则程序里要转义麻烦。

keytool -export -alias demo -keystore demoKeystore -rfc -file demo.cer
//从密钥仓库中导出保存公钥的证书

输入keypass 即demoPwd

try{

//密钥仓库

KeyStore ks = KeyStore.getInstance("JKS");

//读取密钥仓库

FileInputStream ksfis = new FileInputStream("demoKeystore");

BufferedInputStream ksbufin = new BufferedInputStream(ksfis);

char[] storePwd = "storePwd".toCharArray();

ks.load(ksbufin, storePwd);

ksbufin.close();

char[] keyPwd = "demoPwd".toCharArray();

//从密钥仓库得到私钥

PrivateKey priK = (PrivateKey) ks.getKey("demo", keyPwd);

//生成cipher

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding",new
org.bouncycastle.jce.provider.BouncyCastleProvider());

//用私钥初始化cipher

cipher.init(Cipher.ENCRYPT_MODE, priK);

byte[] plain = "This is plain text".getBytes("UTF-8");

//因为用的1024位rsa算法,一次只能加密1024/8-11字节数据,分开加密

byte[] code = new byte[(((plain.length-1)/117+1))*128];

int ixplain = 0;

int ixcode = 0;

while((plain.length - ixplain) > 117) {//每117字节做一次加密

ixcode += cipher.doFinal(plain, ixplain, 117, code,
ixcode);

ixplain += 117;

}

cipher.doFinal(plain, ixplain, plain.length - ixplain, code,
ixcode);

//加密后的code

System.out.println(Arrays.toString(code));

//通常会用base64编码

String base64 = encoder.encode(code);

CertificateFactory certificatefactory = CertificateFactory

.getInstance("X.509");

//读取证书

FileInputStream fin = new FileInputStream("demo.cer");

X509Certificate certificate = (X509Certificate) certificatefactory

.generateCertificate(fin);

fin.close();

//得到公钥

PublicKey pubK = certificate.getPublicKey();

//初始化cipher

cipher.init(Cipher.DECRYPT_MODE, pubK);

//base64解码

code = decoder.decodeBuffer(base64);

System.out.println(Arrays.toString(code));

byte[] plain2 = new byte[code.length];

int ixplain2 = 0;

int ixcode2 = 0;

while((code.length - ixcode2) > 12 8) {//每128字节做一次解密

ixplain2 += cipher.doFinal(code, ixcode2, 128, plain2,
ixplain2);

ixcode2 += 128;

}

ixplain2 += cipher.doFinal(code, ixcode2, code.length -
ixcode2, plain2, ixplain2);

String s2 = new String(plain2, 0, ixplain2, "UTF-8");

System.out.println(s2);

}catch(Exception ex){

ex.printStackTrace();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: