您的位置:

PKCS12证书详解与应用

一、PKCS12证书概述

PKCS12是基于密码学技术实现的一种证书格式,通常被用来存储私钥、公钥和证书信息。该证书格式主要由RSA Security和其它安全技术公司共同推广和开发。

PKCS12证书通常使用扩展名为“.pfx”或“.p12”,它可以包含多个证书链和私钥,同时也可以加密和保护存储在证书内的信息。在HTTPS协议中,服务器通常需要使用PKCS12证书来完成HTTPS协议的握手过程。在Java平台中,我们可以使用Keytool和OpenSSL等工具来生成和管理PKCS12证书。

二、PKCS12证书结构

一个PKCS12证书包含以下内容:

  • 密码基元(Password-Based Encryption):这部分用于保护存储在证书中的所有信息,通常采用对称加密算法进行保护,比如AES、DES、RC2等算法。

  • 私钥:该部分用于存储私钥信息,私钥通常存储在可移植证书中,以便于在不同设备之间进行转移。

  • 证书链:证书链一般用于存储CA证书或者是其他需要的证书链,这些证书用于验证存储在PKCS12证书中的公钥与CA证书是否匹配。

  • 证书属性(Attributes):PKCS12证书支持存储和管理一个特定的证书属性,比如证书过期时间、证书吊销等等。这些属性数据都是可选的,但它们可以帮助我们更好地管理和维护证书。

三、PKCS12证书下载链接

1、生成PKCS12证书的Java代码:

 public static void createP12() throws Exception {
     String alias = "12306";
     String storePwd = "123456";
     String exportPwd = "123456";
     String keyPwd = "123456";
     String certFilePath = "D:\\crt.crt";
     String keyFilePath = "D:\\key.pem";
     String keystoreFile = "D:\\test.p12";

     Certificate cert = getCert(certFilePath);// reads certificate from file
     PrivateKey privKey = getPrivateKey(keyFilePath, "RSA");// reads private key from file
     KeyStore ks = KeyStore.getInstance("PKCS12");
     ks.load(null, storePwd.toCharArray());

     ks.setKeyEntry(alias, privKey, keyPwd.toCharArray(), new Certificate[] { cert });
     FileOutputStream fos = new FileOutputStream(keystoreFile);
     ks.store(fos, exportPwd.toCharArray());
     fos.close();
 }

2、读取PKCS12证书的Java代码:

 public static void readP12() throws Exception {
     String path = "D:\\test.p12";
     String storePwd = "123456";
     String alias = "12306";
     String keyPwd = "123456";
     String cerPath = "D:\\12306.cer";

     KeyStore keyStore = KeyStore.getInstance("PKCS12");
     FileInputStream instream = new FileInputStream(new File(path));
     keyStore.load(instream, storePwd.toCharArray());
     instream.close();

     Certificate[] certs = keyStore.getCertificateChain(alias);// returns the certificate chain
     Certificate cert = keyStore.getCertificate(alias);// returns the certificate

     Key key = keyStore.getKey(alias, keyPwd.toCharArray());// returns the private key
     byte[] encoded = key.getEncoded();

     FileOutputStream fos = new FileOutputStream(cerPath);
     CertificateFactory cf = CertificateFactory.getInstance("X.509");
     Certificate certificate = null;
     for (Certificate c : certs) {
         certificate = c;
         fos.write(certificate.getEncoded());
     }
     fos.close();
 }

3、通过OpenSSL生成PKCS12证书的命令行:

 openssl pkcs12 -export -inkey my_key.pem -in my_cert.crt -out my_cert.pkcs12

四、PKCS12证书应用场景

PKCS12证书广泛地应用在安全通信、数字签名、认证等领域,以及在HTTPS协议中提供了一种安全的传输协议。在Java平台中,我们可以使用PKCS12证书来完成HTTPS协议的握手过程,也可以通过PKCS12证书来完成对文件或数据进行数字签名的操作。

例如,我们可以使用以下Java代码,来对文件进行数字签名:

 public static void sign(String p12Path, String p12Pwd, String srcFilePath, String destFilePath) throws Exception {
     String algorithm = "SHA1withRSA";// the algorithm used for signing
     File f = new File(srcFilePath);
     FileInputStream fin = new FileInputStream(f);
     byte[] buffer = new byte[(int) f.length()];
     fin.read(buffer);

     KeyStore ks = KeyStore.getInstance("PKCS12");
     FileInputStream kins = new FileInputStream(p12Path);
     char[] password = p12Pwd.toCharArray();
     ks.load(kins, password);

     String alias = ((java.security.KeyStore.PrivateKeyEntry) ks.getEntry(alias, new java.security.KeyStore.PasswordProtection(password))).getCertificate().toString();
     PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password);
     Signature signature = Signature.getInstance(algorithm);
     signature.initSign(privateKey, SecureRandom.getInstance("SHA1PRNG"));
     signature.update(buffer);
     byte[] signedBytes = signature.sign();
     FileOutputStream fos = new FileOutputStream(destFilePath);
     fos.write(signedBytes);
     fos.close();
 }

通过PKCS12证书和数字签名技术,我们可以确保文件的完整性和来源,同时也可以避免文件在传输过程中被窃听或篡改,从而保证了数据的安全性和完整性。