一個(gè)比較簡(jiǎn)單的實(shí)現(xiàn):一個(gè)三個(gè)類(lèi)KeyGenerater生成公鑰私鑰對(duì),Signaturer類(lèi)使用私鑰簽名,SignProvider用公鑰驗(yàn)證。公鑰和私鑰使用Base64加密Base64這個(gè)類(lèi)也在博客里面
我們提供的服務(wù)有:成都做網(wǎng)站、網(wǎng)站設(shè)計(jì)、外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、康平ssl等。為成百上千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢(xún)和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的康平網(wǎng)站制作公司
public class KeyGenerater {
private byte[] priKey;
private byte[] pubKey;
public void generater() {
try {
Java.security.KeyPairGenerator keygen = java.security.KeyPairGenerator
.getInstance("RSA");
SecureRandom secrand = new SecureRandom();
secrand.setSeed("syj".getBytes()); // 初始化隨機(jī)產(chǎn)生器
keygen.initialize(1024, secrand);
KeyPair keys = keygen.genKeyPair();
PublicKey pubkey = keys.getPublic();
PrivateKey prikey = keys.getPrivate();
pubKey = Base64.encodeToByte(pubkey.getEncoded());
priKey = Base64.encodeToByte(prikey.getEncoded());
System.out.println("pubKey = " + new String(pubKey));
System.out.println("priKey = " + new String(priKey));
} catch (java.lang.Exception e) {
System.out.println("生成密鑰對(duì)失敗");
e.printStackTrace();
}
}
public byte[] getPriKey() {
return priKey;
}
public byte[] getPubKey() {
return pubKey;
}
}
public class Signaturer {
/**
*
* Description:數(shù)字簽名
*
* @param priKeyText
* @param plainText
* @return
* @author 孫鈺佳
* @since:2007-12-27 上午10:51:48
*/
public static byte[] sign(byte[] priKeyText, String plainText) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64
.decode(priKeyText));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey prikey = keyf.generatePrivate(priPKCS8);
// 用私鑰對(duì)信息生成數(shù)字簽名
java.security.Signature signet = java.security.Signature
.getInstance("MD5withRSA");
signet.initSign(prikey);
signet.update(plainText.getBytes());
byte[] signed = Base64.encodeToByte(signet.sign());
return signed;
} catch (java.lang.Exception e) {
System.out.println("簽名失敗");
e.printStackTrace();
}
return null;
}
}
public class SignProvider {
private SignProvider() {
}
/**
*
* Description:校驗(yàn)數(shù)字簽名,此方法不會(huì)拋出任務(wù)異常,成功返回true,失敗返回false,要求全部參數(shù)不能為空
*
* @param pubKeyText
* 公鑰,base64編碼
* @param plainText
* 明文
* @param signTest
* 數(shù)字簽名的密文,base64編碼
* @return 校驗(yàn)成功返回true 失敗返回false
* @author 孫鈺佳
* @since:2007-12-27 上午09:33:55
*/
public static boolean verify(byte[] pubKeyText, String plainText,
byte[] signText) {
try {
// 解密由base64編碼的公鑰,并構(gòu)造X509EncodedKeySpec對(duì)象
java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec(
Base64.decode(pubKeyText));
// RSA對(duì)稱(chēng)加密算法
java.security.KeyFactory keyFactory = java.security.KeyFactory
.getInstance("RSA");
// 取公鑰匙對(duì)象
java.security.PublicKey pubKey = keyFactory
.generatePublic(bobPubKeySpec);
// 解密由base64編碼的數(shù)字簽名
byte[] signed = Base64.decode(signText);
java.security.Signature signatureChecker = java.security.Signature
.getInstance("MD5withRSA");
signatureChecker.initVerify(pubKey);
signatureChecker.update(plainText.getBytes());
// 驗(yàn)證簽名是否正常
if (signatureChecker.verify(signed))
return true;
else
return false;
} catch (Throwable e) {
System.out.println("校驗(yàn)簽名失敗");
e.printStackTrace();
return false;
}
}
}
望采納,謝謝。
直接將公匙BYTE數(shù)組轉(zhuǎn)換為16進(jìn)制的串啊
private static char hexTable[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
public static String toHexString(byte bytes[])
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i bytes.length; i++)
{
char chars[] = new char[2];
int d = (bytes[i] 240) 4;
int m = bytes[i] 15;
chars[0] = hexTable[d];
chars[1] = hexTable[m];
sb.append(chars);
}
return sb.toString();
}
這個(gè)公鑰和私鑰如果是非對(duì)稱(chēng)加密的算法,那么用公鑰加密的話(huà),就需要用私鑰才能解密了。如果是對(duì)稱(chēng)加密的話(huà),就用加密的公鑰就可以解密了。
SSL加密通信的過(guò)程一般都是首先雙方確認(rèn)大家支持的加密方式,然后采用一種大家都支持的,然后的話(huà),就先用非對(duì)稱(chēng)加密將公鑰加密然后發(fā)給client,然后client解密獲得公鑰。之后的話(huà),大家就可以用公鑰進(jìn)行對(duì)稱(chēng)加密了。
一:需要包含的包
import java.security.*;
import java.io.*;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import sun.security.x509.*
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
二:從文件中讀取證書(shū)
用keytool將.keystore中的證書(shū)寫(xiě)入文件中,然后從該文件中讀取證書(shū)信息
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in=new FileInputStream("out.csr");
Certificate c=cf.generateCertificate(in);
String s=c.toString();
三:從密鑰庫(kù)中直接讀取證書(shū)
String pass="123456";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,pass.toCharArray());
java.security.cert.Certificate c=ks.getCertificate(alias);//alias為條目的別名
四:JAVA程序中顯示證書(shū)指定信息
System.out.println("輸出證書(shū)信息:\n"+c.toString());
System.out.println("版本號(hào):"+t.getVersion());
System.out.println("序列號(hào):"+t.getSerialNumber().toString(16));
System.out.println("主體名:"+t.getSubjectDN());
System.out.println("簽發(fā)者:"+t.getIssuerDN());
System.out.println("有效期:"+t.getNotBefore());
System.out.println("簽名算法:"+t.getSigAlgName());
byte [] sig=t.getSignature();//簽名值
PublicKey pk=t.getPublicKey();
byte [] pkenc=pk.getEncoded();
System.out.println("公鑰");
for(int i=0;ipkenc.length;i++)System.out.print(pkenc[i]+",");
五:JAVA程序列出密鑰庫(kù)所有條目
String pass="123456";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,pass.toCharArray());
Enumeration e=ks.aliases();
while(e.hasMoreElements())
java.security.cert.Certificate c=ks.getCertificate((String)e.nextElement());
六:JAVA程序修改密鑰庫(kù)口令
String oldpass="123456";
String newpass="654321";
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,oldpass.toCharArray());
in.close();
FileOutputStream output=new FileOutputStream(".keystore");
ks.store(output,newpass.toCharArray());
output.close();
七:JAVA程序修改密鑰庫(kù)條目的口令及添加條目
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
Certificate [] cchain=ks.getCertificate(alias);獲取別名對(duì)應(yīng)條目的證書(shū)鏈
PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass.toCharArray());獲取別名對(duì)應(yīng)條目的私鑰
ks.setKeyEntry(alias,pk,newkeypass.toCharArray(),cchain);向密鑰庫(kù)中添加條目
第一個(gè)參數(shù)指定所添加條目的別名,假如使用已存在別名將覆蓋已存在條目,使用新別名將增加一個(gè)新條目,第二個(gè)參數(shù)為條目的私鑰,第三個(gè)為設(shè)置的新口令,第四個(gè)為該私鑰的公鑰的證書(shū)鏈
FileOutputStream output=new FileOutputStream("another");
ks.store(output,storepass.toCharArray())將keystore對(duì)象內(nèi)容寫(xiě)入新文件
八:JAVA程序檢驗(yàn)別名和刪除條目
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
ks.containsAlias("sage");檢驗(yàn)條目是否在密鑰庫(kù)中,存在返回true
ks.deleteEntry("sage");刪除別名對(duì)應(yīng)的條目
FileOutputStream output=new FileOutputStream(".keystore");
ks.store(output,storepass.toCharArray())將keystore對(duì)象內(nèi)容寫(xiě)入文件,條目刪除成功
九:JAVA程序簽發(fā)數(shù)字證書(shū)
(1)從密鑰庫(kù)中讀取CA的證書(shū)
FileInputStream in=new FileInputStream(".keystore");
KeyStore ks=KeyStore.getInstance("JKS");
ks.load(in,storepass.toCharArray());
java.security.cert.Certificate c1=ks.getCertificate("caroot");
(2)從密鑰庫(kù)中讀取CA的私鑰
PrivateKey caprk=(PrivateKey)ks.getKey(alias,cakeypass.toCharArray());
(3)從CA的證書(shū)中提取簽發(fā)者的信息
byte[] encod1=c1.getEncoded(); 提取CA證書(shū)的編碼
X509CertImpl cimp1=new X509CertImpl(encod1); 用該編碼創(chuàng)建X509CertImpl類(lèi)型對(duì)象
X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 獲取X509CertInfo對(duì)象
X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME); 獲取X509Name類(lèi)型的簽發(fā)者信息
(4)獲取待簽發(fā)的證書(shū)
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in2=new FileInputStream("user.csr");
java.security.cert.Certificate c2=cf.generateCertificate(in);
(5)從待簽發(fā)的證書(shū)中提取證書(shū)信息
byte [] encod2=c2.getEncoded();
X509CertImpl cimp2=new X509CertImpl(encod2); 用該編碼創(chuàng)建X509CertImpl類(lèi)型對(duì)象
X509CertInfo cinfo2=(X509CertInfo)cimp2.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 獲取X509CertInfo對(duì)象
(6)設(shè)置新證書(shū)有效期
Date begindate=new Date(); 獲取當(dāng)前時(shí)間
Date enddate=new Date(begindate.getTime()+3000*24*60*60*1000L); 有效期為3000天
CertificateValidity cv=new CertificateValidity(begindate,enddate); 創(chuàng)建對(duì)象
cinfo2.set(X509CertInfo.VALIDITY,cv); 設(shè)置有效期
(7)設(shè)置新證書(shū)序列號(hào)
int sn=(int)(begindate.getTime()/1000); 以當(dāng)前時(shí)間為序列號(hào)
CertificateSerialNumber csn=new CertificateSerialNumber(sn);
cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn);
(8)設(shè)置新證書(shū)簽發(fā)者
cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);應(yīng)用第三步的結(jié)果
(9)設(shè)置新證書(shū)簽名算法信息
AlgorithmId algorithm=new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM,algorithm);
(10)創(chuàng)建證書(shū)并使用CA的私鑰對(duì)其簽名
X509CertImpl newcert=new X509CertImpl(cinfo2);
newcert.sign(caprk,"MD5WithRSA"); 使用CA私鑰對(duì)其簽名
(11)將新證書(shū)寫(xiě)入密鑰庫(kù)
ks.setCertificateEntry("lf_signed",newcert);
FileOutputStream out=new FileOutputStream("newstore");
ks.store(out,"newpass".toCharArray()); 這里是寫(xiě)入了新的密鑰庫(kù),也可以使用第七條來(lái)增加條目
十:數(shù)字證書(shū)的檢驗(yàn)
(1)驗(yàn)證證書(shū)的有效期
(a)獲取X509Certificate類(lèi)型對(duì)象
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in1=new FileInputStream("aa.crt");
java.security.cert.Certificate c1=cf.generateCertificate(in1);
X509Certificate t=(X509Certificate)c1;
in2.close();
(b)獲取日期
Date TimeNow=new Date();
(c)檢驗(yàn)有效性
try{
t.checkValidity(TimeNow);
System.out.println("OK");
}catch(CertificateExpiredException e){ //過(guò)期
System.out.println("Expired");
System.out.println(e.getMessage());
}catch((CertificateNotYetValidException e){ //尚未生效
System.out.println("Too early");
System.out.println(e.getMessage());}
(2)驗(yàn)證證書(shū)簽名的有效性
(a)獲取CA證書(shū)
CertificateFactory cf=CertificateFactory.getInstance("X.509");
FileInputStream in2=new FileInputStream("caroot.crt");
java.security.cert.Certificate cac=cf.generateCertificate(in2);
in2.close();
(c)獲取CA的公鑰
PublicKey pbk=cac.getPublicKey();
(b)獲取待檢驗(yàn)的證書(shū)(上步已經(jīng)獲取了,就是C1)
(c)檢驗(yàn)證書(shū)
boolean pass=false;
try{
c1.verify(pbk);
pass=true;
}catch(Exception e){
pass=false;
System.out.println(e);
}