복붙노트

[SCALA] CSR은 탄력이 성을 사용하여 가입

SCALA

CSR은 탄력이 성을 사용하여 가입

나는 BC를 사용하여 CSR에 서명하는 방법을 설명하는 코드 / 문서를 찾을 수 없습니다. 입력으로 나는 바이트 배열로 CSR을 가지고 PEM 및 / 또는 DER 형식의 인증서를 좀하고 싶습니다.

나는 여기까지 입수했습니다

def signCSR(csrData:Array[Byte], ca:CACertificate, caPassword:String) = {
  val csr = new PKCS10CertificationRequestHolder(csrData)
  val spi = csr.getSubjectPublicKeyInfo

  val ks = new java.security.spec.X509EncodedKeySpec(spi.getDEREncoded())
  val kf = java.security.KeyFactory.getInstance("RSA")
  val pk = kf.generatePublic(ks)

  val (caCert, caPriv) = parsePKCS12(ca.pkcs12data, caPassword)

  val fromDate : java.util.Date = new java.util.Date // FixMe
  val toDate = fromDate // FixMe
  val issuer = PrincipalUtil.getIssuerX509Principal(caCert)
  val contentSigner = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(BC).build(caPriv)
  val serial = BigInt(CertSerialnumber.nextSerialNumber)
  val certgen = new JcaX509v3CertificateBuilder(new X500Name(issuer.getName), serial.bigInteger, fromDate, toDate, csr.getSubject, pk)

나는 PEM 또는 DER 형식이를 저장하는 인증서 발생기에서 GET을 알아내는 데 문제가 있습니다.

아니면 모두 함께 잘못된 길을 갈거야?

해결법

  1. ==============================

    1.좋아요 ... 나도 같은 물건을 찾고 있었어요 그리고 내 인생 내가 어떻게 알아낼 수 없었다. API를 모두 키 쌍을 생성하고 인증서를 생성하지만 어떻게 CSR에 서명하는 방법에 대해 이야기. 어떻게 든, 아주 우연히 - 여기에 내가 무엇을 발견.

    좋아요 ... 나도 같은 물건을 찾고 있었어요 그리고 내 인생 내가 어떻게 알아낼 수 없었다. API를 모두 키 쌍을 생성하고 인증서를 생성하지만 어떻게 CSR에 서명하는 방법에 대해 이야기. 어떻게 든, 아주 우연히 - 여기에 내가 무엇을 발견.

    PKCS10합니다 (CSR의) 요청의 형식을 나타 내기 때문에, 먼저 PKCS10Holder으로 CSR을 넣어해야합니다. (CertificateGenerator은 더 이상 사용되지 않기 때문에) 그런 다음 CertificateBuilder에 전달합니다. 당신이 그것을 전달하는 방법은 홀더의 getSubject를 호출하는 것입니다.

    여기에 코드 (자바 당신이 필요로하는, 적응주십시오)이다 :

    public static X509Certificate sign(PKCS10CertificationRequest inputCSR, PrivateKey caPrivate, KeyPair pair)
            throws InvalidKeyException, NoSuchAlgorithmException,
            NoSuchProviderException, SignatureException, IOException,
            OperatorCreationException, CertificateException {   
    
        AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder()
                .find("SHA1withRSA");
        AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder()
                .find(sigAlgId);
    
        AsymmetricKeyParameter foo = PrivateKeyFactory.createKey(caPrivate
                .getEncoded());
        SubjectPublicKeyInfo keyInfo = SubjectPublicKeyInfo.getInstance(pair
                .getPublic().getEncoded());
    
        PKCS10CertificationRequestHolder pk10Holder = new PKCS10CertificationRequestHolder(inputCSR);
        //in newer version of BC such as 1.51, this is 
        //PKCS10CertificationRequest pk10Holder = new PKCS10CertificationRequest(inputCSR);
    
        X509v3CertificateBuilder myCertificateGenerator = new X509v3CertificateBuilder(
                new X500Name("CN=issuer"), new BigInteger("1"), new Date(
                        System.currentTimeMillis()), new Date(
                        System.currentTimeMillis() + 30 * 365 * 24 * 60 * 60
                                * 1000), pk10Holder.getSubject(), keyInfo);
    
        ContentSigner sigGen = new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
                .build(foo);        
    
        X509CertificateHolder holder = myCertificateGenerator.build(sigGen);
        X509CertificateStructure eeX509CertificateStructure = holder.toASN1Structure(); 
        //in newer version of BC such as 1.51, this is 
        //org.spongycastle.asn1.x509.Certificate eeX509CertificateStructure = holder.toASN1Structure(); 
    
        CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
    
        // Read Certificate
        InputStream is1 = new ByteArrayInputStream(eeX509CertificateStructure.getEncoded());
        X509Certificate theCert = (X509Certificate) cf.generateCertificate(is1);
        is1.close();
        return theCert;
        //return null;
    }
    

    당신이 볼 수 있듯이,이 방법은 외부 요청을 생성하지만 인치 그럼,이 생성자의 인자로 이것을 받아 들일 수있는 PKCS10CertificationRequestHolder을 통과했습니다.

    이 모든 당신이 필요 명백하게 - 다음, X509v3CertificateBuilder 인수에, 당신은 pk10Holder.getSubject를 볼 수 있습니다? 뭔가가없는 경우 나 너무 알려 주시기 바랍니다! 그것은 나를 위해 일했습니다. 내가 생성 된 인증서가 올바르게 내가 필요한 DN 정보를 가지고 있었다.

    위키 백과는 PKCS에 킬러 섹션이 - http://en.wikipedia.org/wiki/PKCS

  2. ==============================

    2.다음 코드는 위의 답변을 기반으로하지만, 컴파일하고하는 PEM 인코딩 된 CSR을 주어, 유효한 PEM 인코딩 SignedData 오브젝트로 가져올 수있는 유형 (서명 인증서 체인을 포함 반환합니다 (키 도구로 내 보낸 가지) ) 키 도구로.

    다음 코드는 위의 답변을 기반으로하지만, 컴파일하고하는 PEM 인코딩 된 CSR을 주어, 유효한 PEM 인코딩 SignedData 오브젝트로 가져올 수있는 유형 (서명 인증서 체인을 포함 반환합니다 (키 도구로 내 보낸 가지) ) 키 도구로.

    아, 그리고 그것은 BouncyCastle 1.49에 있습니다.

    import java.security.*;
    import java.io.*;
    import java.util.Date;
    import java.math.BigInteger;
    import java.security.cert.X509Certificate;
    import org.bouncycastle.asn1.x509.*;
    import org.bouncycastle.asn1.x500.*;
    import org.bouncycastle.asn1.pkcs.*;
    import org.bouncycastle.openssl.*;
    import org.bouncycastle.pkcs.*;
    import org.bouncycastle.cert.*;
    import org.bouncycastle.cms.*;
    import org.bouncycastle.cms.jcajce.*;
    import org.bouncycastle.crypto.util.*;
    import org.bouncycastle.operator.*;
    import org.bouncycastle.operator.bc.*;
    import org.bouncycastle.operator.jcajce.*;
    import org.bouncycastle.util.encoders.Base64;
    
    /**
     * Given a Keystore containing a private key and certificate and a Reader containing a PEM-encoded
     * Certificiate Signing Request (CSR), sign the CSR with that private key and return the signed
     * certificate as a PEM-encoded PKCS#7 signedData object. The returned value can be written to a file
     * and imported into a Java KeyStore with "keytool -import -trustcacerts -alias subjectalias -file file.pem"
     *
     * @param pemcsr a Reader from which will be read a PEM-encoded CSR (begins "-----BEGIN NEW CERTIFICATE REQUEST-----")
     * @param validity the number of days to sign the Certificate for
     * @param keystore the KeyStore containing the CA signing key
     * @param alias the alias of the CA signing key in the KeyStore
     * @param password the password of the CA signing key in the KeyStore
     *
     * @return a String containing the PEM-encoded signed Certificate (begins "-----BEGIN PKCS #7 SIGNED DATA-----")
     */
    public static String signCSR(Reader pemcsr, int validity, KeyStore keystore, String alias, char[] password) throws Exception {
        PrivateKey cakey = (PrivateKey)keystore.getKey(alias, password);
        X509Certificate cacert = (X509Certificate)keystore.getCertificate(alias);
        PEMReader reader = new PEMReader(pemcsr);
        PKCS10CertificationRequest csr = new PKCS10CertificationRequest((CertificationRequest)reader.readObject());
    
        AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA");
        AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
        X500Name issuer = new X500Name(cacert.getSubjectX500Principal().getName());
        BigInteger serial = new BigInteger(32, new SecureRandom());
        Date from = new Date();
        Date to = new Date(System.currentTimeMillis() + (validity * 86400000L));
    
        X509v3CertificateBuilder certgen = new X509v3CertificateBuilder(issuer, serial, from, to, csr.getSubject(), csr.getSubjectPublicKeyInfo());
        certgen.addExtension(X509Extension.basicConstraints, false, new BasicConstraints(false));
        certgen.addExtension(X509Extension.subjectKeyIdentifier, false, new SubjectKeyIdentifier(csr.getSubjectPublicKeyInfo()));
        certgen.addExtension(X509Extension.authorityKeyIdentifier, false, new AuthorityKeyIdentifier(new GeneralNames(new GeneralName(new X509Name(cacert.getSubjectX500Principal().getName()))), cacert.getSerialNumber()));
    
        ContentSigner signer = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(PrivateKeyFactory.createKey(cakey.getEncoded()));
        X509CertificateHolder holder = certgen.build(signer);
        byte[] certencoded = holder.toASN1Structure().getEncoded();
    
        CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
        signer = new JcaContentSignerBuilder("SHA1withRSA").build(cakey);
        generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(signer, cacert));
        generator.addCertificate(new X509CertificateHolder(certencoded));
        generator.addCertificate(new X509CertificateHolder(cacert.getEncoded()));
        CMSTypedData content = new CMSProcessableByteArray(certencoded);
        CMSSignedData signeddata = generator.generate(content, true);
    
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        out.write("-----BEGIN PKCS #7 SIGNED DATA-----\n".getBytes("ISO-8859-1"));
        out.write(Base64.encode(signeddata.getEncoded()));
        out.write("\n-----END PKCS #7 SIGNED DATA-----\n".getBytes("ISO-8859-1"));
        out.close();
        return new String(out.toByteArray(), "ISO-8859-1");
    }
    
  3. ==============================

    3.아치 감사합니다!

    아치 감사합니다!

    난 당신의 코드에 약간의 변경을, 아래를 참조하십시오.

    주요 변경 사항은 발행자의 이름을 전달하고, CSR의 공개 키를 사용한다.

    val caCert = PEMToCert(issuerPEM).get
    val issuer = PrincipalUtil.getIssuerX509Principal(caCert)
    val csr = new PKCS10CertificationRequestHolder(csrData)
    val serial = BigInt(CertSerialNumber.nextSerialNumber)
    val spi = csr.getSubjectPublicKeyInfo();
    
    val certgen = new X509v3CertificateBuilder(
        new X500Name(issuer.getName),
        serial.bigInteger,
        new java.util.Date(),
        new Date(System.currentTimeMillis() + 30 * 365 * 24 * 60 * 60 * 1000),
        csr.getSubject,
        csr.getSubjectPublicKeyInfo())
    
    certgen.addExtension(
        X509Extension.subjectKeyIdentifier,
        false,
        spi
    )
    
    val issuerPK = PEMToPK(issuerPKPEM, caPassword).get
    val contentSigner = new JcaContentSignerBuilder(contentSignerAlg).setProvider(BC).build(issuerPK.getPrivate())
    val x509 = (new JcaX509CertificateConverter).setProvider(BC).getCertificate(certgen.build(contentSigner))
    
  4. ==============================

    4.결국, 이것은 나를 위해 일한 것입니다 :

    결국, 이것은 나를 위해 일한 것입니다 :

    KeyPair serverKeyPair = keyPairLoader.getKeyPair(); //my own class
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC");
    X509Certificate serverCertificate = getServerCertificate(certificateFactory);
    
    org.spongycastle.asn1.x509.Certificate eeX509CertificateStructure = signCertificateSigningRequest(
      jcaPKCS10CertificationRequest, keyPair, serverCertificate);
    
    java.security.cert.X509Certificate signedCertificate = readCertificateFromASN1Certificate(
      eeX509CertificateStructure, certificateFactory);
    

    어디 코드가

      private org.spongycastle.asn1.x509.Certificate signCertificateSigningRequest(
        JcaPKCS10CertificationRequest jcaPKCS10CertificationRequest,
        KeyPair keyPair, X509Certificate serverCertificate)
          throws IOException, OperatorCreationException, NoSuchAlgorithmException, InvalidKeyException
      {
        // Signing CSR
        AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder()
          .find("SHA1withRSA");
    
        X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder(
            serverCertificate, 
            new BigInteger("1"), //serial
            new Date(System.currentTimeMillis()),
            new Date(System.currentTimeMillis() + 30L * 365L * 24L * 60L * 60L * 1000L),
            jcaPKCS10CertificationRequest.getSubject(),
            jcaPKCS10CertificationRequest.getPublicKey()
        /*).addExtension(
            new ASN1ObjectIdentifier("2.5.29.35"),
            false,
            new AuthorityKeyIdentifier(keyPair.getPublic().getEncoded())*/
        ).addExtension(
                new ASN1ObjectIdentifier("2.5.29.19"),
                false,
                new BasicConstraints(false) // true if it is allowed to sign other certs
        ).addExtension(
                new ASN1ObjectIdentifier("2.5.29.15"),
                true,
                new X509KeyUsage(
                    X509KeyUsage.digitalSignature |
                        X509KeyUsage.nonRepudiation   |
                        X509KeyUsage.keyEncipherment  |
                        X509KeyUsage.dataEncipherment));
    
        AsymmetricKeyParameter asymmetricKeyParameter =
              PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
        //ContentSigner sigGen = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(asymmetricKeyParameter);
        ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withRSA").build(keyPair.getPrivate());
    
    
        X509CertificateHolder x509CertificateHolder = certificateBuilder.build(sigGen);
        org.spongycastle.asn1.x509.Certificate eeX509CertificateStructure =
          x509CertificateHolder.toASN1Structure();
        return eeX509CertificateStructure;
      }
    
      private X509Certificate readCertificateFromASN1Certificate(
        org.spongycastle.asn1.x509.Certificate eeX509CertificateStructure,
        CertificateFactory certificateFactory)
        throws IOException, CertificateException {
        // Read Certificate
        InputStream is1 = new ByteArrayInputStream(eeX509CertificateStructure.getEncoded());
        X509Certificate signedCertificate =
          (X509Certificate) certificateFactory.generateCertificate(is1);
        return signedCertificate;
      }
    

    그리고 이것은 PEM로 변환 할 수 있습니다 :

      private String convertCertificateToPEM(X509Certificate signedCertificate) throws IOException {
        StringWriter signedCertificatePEMDataStringWriter = new StringWriter();
        JcaPEMWriter pemWriter = new JcaPEMWriter(signedCertificatePEMDataStringWriter);
        pemWriter.writeObject(signedCertificate);
        pemWriter.close();
        log.info("PEM data:");
        log.info("" + signedCertificatePEMDataStringWriter.toString());
        return signedCertificatePEMDataStringWriter.toString();
      }
    
  5. ==============================

    5.B @ 마이크 - 당신이 철저하게 예를 테스트 한? 난 당신의 코드로 이상한 행동을 얻을 : 임 버전을 bc15on 사용. 나는 자체 서명 CA와 클라이언트 요청에 서명 할 때 나는 IE에서 그것을 가져 와서는 체인의 CA와 유효한 인증서를 보여줍니다

    B @ 마이크 - 당신이 철저하게 예를 테스트 한? 난 당신의 코드로 이상한 행동을 얻을 : 임 버전을 bc15on 사용. 나는 자체 서명 CA와 클라이언트 요청에 서명 할 때 나는 IE에서 그것을 가져 와서는 체인의 CA와 유효한 인증서를 보여줍니다

    그러나 당신은 FF에서 가져올 때 체인의 CA가없는 오른쪽 이미지와 FF가 신뢰할 수있는 기관으로 확인할 수없는 것을 볼 수 있습니다. 또한 너무 신뢰할 수있는 기관에 검증 할 수 HTTP로 실패 그것으로 웹 서버에 인증을 시도 할 때 IE 또는 FF로.

    난 그냥 내 요구에 맞게 그러나 일반적으로이 사람이 나에게 임 잘못 여기에 뭘에 대한 몇 가지 포인터를 제공 할 수 있습니다, 동일해야합니다 코드의 일부를 변경했습니다 :

        public static String GenCert(long SerNum, int addYear, int addHours,
                                 String reqText,
                                 String reqName) throws Exception,
                                                        SQLException {
    
        String result = "";
        reqText = csr; // hard code base64 csr for testing purposes
        reqText =
            "-----BEGIN CERTIFICATE REQUEST-----\n" + reqText +
            "\n-----END CERTIFICATE REQUEST-----\n";
    
        try {
    
    
            String castr = ca + "\n"; // hard code base64 CA pub key for testing
            String strPriv = caPrivk + "\n"; // hard code base64 CA private key for testing
    
    
            byte[] encKey = castr.getBytes();
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate caCert =
                (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(encKey));
    
            PEMParser pr = new PEMParser(new StringReader(strPriv));
            Object obj = pr.readObject();
            JcaPEMKeyConverter converter =
                new JcaPEMKeyConverter().setProvider("BC");
            KeyPair kp;
            kp = converter.getKeyPair((PEMKeyPair)obj);
    
            PrivateKey privateKey = kp.getPrivate();
    
            // parse the request
            PEMParser pRd =
                new PEMParser(new InputStreamReader(new ByteArrayInputStream(reqText.getBytes())));
            PKCS10CertificationRequest csr =
                (PKCS10CertificationRequest)pRd.readObject();
    
            String strReq = csr.getSubject().toString();
    
            strReq = strReq.substring(strReq.indexOf("CN=") + 3).trim();
            if (strReq.indexOf(",") > 0)
                strReq = strReq.substring(0, strReq.indexOf(",")).trim();
            if (!strReq.equals(reqName)) {
                return "";
            }
    
            AlgorithmIdentifier sigAlgId =
                new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA"); //SHA1withRSA
            AlgorithmIdentifier digAlgId =
                new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
            X500Name issuer =
                new X500Name(caCert.getSubjectX500Principal().getName());
            BigInteger serial = BigInteger.valueOf(SerNum);
    
            // The date object returns GMT format
            Date date = new Date(System.currentTimeMillis() - 180 * 1000);
            date.setHours(date.getHours() + addHours);
            Calendar cal = Calendar.getInstance();
            Date from = date;
            cal.setTime(date);
            cal.add(1, addYear);
            Date to = cal.getTime();
    
            SubjectPublicKeyInfo pkInfo = csr.getSubjectPublicKeyInfo();
            //SubjectPublicKeyInfo pkInfo = SubjectPublicKeyInfo.getInstance(kp.getPublic().getEncoded());
            RSAKeyParameters rsa =
                (RSAKeyParameters)PublicKeyFactory.createKey(pkInfo);
            RSAPublicKeySpec rsaSpec =
                new RSAPublicKeySpec(rsa.getModulus(), rsa.getExponent());
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PublicKey rsaPub = kf.generatePublic(rsaSpec);
    
    
            X509v3CertificateBuilder certgen =
                new X509v3CertificateBuilder(issuer, serial, from, to,
                                             csr.getSubject(),
                                             csr.getSubjectPublicKeyInfo());
    
            certgen.addExtension(X509Extension.basicConstraints, false,
                                 new BasicConstraints(false));
            certgen.addExtension(X509Extension.subjectKeyIdentifier, false,
                                 new SubjectKeyIdentifier(pkInfo));
            //            certgen.addExtension(X509Extension.subjectKeyIdentifier, false,
            //                                 new SubjectKeyIdentifierStructure(rsaPub)); // In old version done with much more extensive parsing
            certgen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
                                 new AuthorityKeyIdentifierStructure(caCert));
            //            certgen.addExtension(X509Extension.authorityKeyIdentifier, false,
            //                                 new AuthorityKeyIdentifier(new GeneralNames(new GeneralName(new X509Name(caCert.getSubjectX500Principal().getName()))),
            //                                                            caCert.getSerialNumber()));
    
            // add certificate purposes
            ASN1EncodableVector vector = new ASN1EncodableVector();
            vector.add(new DERObjectIdentifier("1.3.6.1.5.5.7.3.2"));
            vector.add(new DERObjectIdentifier("1.3.6.1.4.1.311.20.2.2"));
            vector.add(new DERObjectIdentifier("1.3.6.1.4.1.311.10.3.12"));
            vector.add(new DERObjectIdentifier("1.3.6.1.5.5.7.3.4"));
    
    
            DERSequence seq = new DERSequence(vector);
            certgen.addExtension(X509Extensions.ExtendedKeyUsage, false, seq);
    
    
            ContentSigner signer =
                new BcRSAContentSignerBuilder(sigAlgId,
                                              digAlgId).build(PrivateKeyFactory.createKey(privateKey.getEncoded()));
            X509CertificateHolder holder = certgen.build(signer);
            byte[] certencoded = holder.toASN1Structure().getEncoded();
    
            CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
            signer =
                new JcaContentSignerBuilder("SHA1withRSA").build(privateKey);
            generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(signer,
                                                                                                                                       caCert));
            generator.addCertificate(new X509CertificateHolder(certencoded));
            generator.addCertificate(new X509CertificateHolder(caCert.getEncoded()));
            CMSTypedData content = new CMSProcessableByteArray(certencoded);
            CMSSignedData signeddata = generator.generate(content, true);
    
            result = Base64Utils.base64Encode(signeddata.getEncoded());
    
        } catch (Exception e) {
            result = e.toString();
            getStackTrace(e);
        }
        return result;
    }
    

    나는 탄력이 성 1.4 우리는 X509V3CertificateGenerator을 사용하고 바로 내용을 반환하기 전에 우리가 같이 체인을 구축하는 데 사용 내 코드의 이전 버전에서 :

                X509Certificate newCert =
                certGen.generateX509Certificate(privateKey, "BC");
            //=============================
            List chain = new ArrayList();
            chain.add(newCert);
            //-------------------------------------------------
            //  create the CertPath with old BouncyCastle
            CertificateFactory fact =
                CertificateFactory.getInstance("X.509", "BC");
            CertPath path = fact.generateCertPath(chain);
            result = Base64Utils.base64Encode(path.getEncoded("PKCS7"));
    

    UPDATE : OK 케이스 해결했다. 사용 분명히이 스레드에 감사 :

    cacert.getSubjectX500Principal (). getName ()

    내가 사용하는 대신, 체인을 깨고 역으로 발행자의 이름을 가지고 :

    cert.getSubjectX500Principal ().의 getEncoded ()는 나를 위해 그것을 해결! 당신의 CA가 신뢰할 수있는 기관 개까지 확인되지 않는 경우에 따라서는 이름을 제대로 받고 있는지 확인하십시오.

  6. from https://stackoverflow.com/questions/7230330/sign-csr-using-bouncy-castle by cc-by-sa and MIT license