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