在Security编程中,有几种典型的密码交换信息文件格式:
DER-encoded certificate: .cer, .crt
PEM-encoded message: .pem
PKCS#12 Personal Information Exchange: .pfx, .p12
PKCS#10 Certification Request: .p10
PKCS#7 cert request response: .p7r
PKCS#7 binary message: .p7b
.cer/.crt是用于存放证书,它是2进制形式存放的,不含私钥。
.pem跟crt/cer的区别是它以Ascii来表示。
pfx/p12用于存放个人证书/私钥,他通常包含保护密码,2进制方式
p10是证书请求
p7r是CA对证书请求的回复,只用于导入
p7b以树状展示证书链(certificate chain),同时也支持单个证书,不含私钥。
其中,我介绍如何从p12/pfx文件中提取密钥对及其长度:
1,首先,读取pfx/p12文件(需要提供保护密码)
2,通过别名(Alias,注意,所有证书中的信息项都是通过Alias来提取的)提取你想要分析的证书链
3,再将其转换为一个以X509证书结构体
4,提取里面的项,如果那你的证书项放在第一位(单一证书),直接读取 x509Certs[0](见下面的代码)这个X509Certificate对象
5,X509Certificate对象有很多方法,tain198127网友希望读取RSA密钥(公私钥)及其长度(见http://www.matrix.org.cn/thread.shtml?topicId=43786&forumId=55&#reply),那真是太Easy了,
X509Certificate keyPairCert = x509Certs[0];
int iKeySize = X509CertUtil.getCertificateKeyLength(keyPairCert);
System.out.println("证书密钥算法="+keyPairCert.getPublicKey().getAlgorithm());
System.out.println("证书密钥长度="+iKeySize);
提取了他所需要的信息。
下面的代码来自于我的SecureX项目(https://sourceforge.net/projects/securex)的一部分,仅供参考,可以运行,但需要安装BouncyCastle。
package
org.dev2dev.client.keypair;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileNotFoundException;
import
java.io.IOException;
import
java.security.KeyStore;
import
java.security.KeyStoreException;
import
java.security.NoSuchAlgorithmException;
import
java.security.NoSuchProviderException;
import
java.security.Security;
import
java.security.cert.Certificate;
import
java.security.cert.CertificateException;
import
java.security.cert.X509Certificate;
import
org.dev2dev.security.keytool.X509CertUtil;


public
class
LoadKeyFromPKCS12
{

public static void main(String[] args)
{
try
{
// Open an input stream on the keystore file
String pfxFileName = " c:\\david.turing.pfx " ;
String pfxPassword = " 123456 " ;
File fPkcs12 = null ;
if (pfxFileName != null )
{
// Open the file
fPkcs12 = new File(pfxFileName);
}
FileInputStream fis = new FileInputStream(fPkcs12);
// Create a keystore object
KeyStore keyStore = null ;
try 
{
// Need BC provider for PKCS #12, BKS and UBER
if (Security.getProvider( " BC " ) == null )
{
throw new Exception( " 不能Load入BouncyCastle! " );
} 
keyStore = KeyStore.getInstance( " PKCS12 " , " BC " );
}
catch (KeyStoreException ex)
{
throw new Exception( " 不能正确解释pfx文件! " );
}
catch (NoSuchProviderException ex)
{
throw new Exception( " Security Provider配置有误! " );
} 
try 
{
// Load the file into the keystore
keyStore.load(fis, pfxPassword.toCharArray());
}
catch (CertificateException ex)
{
throw new Exception( " 证书格式问题! " );
}
catch (NoSuchAlgorithmException ex)
{
throw new Exception( " 算法不支持! " );
}
catch (FileNotFoundException ex)
{
throw new Exception( " pfx文件没找到 " );
}
catch (IOException ex)
{
throw new Exception( " 读取pfx有误! " );
}
// 获取我的证书链的中keyEntry的别名
Certificate[] certs = keyStore.getCertificateChain( " david.turing " );
X509Certificate[] x509Certs = X509CertUtil.convertCertificates(certs);
if (x509Certs == null )
{
return ;
} 
x509Certs = X509CertUtil.orderX509CertChain(x509Certs);
X509Certificate keyPairCert = x509Certs[ 0 ];
int iKeySize = X509CertUtil.getCertificateKeyLength(keyPairCert);
System.out.println( " 证书密钥算法= " + keyPairCert.getPublicKey().getAlgorithm());
System.out.println( " 证书密钥长度= " + iKeySize);

} catch (Exception e)
{
e.printStackTrace();
}
} 
}
package
org.dev2dev.security.keytool;
import
java.io.ByteArrayInputStream;
import
java.io.ByteArrayOutputStream;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileNotFoundException;
import
java.io.IOException;
import
java.math.BigInteger;
import
java.security.GeneralSecurityException;
import
java.security.InvalidKeyException;
import
java.security.KeyFactory;
import
java.security.KeyStore;
import
java.security.KeyStoreException;
import
java.security.NoSuchAlgorithmException;
import
java.security.NoSuchProviderException;
import
java.security.Principal;
import
java.security.PrivateKey;
import
java.security.PublicKey;
import
java.security.SignatureException;
import
java.security.cert.CRLException;
import
java.security.cert.CertPath;
import
java.security.cert.Certificate;
import
java.security.cert.CertificateException;
import
java.security.cert.CertificateFactory;
import
java.security.cert.X509CRL;
import
java.security.cert.X509Certificate;
import
java.security.spec.DSAPublicKeySpec;
import
java.security.spec.RSAPublicKeySpec;
import
java.text.MessageFormat;
import
java.util.ArrayList;
import
java.util.Collection;
import
java.util.Date;
import
java.util.Enumeration;
import
java.util.Hashtable;
import
java.util.Iterator;
import
java.util.ResourceBundle;
import
java.util.Vector;
import
org.bouncycastle.asn1.DEROutputStream;
import
org.bouncycastle.asn1.x509.X509Name;
import
org.bouncycastle.jce.PKCS10CertificationRequest;
import
org.bouncycastle.jce.X509Principal;
import
org.bouncycastle.jce.X509V1CertificateGenerator;
public
final
class
X509CertUtil
extends
Object
{
/** *//** Resource bundle */
private static ResourceBundle m_res = ResourceBundle.getBundle("org/dev2dev/security/keytool/resources");

/** *//** Type name for X.509 certificates */
private static final String X509_CERT_TYPE = "X.509";

/** *//** PKCS #7 encoding name */
private static final String PKCS7_ENCODING = "PKCS7";

/** *//** Begin certificate in RFC 1421 encoding */
private static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";

/** *//** End certificate in RFC 1421 encoding */
private static final String END_CERT = "-----END CERTIFICATE-----";

/** *//** The maximum length of lines in printable encoded certificates */
private static final int CERT_LINE_LENGTH = 64;

/** *//** Begin certificate signing request */
private static final String BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----";

/** *//**
本文介绍如何从PKCS#12 (.pfx/.p12) 文件中提取密钥对及其长度,并展示了具体的Java代码实现过程。此外,还介绍了如何使用X509Utils工具类来进一步分析证书结构。

被折叠的 条评论
为什么被折叠?



