[转]PKCS12 证书的生成及验证

[url=http://blog.csdn.net/kmyhy/article/details/6431609]http://blog.csdn.net/kmyhy/article/details/6431609[/url]


?

本文首先感谢 Apple 开发者论坛的eskimo1,他是我见过的最热心肠的人,对任何人他都不吝于给予无私帮助。




一、

生成证书




keytool -genkey -v
-alias root -keyalg RSA -storetype PKCS12 -keystore dlt.p12 -dname "CN=www.handtimes.com,OU=ipcc,O=云电同方,L=昆明,ST=云南,C=中国"
-storepass ipcc@95598 -keypass ipcc@95598


keytool -genkey -v
-alias p12client -keyalg RSA -storetype PKCS12 -keystore dlt.p12 -dname
"CN=www.handtimes.com,OU=ipcc,O=云电同方,L=昆明,ST=云南,C=中国" -storepass ipcc@95598
-keypass 123456 -validity 1


keytool -list -v
-alias p12client -keystore dlt.p12 -storepass ipcc@95598 -storetype PKCS12


keytool -list -v
-keystore IPCCCA

dlt.p12 ipcc@95598 -storetype PKCS12




keytool -export
-alias p12client -keystore dlt.p12 -storetype PKCS12 -storepass ipcc@95598 -rfc
-file p12.cer




keytool -printcert
-v -file /Users/kmyhy/Desktop/client.cer




Keytool.exe
-importkeystore -srckeystore IPCCCA -srcstoretype jks -srcstorepass ipcc@95598 -srcalias
p12client?
-destkeystore dltclient.p12
-deststoretype pkcs12 -deststorepass ipcc@95598 -destkeypass 123456

validity 3







重新输入密码123456,回车,将在用户主目录下生成dltclient.p12文件。







keytool.exe -list
-keystore dltclient.p12 -storepass ipcc@95598 -storetype pkcs12


?




可以看到其中包含了证书和私钥,并且其认证指纹是和IPCCCA中的一模一样的。




一、

提供证书下载





[/b]

[b]class
[/b]
GetP12Cert
[b]extends
[/b]
HttpServlet {



[b]private
[/b]

[b]static
[/b]

[b]final
[/b]

[b]long
[/b]

[i]serialVersionUID
[/i]
= 1L;

???

[b]private
[/b]

[b]static
[/b]

[b]final
[/b]

[b]int
[/b]

[i]max_days
[/i]
=1;??


???

/**

????
*
[b]@see
[/b]
HttpServlet#HttpServlet()

????
*/

???

[b]public
[/b]
GetP12Cert() {

???????

[b]super
[/b]
();

???????

//
[b]TODO
[/b]
Auto-generated constructor stub

???
}




/**


?
*
[b]@see
[/b]
HttpServlet#doGet(HttpServletRequest
request, HttpServletResponse response)



?
*/



[b]protected
[/b]

[b]void
[/b]
doGet(HttpServletRequest
request, HttpServletResponse response)

[b]throws
[/b]
ServletException, IOException {



String filename=
"C://Documents and
Settings//Administrator//dlt.cer"

;



String pass=
"ipcc@95598"
;



Pkcs12Manager man=
[b]null
[/b]
;



String alias=
"p12client"
;



String keypass=
"123456"
;




[b]try
[/b]
{




man=
[b]new
[/b]
Pkcs12Manager(
[b]new
[/b]
File(filename),pass);







man.updateExpiration(alias,
keypass,
[i]max_days
[/i]
);




exportCert(man,alias,response);

//


man.saveCert(alias,
"123456");





//man.saveCert(alias,
"123456");









}
[b]catch
[/b]
(Exception e){




e.printStackTrace();



}


}




//
导出证书



[b]private
[/b]

[b]void
[/b]
exportCert(Pkcs12Manager
man,String alias,HttpServletResponse response){




OutputStream out=
[b]null
[/b]
;




[b]try
[/b]
{



???
Certificate cert = man.
keyStore
.getCertificate(alias);



???

//
得到证书内容(以编码过的格式)



???

[b]byte
[/b]
[] buf = cert.getEncoded();





//
写证书文件



???
response.setContentType(
"application/x-download"
);??




???
response.addHeader(
"Content-Disposition"
,
"attachment;filename="
?




???????????
+ man.
file
.getName());??




???
out= response.getOutputStream();



???
out.write(buf);

???




}




[b]catch
[/b]
(Exception e){e.printStackTrace();}




[b]finally
[/b]
{





[b]try
[/b]
{





out.close();




}
[b]catch
[/b]
(Exception e){








}



}


}




/**


?
*
[b]@see
[/b]

HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)



?
*/



[b]protected
[/b]

[b]void
[/b]

doPost(HttpServletRequest request, HttpServletResponse response)

[b]throws
[/b]
ServletException,
IOException {




doGet(request,response);


}





[/b]

[b]class
[/b]
Pkcs12Manager {

???

[b]public
[/b]
File
file
;

???

[b]public
[/b]
KeyStore
keyStore
;

???

[b]private
[/b]

[b]char
[/b]
[]
storePass
;

???

[b]public
[/b]
Pkcs12Manager(File file, String pass)
[b]throws
[/b]
IOException, Exception {

???????

[b]this
[/b]
.
file
= file;

???????

[b]this
[/b]
.
storePass
=pass.toCharArray();

???????
getKeyStore();
//
加载
KeyStore
文件

???
}

???

//
加载
KeyStore
文件

???

[b]public
[/b]

[b]synchronized
[/b]
KeyStore getKeyStore()
[b]throws
[/b]
IOException, Exception {

???????

[b]if
[/b]
(
keyStore
==
[b]null
[/b]
) {

???????????
FileInputStream fin =
[b]new
[/b]
FileInputStream(
file
);

???????????
KeyStore store = KeyStore.[i]getInstance[/i]
(
"PKCS12"
);

???????????

[b]try
[/b]
{

???????????????
store.load(fin,
storePass
);???????????????


???????????
}

???????????

[b]finally
[/b]
{

???????????????

[b]try
[/b]
{

??????????????????
?
fin.close();

???????????????
}
[b]catch
[/b]
(IOException e) { }

???????????
}

???????????

keyStore
= store;

???????
}

???????

[b]return
[/b]

keyStore
;

???
}

???

//
读取
alias
指定的证书内容



[b]public
[/b]
X509CertInfo
getX509CertInfo(String alias)

[b]throws
[/b]
Exception {



X509CertImpl cimp=getX509CertImpl(alias);




//
获取
X509CertInfo
对象




[b]return
[/b]
(X509CertInfo) cimp.get(X509CertImpl.
[i]NAME
[/i]






+
"."
+ X509CertImpl.
[i]INFO
[/i]
);


}

???

//
根据
alias
获取
X509CertImpl
对象



[b]private
[/b]
X509CertImpl
getX509CertImpl(String alias)

[b]throws
[/b]
Exception{



Certificate c =
keyStore
.getCertificate(alias);
//
读取证书




//
从待签发的证书中提取证书信息  




[b]byte
[/b]
[] enc = c.getEncoded();
//
获取

证书内容(经过编码的字节)



X509CertImpl cimp=
[b]new
[/b]
X509CertImpl(enc);
//
创建
X509CertImpl





[b]return
[/b]
cimp;


}



//
修改证书过期时间
:
过期时间顺延
n




[b]public
[/b]

[b]void
[/b]
updateExpiration(String
alias,String keypass,

[b]int
[/b]
n)
[b]throws
[/b]
Exception{



System.
[i]out
[/i]
.println(getExpiration(alias));



X509CertInfo cinfo=getX509CertInfo(alias);

//
获取
X509CertInfo
对象



X509CertImpl cimp=getX509CertImpl(alias);

//
获取
X509CertImpl
对象



String sigAlgrithm=cimp.getSigAlgName();

//
获取签名算法



CertificateValidity
cv=(CertificateValidity)cinfo.get(X509CertInfo.
[i]VALIDITY
[/i]
);




//
有效期为当前日期后延
n




Date d2 =
[b]new
[/b]
Date(
[b]new
[/b]
Date().getTime() + n * 24 * 60 * 60 *
1000L);




System.
[i]out
[/i]
.println(
"new date:"
+d2.toString());




//
创建有效期对象



cv.set(CertificateValidity.
[i]NOT_AFTER
[/i]
, d2);



cinfo.set(X509CertInfo.
[i]VALIDITY
[/i]
, cv);
//
设置有效期





saveCert(alias,keypass,cinfo,sigAlgrithm);



System.
[i]out
[/i]
.println(getExpiration(alias));


}



//?

读取证书过期时间



[b]public
[/b]
String
getExpiration(String alias)

[b]throws
[/b]
Exception{



X509CertInfo cinfo=getX509CertInfo(alias);



CertificateValidity
cv=(CertificateValidity)cinfo.get(X509CertInfo.
[i]VALIDITY
[/i]
);




//
创建有效期对象



Date d=(Date)cv.get(CertificateValidity.
[i]NOT_AFTER
[/i]
);




[b]return
[/b]
d.toString();


}

//?

存储证书



[b]private
[/b]

[b]void
[/b]
saveCert(String
alias,String keypass,





X509CertInfo
cinfo,String algrithm)
[b]throws
[/b]
Exception{




//
从密钥库中读取
CA
的私钥



PrivateKey pKey = (PrivateKey)
keyStore
.getKey(alias,
keypass.toCharArray());




X509CertImpl cert =
[b]new
[/b]
X509CertImpl(cinfo);
//
新建证书




cert.sign(pKey,
algrithm);
//
使用
CA
私钥对其签名





//
获取别名对应条目的证书链




Certificate[]
chain =
[b]new
[/b]
Certificate[] { cert };





//
向密钥库中添加条目
,
使用已存在别名将覆盖已存在条目





keyStore
.setKeyEntry(alias, pKey,
keypass.toCharArray(), chain);






//

keystore

存储至文件




FileOutputStream
fOut =
[b]new
[/b]
FileOutputStream(
file
);





keyStore
.store(fOut,
storePass
);




fOut.close();


}



//
获取签名算法



[b]public
[/b]
String
getSigAlgName(String alias)

[b]throws
[/b]
Exception{



Certificate c =
keyStore
.getCertificate(alias);
//
读取证书




//
获取

证书内容(经过编码的字节)  




[b]byte
[/b]
[] enc = c.getEncoded();




//
创建
X509CertImpl
对象



X509CertImpl cimp2 =
[b]new
[/b]
X509CertImpl(enc);



String sigAlgrithm=cimp2.getSigAlgName();




[b]return
[/b]
sigAlgrithm;


}


Servlet
和javabean 部署到服务器中。这样,通过访问http://localhost/GetP12Cert

就可以获得一个有效的证书dlt.cer。


二、

证书的验证





* path=[[
NSBundle

mainBundle
]
pathForResource
:
@"dlt.cer"

ofType
:
nil
];


参数为任意一个有效的日期(在证书有效期之内)


* myTrust=[[
MyTrustService

alloc
]


initWithFilename
:path
EfficientDate
:
@"2011-05-10 0:0:0"
];


ret=[myTrust
trustValuate
:[[
NSDate

alloc
]
init
]];


(ret) {




case

ValuateResultOK
:





NSLog
(
@"
证书有效
"
);





break
;




case

ValuateResultEXPIRED
:





NSLog
(
@"
证书已过期
"
);





break
;




default
:





NSLog
(
@"
证书校验失败
"
);





break
;


release
];












const

char
*
kTrustNames
[
8
] = {



"Invalid"
,



"Proceed"
,



"Confirm"
,



"Deny"
,



"Unspecified"
,



"RecoverableTrustFailure"
,



"FatalTrustFailure"
,



"OtherError"



enum




ValuateResultINVALID
=
0
,

//
评估结果无效,表明评估出错或未经过评估



ValuateResultFAILED
,


//
证书签名无效



ValuateResultEXPIRED
,


//
证书过期



ValuateResultOK





//
证书有效


MyTrustService :
NSObject {




NSString
*
file
;




NSDate
*
efficientDate
;


id
)initWithFilename:(
NSString
*)filename EfficientDate:(
NSString
*)date;


ValuateResult
)trustValuate:(
NSDate
*)date;


ValuateResult
)valuate:(
SecCertificateRef
)cert Trust:(
SecTrustRef
)trust Date:(
NSDate
*)date;


"MyTrustService.h"


MyTrustService


id
)initWithFilename:(
NSString
*)filename
EfficientDate:(

NSString
*)date{



if
(
self
=[
super

init
]) {




file
=filename;




//
设置有效日期,注意,第
2
个参数是一个有效的证书日期,只要这个日期对证书而言是有效的就行




efficientDate
=[[
NSDate

alloc
]
initWithString
:date];




}



return

self
;


ValuateResult
)trustValuate:(
NSDate
*)date{



ValuateResult
ret;



OSStatus
???????????
err;


???

NSData
*???????????
certData;


???

SecCertificateRef
??
cert;


???

SecPolicyRef
???????
policy;


???

SecTrustRef
????????
trust;


?



???

assert
(
file
!=
nil
);

???

assert
(date !=
nil
);






//
从文件获得
DER
数据

???
certData = [
NSData

dataWithContentsOfFile
:
file
];

???

assert
(certData !=
nil
);






//

NSData
获得
Certificate
对象

???
cert =
SecCertificateCreateWithData
(
NULL
, (
CFDataRef
) certData);

???

assert
(cert !=
NULL
);






//
获得
x509 policy

???
policy =
SecPolicyCreateBasicX509
();

???

assert
(policy !=
NULL
);






//
获得
Trust
对象

???
err =
SecTrustCreateWithCertificates
(cert,
policy, &trust);


???

assert
(err ==
noErr
);






//
由于是自签名证书,需要将锚证书设置为要验证的证书自己。注意,这样将使所有除了参数指定的锚证书之外的所有锚证书无效

???
err =
SecTrustSetAnchorCertificates
(trust,
(

CFArrayRef
) [
NSArray

arrayWithObject
:(
id
) cert]);

???

assert
(err ==
noErr
);






//
调用
valuate
方法进行评估


ret=[
self

valuate
:cert
Trust
:trust
Date
:date];






//
评估结束,把
SecTrustSetAnchorCertificates
指定的锚证书失效,于是所有锚证书又可被信任了

??

err=
SecTrustSetAnchorCertificatesOnly
(trust,
NO
);

???

CFRelease
(trust);

???

CFRelease
(policy);

???

CFRelease
(cert);



return
ret;


ValuateResult
)valuate:(
SecCertificateRef
)cert Trust:(
SecTrustRef
)trust Date:(
NSDate
*)date{



ValuateResult
ret;



OSStatus
???????????
err;


???

SecTrustResultType
?
result;





???
err =
SecTrustSetVerifyDate
(trust,
(

CFDateRef
) date);

???

assert
(err ==
noErr
);






CFAbsoluteTime

trustTime;



trustTime =
SecTrustGetVerifyTime
(trust);




???
err =
SecTrustEvaluate
(trust,
&result);


???

assert
(err ==
noErr
);




???

if
(result < (
sizeof
(
kTrustNames
) /
sizeof
(*
kTrustNames
))) {
// if(result < 8)

???????

if
(result==
5
) {
// if result=RecoverableTrustFailure





//

设了个有效的日期,进行再次评估




err=
SecTrustSetVerifyDate
(trust, (
CFDateRef
)
efficientDate
);





assert
(err==
noErr
);




err=
SecTrustEvaluate
(trust, &result);





assert
(err ==
noErr
);





if
(result==
4
) {
// if result=Unspecified,






//
返回证书已过期,这里我们假设把证书尚未生效的情况也算作过期





ret=
ValuateResultEXPIRED
;




}



}
else

if
(result==
4
) {
//
如果第
1
次就通过评估,证书有效




ret=
ValuateResultOK
;



}
else
{




ret=
ValuateResultFAILED
;
//
证书

无效



}






???
}
else
{

???????

NSLog
(
@"result = unknown (%zu)"
, (
size_t
) result);

???
}



return
ret;


void
)dealloc{


[
efficientDate

release
];


[
super

dealloc
];

你可能感兴趣的:(java,[转]PKCS12,证书的生成及验证)