代码之家  ›  专栏  ›  技术社区  ›  Yuliy

在没有BouncyCastle的Java中创建X509证书?

  •  31
  • Yuliy  · 技术社区  · 15 年前

    X509V*CertificateGenerator 上课?

    5 回复  |  直到 5 年前
        1
  •  83
  •   vbence    8 年前

    是的,但不是公开记录的类。我已经记录了这个过程 in this article .

    import sun.security.x509.*;
    import java.security.cert.*;
    import java.security.*;
    import java.math.BigInteger;
    import java.util.Date;
    import java.io.IOException
    
    /** 
     * Create a self-signed X.509 Certificate
     * @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
     * @param pair the KeyPair
     * @param days how many days from now the Certificate is valid for
     * @param algorithm the signing algorithm, eg "SHA1withRSA"
     */ 
    X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
      throws GeneralSecurityException, IOException
    {
      PrivateKey privkey = pair.getPrivate();
      X509CertInfo info = new X509CertInfo();
      Date from = new Date();
      Date to = new Date(from.getTime() + days * 86400000l);
      CertificateValidity interval = new CertificateValidity(from, to);
      BigInteger sn = new BigInteger(64, new SecureRandom());
      X500Name owner = new X500Name(dn);
     
      info.set(X509CertInfo.VALIDITY, interval);
      info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
      info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
      info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
      info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
      info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
      AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
      info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
     
      // Sign the cert to identify the algorithm that's used.
      X509CertImpl cert = new X509CertImpl(info);
      cert.sign(privkey, algorithm);
     
      // Update the algorith, and resign.
      algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
      info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
      cert = new X509CertImpl(info);
      cert.sign(privkey, algorithm);
      return cert;
    }   
    
        2
  •  20
  •   erickson    15 年前

    签署证书的能力不是标准Java库或扩展的一部分。

    自己实现这一点并不简单,但绝对是可行的——第一次为证书签名制作工作原型时,我可能花了整整4到5天的时间。这是一场灾难

        3
  •  12
  •   Clark Hobbie    7 年前
    import sun.security.x509.*;
    
    import java.security.cert.*;
    import java.security.*;
    import java.math.BigInteger;
    import java.security.cert.Certificate;
    import java.util.Date;
    import java.io.IOException;
    
    public class Example {
        /**
         * Create a self-signed X.509 Example
         *
         * @param dn        the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
         * @param pair      the KeyPair
         * @param days      how many days from now the Example is valid for
         * @param algorithm the signing algorithm, eg "SHA1withRSA"
         */
        public X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
                throws GeneralSecurityException, IOException {
            PrivateKey privkey = pair.getPrivate();
            X509CertInfo info = new X509CertInfo();
            Date from = new Date();
            Date to = new Date(from.getTime() + days * 86400000l);
            CertificateValidity interval = new CertificateValidity(from, to);
            BigInteger sn = new BigInteger(64, new SecureRandom());
            X500Name owner = new X500Name(dn);
    
            info.set(X509CertInfo.VALIDITY, interval);
            info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
            info.set(X509CertInfo.SUBJECT, owner);
            info.set(X509CertInfo.ISSUER, owner);
            info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
            info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
            AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
            info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
    
            // Sign the cert to identify the algorithm that's used.
            X509CertImpl cert = new X509CertImpl(info);
            cert.sign(privkey, algorithm);
    
            // Update the algorith, and resign.
            algo = (AlgorithmId) cert.get(X509CertImpl.SIG_ALG);
            info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
            cert = new X509CertImpl(info);
            cert.sign(privkey, algorithm);
            return cert;
        }
    
        public static void main (String[] argv) throws Exception {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            Example example = new Example();
            String distinguishedName = "CN=Test, L=London, C=GB";
            Certificate certificate = example.generateCertificateOriginal(distinguishedName, keyPair, 365, "SHA256withRSA");
            System.out.println("it worked!");
        }
    }
    

    我喜欢vbence的答案,但我一直得到以下例外:

    java.security.cert.CertificateException:主题类类型无效。

    一个有效的主题类,我发现X509CerInfo需要一个X500Name的实例。

    1 info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
    2 info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
    3 info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
    4 info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
    

    因此,第2及;3需要更改为

    2 info.set(X509CertInfo.SUBJECT, owner);
    3 info.set(X509CertInfo.ISSUER, owner);
    
        4
  •  4
  •   ZZ Coder    15 年前

    JRE中提供了生成自签名证书(签名、X509编码等)的所有基本组件。与BC不同,Sun的JCE不提供任何公共调用来签署证书。但是,所有功能都可以在Keytool中使用。您只需从keytool复制代码即可完成此操作。您需要复制的方法是 doSelfCert()

        5
  •  1
  •   Von    15 年前

    这取决于你到底想做什么(可能还取决于你对“理智”的定义)。正如ZZ Coder所指出的,您可以通过复制直接创建自签名证书 keytool . 但我不相信可以使用标准JCE创建PKCS10证书请求对象,如果想要创建标准的CA签名EEC,可能需要这样做。

    推荐文章