PKCS12 证书的生成及验证

Posted 颐和园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PKCS12 证书的生成及验证相关的知识,希望对你有一定的参考价值。

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

服务器生成PKCS12证书库,并通过servlet导出为DER客户端证书(含一个密钥和一个证书)。iPhone从服务器下载证书后,如何进行验证?

一、 生成证书

假设密钥库为dlt.p12,库密码ipcc@95598,有效期1天,则命令为:

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

 

如果需要将p12证书导出为.cer格式,可以使用命令:

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

查看.cer文件:

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

如果需要将keystore中的私钥导出为.p12格式:

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

注意,keytool用的是jdk1.6提供的版本。此时命令提示忽略用户输入的destkeypass密码:

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

查看dltclient.p12内容:

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

可以看到如下输出:

 

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

一、 提供证书下载

先把生成的p12证书库dlt.p12放到服务器目录下。

新建一个Servlet:GetP12Cert。

public class GetP12Cert extends HttpServlet

private static final long serialVersionUID = 1L;

    private static final int max_days =1;  

    /**

     * @see HttpServlet#HttpServlet()

     */

    public GetP12Cert()

        super ();

        // TODO Auto-generated constructor stub

   

 

/**

  * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

  */

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException

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

String pass= "ipcc@95598" ;

Pkcs12Manager man= null ;

String alias= "p12client" ;

String keypass= "123456" ;

try

man= new Pkcs12Manager( new File(filename),pass);

man.updateExpiration(alias, keypass, max_days );

exportCert(man,alias,response);

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

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

catch (Exception e)

e.printStackTrace();

 

// 导出证书

private void exportCert(Pkcs12Manager man,String alias,HttpServletResponse response)

OutputStream out= null ;

try

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

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

    byte [] buf = cert.getEncoded();

// 写证书文件

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

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

            + man. file .getName());  

    out= response.getOutputStream();

    out.write(buf);    

catch (Exception e)e.printStackTrace();

finally

try

out.close();

catch (Exception e)

 

/**

  * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

  */

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException

doGet(request,response);

 

其中,Pkcs12Manager是一个javabean,提供了对PKCS12证书的读取、修改操作,代码如下:

public class Pkcs12Manager

    public File file ;

    public KeyStore keyStore ;

    private char [] storePass ;

    public Pkcs12Manager(File file, String pass) throws IOException, Exception

        this . file = file;

        this . storePass =pass.toCharArray();

        getKeyStore(); // 加载 KeyStore 文件

   

    // 加载 KeyStore 文件

    public synchronized KeyStore getKeyStore() throws IOException, Exception

        if ( keyStore == null )

            FileInputStream fin = new FileInputStream( file );

            KeyStore store = KeyStore.getInstance ( "PKCS12" );

            try

                store.load(fin, storePass );               

           

            finally

                try

                     fin.close();

                catch (IOException e)

           

            keyStore = store;

       

        return keyStore ;

   

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

public X509CertInfo getX509CertInfo(String alias) throws Exception

X509CertImpl cimp=getX509CertImpl(alias);

// 获取 X509CertInfo 对象

return (X509CertInfo) cimp.get(X509CertImpl. NAME

+ "." + X509CertImpl. INFO );

    // 根据 alias 获取 X509CertImpl 对象

private X509CertImpl getX509CertImpl(String alias) throws Exception

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

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

byte [] enc = c.getEncoded(); // 获取 证书内容(经过编码的字节)

X509CertImpl cimp= new X509CertImpl(enc); // 创建 X509CertImpl

return cimp;

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

public void updateExpiration(String alias,String keypass, int n) throws Exception

System. out .println(getExpiration(alias));

X509CertInfo cinfo=getX509CertInfo(alias); // 获取 X509CertInfo 对象

X509CertImpl cimp=getX509CertImpl(alias); // 获取 X509CertImpl 对象

String sigAlgrithm=cimp.getSigAlgName(); // 获取签名算法

CertificateValidity cv=(CertificateValidity)cinfo.get(X509CertInfo. VALIDITY );

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

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

System. out .println( "new date:" +d2.toString());

// 创建有效期对象

cv.set(CertificateValidity. NOT_AFTER , d2);

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

saveCert(alias,keypass,cinfo,sigAlgrithm);

System. out .println(getExpiration(alias));

//  读取证书过期时间

public String getExpiration(String alias) throws Exception

X509CertInfo cinfo=getX509CertInfo(alias);

CertificateValidity cv=(CertificateValidity)cinfo.get(X509CertInfo. VALIDITY );

// 创建有效期对象

Date d=(Date)cv.get(CertificateValidity. NOT_AFTER );

return d.toString();

//  存储证书

private void saveCert(String alias,String keypass,

X509CertInfo cinfo,String algrithm) throws Exception

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

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

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

cert.sign(p

以上是关于PKCS12 证书的生成及验证的主要内容,如果未能解决你的问题,请参考以下文章

如何从 .SPC(代码签名证书)和 .PKCS12(私钥)生成 PKCS12 (.p12)?

将PKCS#12证书转换为PEM时输入PEM密码短语

使用OpenSSL创建多级CA证书链签发证书并导出为pkcs12/p12/pfx文件

java PKCS12 证书生成

使用OpenSSL创建多级CA证书链签发证书并导出为pkcs12/p12/pfx文件

使用OpenSSL创建多级CA证书链签发证书并导出为pkcs12/p12/pfx文件