[SCALA] CSR은 탄력이 성을 사용하여 가입
SCALACSR은 탄력이 성을 사용하여 가입
나는 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.좋아요 ... 나도 같은 물건을 찾고 있었어요 그리고 내 인생 내가 어떻게 알아낼 수 없었다. 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.다음 코드는 위의 답변을 기반으로하지만, 컴파일하고하는 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.아치 감사합니다!
아치 감사합니다!
난 당신의 코드에 약간의 변경을, 아래를 참조하십시오.
주요 변경 사항은 발행자의 이름을 전달하고, 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.결국, 이것은 나를 위해 일한 것입니다 :
결국, 이것은 나를 위해 일한 것입니다 :
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.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가 신뢰할 수있는 기관 개까지 확인되지 않는 경우에 따라서는 이름을 제대로 받고 있는지 확인하십시오.
from https://stackoverflow.com/questions/7230330/sign-csr-using-bouncy-castle by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 어떻게 스칼라의 () 메소드 마법의 작업을 적용됩니까? (0) | 2019.11.03 |
---|---|
[SCALA] 때 스칼라의 특성에 발 또는 데프를 사용 하는가? (0) | 2019.11.03 |
[SCALA] 어떻게 로컬 받는다는 프록시 저장소 (넥서스)를 사용하는 SBT받을 수 있나요? (0) | 2019.11.03 |
[SCALA] 스칼라에서 정규 표현식을 사용하는 방법 패턴 일치에? (0) | 2019.11.03 |
[SCALA] 스칼라 함수의 일부인가 대 무두질 (0) | 2019.11.03 |