PKCS12证书详解与应用

发布时间:2023-05-18

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();
}
  1. 读取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();
}
  1. 通过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证书和数字签名技术,我们可以确保文件的完整性和来源,同时也可以避免文件在传输过程中被窃听或篡改,从而保证了数据的安全性和完整性。