David.Turing's blog

 

如何从pfx/p12文件中提取RSA密钥长度及其他相关信息

在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();
        }
        
    }


}
另外,我会调用其他一个工具类X509Utils来分析证书结构
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-----";

    
/** End certificate signing request */
    
private static final String END_CERT_REQ = "-----END CERTIFICATE REQUEST-----";

    
/** The maximum length of lines in certificate signing requests */
    
private static final int CERT_REQ_LINE_LENGTH = 76;

    
/**
     * Private to prevent construction.
     
*/

    
private X509CertUtil() {}

    
/**
     * Load one or more certificates from the specified file.
     *
     * 
@param fCertFile The file to load certificates from
     * 
@return The certificates
     * 
@throws CryptoException Problem encountered while loading the certificate(s)
     * 
@throws FileNotFoundException If the certificate file does not exist,
     *                               is a directory rather than a regular
     *                               file, or for some other reason cannot
     *                               be opened for reading
     * 
@throws IOException An I/O error occurred
     
*/

    
public static X509Certificate[] loadCertificates(File fCertFile)
        
throws CryptoException, FileNotFoundException, IOException
    
{
        Vector vCerts 
= new Vector();

        FileInputStream fis 
= new FileInputStream(fCertFile);

        
try
        
{
            CertificateFactory cf 
= CertificateFactory.getInstance(X509_CERT_TYPE);

            Collection coll 
= cf.generateCertificates(fis);
            Iterator iter 
= coll.iterator();

            
while (iter.hasNext())
            
{
                X509Certificate cert 
= (X509Certificate)iter.next();
                
if (cert != null)
                
{
                    vCerts.add(cert);
                }

            }

        }

        
catch (CertificateException ex)
        
{
            
throw new CryptoException(MessageFormat.format(m_res.getString("NoLoadCertificate.exception.message"), new String[]{ex.getMessage()}), ex);
        }

        
finally
        
{
            fis.close();
        }


        
return (X509Certificate[])vCerts.toArray(new X509Certificate[vCerts.size()]);
    }


    
/**
     * Load a CRL from the specified file.
     *
     * 
@param fCRLFile The file to load CRL from
     * 
@return The CRL
     * 
@throws CryptoException Problem encountered while loading the certificate(s)
     * 
@throws FileNotFoundException If the CRL file does not exist,
     *                               is a directory rather than a regular
     *                               file, or for some other reason cannot
     *                               be opened for reading
     * 
@throws IOException An I/O error occurred
     
*/

    
public static X509CRL loadCRL(File fCRLFile)
        
throws CryptoException, FileNotFoundException, IOException
    
{
        FileInputStream fis 
= new FileInputStream(fCRLFile);

        
try
        
{
            CertificateFactory cf 
= CertificateFactory.getInstance(X509_CERT_TYPE);
            X509CRL crl 
= (X509CRL)cf.generateCRL(fis);
            
return crl;
        }

        
catch (CertificateException ex)
        
{
            
throw new CryptoException(m_res.getString("NoLoadCrl.exception.message"), ex);
        }

        
catch (CRLException ex)
        
{
            
throw new CryptoException(m_res.getString("NoLoadCrl.exception.message"), ex);
        }

        
finally
        
{
            fis.close();
        }

    }


    
/**
     * Convert the supplied array of certificate objects into X509Certificate objects.
     *
     * 
@param certsIn The Certificate objects
     * 
@return The converted X509Certificate objects
     * 
@throws CryptoException A problem occurred during the conversion
     
*/

    
public static X509Certificate[] convertCertificates(Certificate[] certsIn)
        
throws CryptoException
    
{
        X509Certificate[] certsOut 
= new X509Certificate[certsIn.length];

        
for (int iCnt=0; iCnt < certsIn.length; iCnt++)
        
{
            certsOut[iCnt] 
= convertCertificate(certsIn[iCnt]);
        }


        
return certsOut;
    }


    
/**
     * Convert the supplied certificate object into an X509Certificate object.
     *
     * 
@param certIn The Certificate object
     * 
@return The converted X509Certificate object
     * 
@throws CryptoException A problem occurred during the conversion
     
*/

    
public static X509Certificate convertCertificate(Certificate certIn)
        
throws CryptoException
    
{
        
try
        
{
            CertificateFactory cf 
= CertificateFactory.getInstance(X509_CERT_TYPE);
            ByteArrayInputStream bais 
= new ByteArrayInputStream(certIn.getEncoded());
            
return (X509Certificate)cf.generateCertificate(bais);
        }

        
catch (CertificateException ex)
        
{
            
throw new CryptoException(m_res.getString("NoConvertCertificate.exception.message"), ex);
        }

    }


    
/**
     * Attempt to order the supplied array of X.509 certificates in issued to
     * to issued from order.
     *
     * 
@param certs The X.509 certificates in order
     * 
@return The ordered X.509 certificates
     
*/

    
public static X509Certificate[] orderX509CertChain(X509Certificate certs[])
    
{
        
int iOrdered = 0;
        X509Certificate[] tmpCerts 
= (X509Certificate[])certs.clone();
        X509Certificate[] orderedCerts 
= new X509Certificate[certs.length];

        X509Certificate issuerCert 
= null;

        
// Find the root issuer (ie certificate where issuer is the same as subject)
        for (int iCnt=0; iCnt < tmpCerts.length; iCnt++)
        
{
            X509Certificate aCert 
= tmpCerts[iCnt];
            
if (aCert.getIssuerDN().equals(aCert.getSubjectDN()))
            
{
                issuerCert 
= aCert;
                orderedCerts[iOrdered] 
= issuerCert;
                iOrdered
++;
            }

        }


        
// Couldn't find a root issuer so just return the unordered array
        if (issuerCert == null)
        
{
            
return certs;
        }


        
// Keep making passes through the array of certificates lookign for the
        
// next certificate in the chain until the links run out
        while (true)
        
{
            
boolean bFoundNext = false;
            
for (int iCnt=0; iCnt < tmpCerts.length; iCnt++)
            
{
                X509Certificate aCert 
= tmpCerts[iCnt];

                
// Is this certificate the next in the chain?
                if ((aCert.getIssuerDN().equals(issuerCert.getSubjectDN())) && (aCert != issuerCert))
                
{
                    
// Yes
                    issuerCert = aCert;
                    orderedCerts[iOrdered] 
= issuerCert;
                    iOrdered
++;
                    bFoundNext 
= true;
                    
break;
                }

            }

            
if (!bFoundNext)
            
{
                
break;
            }

        }


        
// Resize array
        tmpCerts = new X509Certificate[iOrdered];
        System.arraycopy(orderedCerts, 
0, tmpCerts, 0, iOrdered);

        
// Reverse the order of the array
        orderedCerts = new X509Certificate[iOrdered];

        
for (int iCnt=0; iCnt < iOrdered; iCnt++)
        
{
            orderedCerts[iCnt] 
= tmpCerts[tmpCerts.length - 1 - iCnt];
        }


        
return orderedCerts;
    }


    
/**
     * DER encode a certificate.
     *
     * 
@return The binary encoding
     * 
@param cert The certificate
     * 
@throws CryptoException If there was a problem encoding the certificate
     
*/

    
public static byte[] getCertEncodedDer(X509Certificate cert) throws CryptoException
    
{
        
try
        
{
            
return cert.getEncoded();
        }

        
catch (CertificateException ex)
        
{
            
throw new CryptoException(m_res.getString("NoDerEncode.exception.message"), ex);
        }

    }


    
/**
     * Base-64 encode a certificate.
     *
     * 
@return The printable encoding
     * 
@param cert The certificate
     * 
@throws CryptoException If there was a problem encoding the certificate
     
*/

    
public static String getCertEncodedBase64(X509Certificate cert) throws CryptoException
    
{
        
try
        
{
            
// Get Base 64 encoding of certificate
            String sTmp = new String(Base64.encode(cert.getEncoded()));

            
// Certificate encodng is bounded by a header and footer
            String sEncoded = BEGIN_CERT + "\n";

            
// Limit line lengths between header and footer
            for (int iCnt=0; iCnt < sTmp.length(); iCnt += CERT_LINE_LENGTH)
            
{
                
int iLineLength;

                
if ((iCnt + CERT_LINE_LENGTH) > sTmp.length())
                
{
                    iLineLength 
= (sTmp.length() - iCnt);
                }

                
else
                
{
                    iLineLength 
= CERT_LINE_LENGTH;
                }


                sEncoded 
+= sTmp.substring(iCnt, (iCnt + iLineLength)) + "\n";
            }


            
// Footer
            sEncoded += END_CERT + "\n";

            
return sEncoded;
        }

        
catch (CertificateException ex)
        
{
            
throw new CryptoException(m_res.getString("NoBase64Encode.exception.message"), ex);
        }

        
catch (IOException ex)
        
{
            
throw new CryptoException(m_res.getString("NoBase64Encode.exception.message"), ex);
        }

    }


    
/**
     * PKCS #7 encode a certificate.
     *
     * 
@return The encoding
     * 
@param cert The certificate
     * 
@throws CryptoException If there was a problem encoding the certificate
     
*/

    
public static byte[] getCertEncodedPkcs7(X509Certificate cert)
        
throws CryptoException
    
{
        
return getCertsEncodedPkcs7(new X509Certificate[] {cert});
    }


    
/**
     * PKCS #7 encode a number of certificates.
     *
     * 
@return The encoding
     * 
@param certs The certificates
     * 
@throws CryptoException If there was a problem encoding the certificates
     
*/

    
public static byte[] getCertsEncodedPkcs7(X509Certificate[] certs)
        
throws CryptoException
    
{
        
try
        
{
             ArrayList alCerts 
= new ArrayList();

             
for (int iCnt=0; iCnt < certs.length; iCnt++)
             
{
                 alCerts.add(certs[iCnt]);
             }


             CertificateFactory cf 
= CertificateFactory.getInstance(X509_CERT_TYPE);
             CertPath cp 
= cf.generateCertPath(alCerts);

             
return cp.getEncoded(PKCS7_ENCODING);
        }

        
catch (CertificateException ex)
        
{
            
throw new CryptoException(m_res.getString("NoPkcs7Encode.exception.message"), ex);
        }

    }


    
/**
     * Generate a self-signed X509 Version 1 certificate for the supplied key
     * pair and signature algorithm.
     *
     * 
@return The generated certificate
     * 
@param sCommonName Common name certficate attribute
     * 
@param sOrganisationUnit Organisation Unit certificate attribute
     * 
@param sOrganisation Organisation certificate attribute
     * 
@param sLocality Locality certificate
     * 
@param sState State certificate attribute
     * 
@param sCountryCode Country Code certificate attribute
     * 
@param iValidity Validity period of cerficate in days
     * 
@param publicKey Public part of key pair
     * 
@param privateKey Private part of key pair
     * 
@param signatureType Signature Type
     * 
@throws CryptoException If there was a problem generating the certificate
     
*/

    
public static X509Certificate generateCert(String sCommonName, String sOrganisationUnit,
                                               String sOrganisation, String sLocality,
                                               String sState, String sCountryCode,
                                               
int iValidity, PublicKey publicKey,
                                               PrivateKey privateKey, SignatureType signatureType)
        
throws CryptoException
    
{
        
// Holds certificate attributes
        Hashtable attrs = new Hashtable();
        Vector vOrder 
= new Vector();

        
// Load certificate attributes
        if (sCommonName != null)
        
{
            attrs.put(X509Principal.CN, sCommonName);
            vOrder.add(
0, X509Principal.CN);
        }


        
if (sOrganisationUnit != null)
        
{
            attrs.put(X509Principal.OU, sOrganisationUnit);
            vOrder.add(
0, X509Principal.OU);
        }


        
if (sOrganisation != null)
        
{
            attrs.put(X509Principal.O, sOrganisation);
            vOrder.add(
0, X509Principal.O);
        }


        
if (sLocality != null)
        
{
            attrs.put(X509Principal.L, sLocality);
            vOrder.add(
0, X509Principal.L);
        }


        
if (sState != null)
        
{
            attrs.put(X509Principal.ST, sState);
            vOrder.add(
0, X509Principal.ST);
        }


        
if (sCountryCode != null)
        
{
            attrs.put(X509Principal.C, sCountryCode);
            vOrder.add(
0, X509Principal.C);
        }


        
// Get an X509 Version 1 Certificate generator
        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();

        
// Load the generator with generation parameters

        
// Set the issuer distinguished name
        certGen.setIssuerDN(new X509Principal(vOrder, attrs));

        
// Valid before and after dates now to iValidity days in the future
        certGen.setNotBefore(new Date(System.currentTimeMillis()));
        certGen.setNotAfter(
new Date(System.currentTimeMillis() + ((long)iValidity * 24 * 60 * 60 * 1000)));

        
// Set the subject distinguished name (same as issuer for our purposes)
        certGen.setSubjectDN(new X509Principal(vOrder, attrs));

        
// Set the public key
        certGen.setPublicKey(publicKey);

        
// Set the algorithm
        certGen.setSignatureAlgorithm(signatureType.toString());

        
// Set the serial number
        certGen.setSerialNumber(generateX509SerialNumber());

        
try
        
{
            
// Generate an X.509 certificate, based on the current issuer and
            
// subject
            X509Certificate cert = certGen.generateX509Certificate(privateKey);

            
// Return the certificate
            return cert;
        }

        
// Something went wrong
        catch (SignatureException ex)
        
{
            
throw new CryptoException(m_res.getString("CertificateGenFailed.exception.message"), ex);
        }

        
catch (InvalidKeyException ex)
        
{
            
throw new CryptoException(m_res.getString("CertificateGenFailed.exception.message"), ex);
        }

    }


    
/**
     * Generate a unique serial number for use as an X509 serial number.
     *
     * 
@return The unique serial number
     
*/

    
private static BigInteger generateX509SerialNumber()
    
{
        
// Time in seconds
        return new BigInteger(Long.toString(System.currentTimeMillis() / 1000));
    }


    
/**
     * Create a PKCS #10 certificate signing request (CSR) using the supplied
     * certificate and private key.
     *
     * 
@param cert The certificate
     * 
@param privateKey The private key
     * 
@throws CryptoException If there was a problem generating the CSR
     * 
@return The CSR
     
*/

    
public static String generatePKCS10CSR(X509Certificate cert, PrivateKey privateKey)
        
throws CryptoException
    
{
        X509Name subject 
= new X509Name(cert.getSubjectDN().toString());

        
try
        
{
            PKCS10CertificationRequest csr 
=
                
new PKCS10CertificationRequest(cert.getSigAlgName(),
                                               subject,
                                               cert.getPublicKey(),
                                               
null,
                                               privateKey);
            
if (!csr.verify())
            
{
                
throw new CryptoException(m_res.getString("NoVerifyCsr.exception.message"));
            }


            
// Get Base 64 encoding of CSR
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            DEROutputStream deros 
= new DEROutputStream(baos);
            deros.writeObject(csr.getDERObject());
            String sTmp 
= new String(Base64.encode(baos.toByteArray()));

            
// CSR is bounded by a header and footer
            String sCsr = BEGIN_CERT_REQ + "\n";

            
// Limit line lengths between header and footer
            for (int iCnt=0; iCnt < sTmp.length(); iCnt += CERT_REQ_LINE_LENGTH)
            
{
                
int iLineLength;

                
if ((iCnt + CERT_REQ_LINE_LENGTH) > sTmp.length())
                
{
                    iLineLength 
= (sTmp.length() - iCnt);
                }

                
else
                
{
                    iLineLength 
= CERT_REQ_LINE_LENGTH;
                }


                sCsr 
+= sTmp.substring(iCnt, (iCnt + iLineLength)) + "\n";
            }


            
// Footer
            sCsr += END_CERT_REQ + "\n";

            
return sCsr;
        }

        
catch (NoSuchProviderException ex)
        
{
            
throw new CryptoException(m_res.getString("NoGenerateCsr.exception.message"), ex);
        }

        
catch (NoSuchAlgorithmException ex)
        
{
            
throw new CryptoException(m_res.getString("NoGenerateCsr.exception.message"), ex);
        }

        
catch (SignatureException ex)
        
{
            
throw new CryptoException(m_res.getString("NoGenerateCsr.exception.message"), ex);
        }

        
catch (InvalidKeyException ex)
        
{
            
throw new CryptoException(m_res.getString("NoGenerateCsr.exception.message"), ex);
        }

        
catch (IOException ex)
        
{
            
throw new CryptoException(m_res.getString("NoGenerateCsr.exception.message"), ex);
        }

    }


    
/**
     * Verify that one X.509 certificate was signed using the private key that
     * corresponds to the public key of a second certificate.
     *
     * 
@return True if the first certificate was signed by private key
     *         corresponding to the second signature
     * 
@param signedCert The signed certificate
     * 
@param signingCert The signing certificate
     * 
@throws CryptoException If there was a problem verifying the signature.
     
*/

    
public static boolean verifyCertificate(X509Certificate signedCert, X509Certificate signingCert)
        
throws CryptoException
    
{
        
try
        
{
            signedCert.verify(signingCert.getPublicKey());
        }

        
// Verification failed
        catch (InvalidKeyException ex)
        
{
            
return false;
        }

        
// Verification failed
        catch (SignatureException ex)
        
{
            
return false;
        }

        
// Problem verifying
        catch (NoSuchProviderException ex)
        
{
            
throw new CryptoException(m_res.getString("NoVerifyCertificate.exception.message"), ex);
        }

        
catch (NoSuchAlgorithmException ex)
        
{
            
throw new CryptoException(m_res.getString("NoVerifyCertificate.exception.message"), ex);
        }

        
catch (CertificateException ex)
        
{
            
throw new CryptoException(m_res.getString("NoVerifyCertificate.exception.message"), ex);
        }

        
return true;
    }


    
/**
     * Check whether or not a trust path exists between the supplied X.509 certificate and
     * and the supplied keystores based on the trusted certificates contained
     * therein, ie that a chain of trust exists between the supplied certificate
     * and a self-signed trusted certificate in the KeyStores.
     *
     * 
@return The trust chain, or null if trust could not be established
     * 
@param cert The certificate
     * 
@param keyStores The KeyStores
     * 
@throws CryptoException If there is a problem establishing trust
     
*/

    
public static X509Certificate[] establishTrust(KeyStore keyStores[], X509Certificate cert)
        
throws CryptoException
    
{
        
// Extract all certificates from the Keystores creating
        Vector ksCerts = new Vector();
        
for (int iCnt=0; iCnt < keyStores.length; iCnt++)
        
{
            ksCerts.addAll(extractCertificates(keyStores[iCnt]));
        }


        
// Try and establish trust against the set of all certificates
        return establishTrust(ksCerts, cert);
    }


    
/**
     * Check whether or not a trust path exists between the supplied X.509 certificate and
     * and the supplied comparison certificates based on the trusted certificates contained
     * therein, ie that a chain of trust exists between the supplied certificate
     * and a self-signed trusted certificate in the comparison set.
     *
     * 
@return The trust chain, or null if trust could not be established
     * 
@param cert The certificate
     * 
@param vCompCerts The comparison set of certificates
     * 
@throws CryptoException If there is a problem establishing trust
     
*/

    
private static X509Certificate[] establishTrust(Vector vCompCerts, X509Certificate cert)
        
throws CryptoException
    
{
        
// For each comparison certificate
        for (int iCnt=0; iCnt < vCompCerts.size(); iCnt++)
        
{
            X509Certificate compCert 
= (X509Certificate)vCompCerts.get(iCnt);

            
// Check if the Comparison certificate's subject is the same as the
            
// certificate's issuer
            if (cert.getIssuerDN().equals(compCert.getSubjectDN()))
            
{
                
// If so verify with the comparison certificate's corresponding
                
// private key was used to sign the certificate
                if (X509CertUtil.verifyCertificate(cert, compCert))
                
{
                    
// If the KeyStore certificate is self-signed then a
                    
// chain of trust exists
                    if (compCert.getSubjectDN().equals(compCert.getIssuerDN()))
                    
{
                        
return new X509Certificate[]{cert, compCert};
                    }

                    
// Otherwise try and establish a chain of trust for
                    
// the comparison certificate against the other comparison certificates
                    else
                    
{
                        X509Certificate[] tmpChain 
= establishTrust(vCompCerts, compCert);
                        
if (tmpChain != null)
                        
{
                            X509Certificate[] trustChain 
= new X509Certificate[tmpChain.length + 1];

                            trustChain[
0= cert;

                            
for (int iCntInr=1; iCntInr <= tmpChain.length; iCntInr++)
                            
{
                                trustChain[iCntInr] 
= tmpChain[iCntInr-1];
                            }


                            
return trustChain;
                        }

                    }

                }

            }

        }


        
// No chain of trust
        return null;
    }


    
/**
     * Extract a copy of all trusted certificates contained within the supplied KeyStore.
     *
     * 
@param keyStore The KeyStore
     * 
@return The extracted certificates
     * 
@throws CryptoException If a problem is encountered extracting the certificates
     
*/

    
private static Vector extractCertificates(KeyStore keyStore) throws CryptoException
    
{
        
try
        
{
            
// For each KeyStore certificate
            Enumeration enum2 = keyStore.aliases();

            Vector vCerts 
= new Vector();

            
while (enum2.hasMoreElements())
            
{
                String sAlias 
= (String)enum2.nextElement();

                
if (keyStore.isCertificateEntry(sAlias))
                
{
                    vCerts.add(X509CertUtil.convertCertificate(keyStore.getCertificate(sAlias)));
                }

            }


            
return vCerts;
        }

        
catch (KeyStoreException ex)
        
{
            
throw new CryptoException(m_res.getString("NoExtractCertificates.exception.message"), ex);
        }

    }


    
/**
     * Check whether or not a trusted certificate in the supplied KeyStore
     * matches the the supplied X.509 certificate.
     *
     * 
@return The alias of the matching certificate in the KeyStore or null
     *         if there is no match
     * 
@param cert The certificate
     * 
@param keyStore The KeyStore
     * 
@throws CryptoException If there is a problem establishing trust
     
*/

    
public static String matchCertificate(KeyStore keyStore, X509Certificate cert)
        
throws CryptoException
    
{
        
try
        
{
            Enumeration enum2 
= keyStore.aliases();

            
while (enum2.hasMoreElements())
            
{
                String sAlias 
= (String)enum2.nextElement();
                
if (keyStore.isCertificateEntry(sAlias))
                
{
                    X509Certificate compCert 
= X509CertUtil.convertCertificate(keyStore.getCertificate(sAlias));

                    
if (cert.equals(compCert))
                    
{
                        
return sAlias;
                    }

                }

            }

            
return null;
        }

        
catch (KeyStoreException ex)
        
{
            
throw new CryptoException(m_res.getString("NoMatchCertificate.exception.message"), ex);
        }

    }


    
/**
     * For a given X.509 certificate get a representative alias for it in a KeyStore.
     * For a self-signed certificate this will be the subject's common name (if
     * any).  For a non-self-signed certificate it will be the subject's common
     * name followed by the issuer's common name in brackets.  Alaises will
     * always be in lower case.
     *
     * 
@param cert The certificate
     * 
@return The alias or a blank string if none could be worked out
     
*/

    
public static String getCertificateAlias(X509Certificate cert)
    
{
        
// Get the subject and issuer distinguished names
        Principal subject = cert.getSubjectDN();
        Principal issuer 
= cert.getIssuerDN();

        
// Get the subject's common name
        String sSubject = subject.getName();
        String sSubjectCN 
= "";
        
int iCN = sSubject.indexOf("CN=");
        
if (iCN != -1)
        
{
            iCN 
+= 3;
            
int iEndCN = sSubject.indexOf("", iCN);
            
if (iEndCN != -1)
            
{
                sSubjectCN 
= sSubject.substring(iCN, iEndCN).toLowerCase();
            }

            
else
            
{
                sSubjectCN 
= sSubject.substring(iCN).toLowerCase();
            }

        }


        
// Get the issuer's common name
        String sIssuer = issuer.getName();
        String sIssuerCN 
= "";
        iCN 
= sIssuer.indexOf("CN=");
        
if (iCN != -1)
        
{
            iCN 
+= 3;
            
int iEndCN = sIssuer.indexOf("", iCN);
            
if (iEndCN != -1)
            
{
                sIssuerCN 
= sIssuer.substring(iCN, iEndCN).toLowerCase();
            }

            
else
            
{
                sIssuerCN 
= sIssuer.substring(iCN).toLowerCase();
            }

        }


        
// Could not get a subject CN - return blank
        if (sSubjectCN.length() == 0)
        
{
            
return "";
        }


        
// Self-signed certificate or could not get an issuer CN
        if ((subject.equals(issuer)) || (sIssuerCN.length() == 0))
        
{
            
// Alias is the subject CN
            return sSubjectCN;
        }

        
// Non-self-signed certificate
        else
        
{
            
// Alias is the subject CN followed by the issuer CN in brackets
            return MessageFormat.format("{0} ({1})"new String[]{sSubjectCN, sIssuerCN});
        }

    }


    
/**
     * For a given X.509 certificate get the keysize of its public key.
     *
     * 
@param cert The certificate
     * 
@return The keysize
     * 
@throws CryptoException If there is a problem getting the keysize
     
*/

    
public static int getCertificateKeyLength(X509Certificate cert)
        
throws CryptoException
    
{
        
try
        
{
            
// Get the certificate's public key
            PublicKey pubKey = cert.getPublicKey();

            
// Get the public key algorithm
            String sAlgorithm = pubKey.getAlgorithm();

            
// If the algorithm is RSA then use a KeyFactory to create an RSA public
            
// key spec and get the keysize from the modulus length in bits
            if (sAlgorithm.equals(KeyPairType.RSA.toString()))
            
{
                KeyFactory keyFact 
= KeyFactory.getInstance(sAlgorithm);
                RSAPublicKeySpec keySpec 
= (RSAPublicKeySpec)keyFact.getKeySpec(pubKey, RSAPublicKeySpec.class);
                BigInteger modulus 
= keySpec.getModulus();
                
return modulus.toString(2).length();
            }

            
// If the algorithm is RSA then use a KeyFactory to cretae an DSA public
            
// key spec and get the keysize from the prime length in bits
            else if (sAlgorithm.equals(KeyPairType.DSA.toString()))
            
{
                KeyFactory keyFact 
= KeyFactory.getInstance(sAlgorithm);
                DSAPublicKeySpec keySpec 
= (DSAPublicKeySpec)keyFact.getKeySpec(pubKey, DSAPublicKeySpec.class);
                BigInteger prime 
= keySpec.getP();
                
return prime.toString(2).length();
            }

            
// Otherwise cannot calculate keysize
            else
            
{
                
throw new CryptoException(MessageFormat.format(m_res.getString("NoCertificatePublicKeysizeUnrecogAlg.exception.message"), new Object[]{sAlgorithm}));
            }

        }

        
catch (GeneralSecurityException ex)
        
{
            
throw new CryptoException(m_res.getString("NoCertificatePublicKeysize.exception.message"), ex);
        }

    }

}




   
            

posted on 2006-04-29 09:38 david.turing 阅读(17315) 评论(13)  编辑  收藏 所属分类: Security领域

评论

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2006-05-25 21:18 tain198127

这个方法我是知道的。只是因为我上次的工程,需要输入的数据超过了117个字节,结果造成了异常,我以为是我的密钥长度不对,所以希望能够人工的算出密钥长度,不过还是很感谢你。
后来我才发现,原来是因为我输入的数据长度,超过了128个字节,而我使用的1024位的密钥,所以才造成了加密失败。不过你前面解释的证书体系还是非常不错的。再次感谢你。  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2006-05-29 22:54 david.turing

hehe, 你必须自己处理RSA的InBlock Size和OutBlock Size,1024bit的RSA加密算法,假定你用PKCS,需要使用117 inBlock->128 outBlock是必须遵循的,用128byte的输入显然是溢出了:)  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2006-06-26 19:45 cboys

看了你的blog上的很多文章,写的真不错,向你学习ing....

我现在遇到一个问题,希望你能帮帮我,已经捆饶我很久了。
我使用CryptoAPI通过CSP访问到usbkey,然后对一段数据进行签名,得到的签名值(好象是PKCS#7 ),然后我在服务器端验证签名,使用java语言,已经有证书,我得到证书里的公钥,被签名的明文我也有。为什么老是验证通不过呢,仔细看过代码(也让别人看过我的java代码)不应该有错。

我怀疑是不是通过CSP签名后的签名值和java验证签名时传入的签名值有差异。

你能帮我吗?
我的信箱是yangnan2004@163.com  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2006-08-03 06:49 可怜的人

我的证书密码忘了~~~导入不了~能帮我找找吗??

好心人,善良人,看到一定会帮我的~~我的QQ是:86661177

  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2006-08-03 09:27 openssl

cboys, 你的问题太经典了
原则上,如果你调用CAPI访问usbkey产生签名,签名是PKCS#7,Windows是little-endian, Java处理的是Big-endian的,你需要先通过BASE64处理一下签名,然后再发送到服务器。  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2006-08-03 09:29 openssl

pfx证书密码忘了,那没办法帮你啊  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2006-08-23 15:49 rom

没有密码怎么从 pfx 获取公钥?  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2006-12-04 14:31 起点[匿名]

写的非常不错,我也刚研究pki没多久  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2007-04-12 18:32 ggyy

向各位好心人请教个问题,我的.Pfx证书在导入的时侯提示:发生一个内部错误,导入的私钥需要一个加密服务提供程序,但系统上没有安装该程序。
我想知道我应该安装什么?拜谢诸位,  回复  更多评论   

# cer fil 2007-08-30 20:31 shi

请问有了一个p12文件,如何生成一个cer或crt文件,可以用p12来生成也可以自己生成,只要能生成cer文件即可.

需用JACA程序实现谢谢shichling@126.com  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2007-08-30 21:46 shi

3再将其转换为一个以X509证书结构体
这一条怎么实现? 即p12 -> cer/crt格式?  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2007-08-30 21:47 shi

3再将其转换为一个以X509证书结构体
如果可以请发送到 shichling@126.com, 谢谢  回复  更多评论   

# re: 如何从pfx/p12文件中提取RSA密钥长度及其他相关信息 2008-08-28 13:57 刘飞

太好了兄弟,找的就是这个,爱死你了!哈哈哈哈哈哈  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(110)

我参与的团队

随笔分类(126)

随笔档案(155)

文章分类(9)

文章档案(19)

相册

搜索

积分与排名

最新随笔

最新评论

阅读排行榜

评论排行榜