2016-02-18 2 views
0

Я искал последние несколько дней для решения моей проблемы и ничего не нашел. Я пропустил что-то в своем коде, но я не могу понять, что :(Как-то, когда я подписываю PKCS # 10, цепочка сломана.Знак CSR с BouncyCastle

В основном у меня есть сервер и клиент. Я хочу, чтобы клиент отправил CSR к серверу, и сервер подписывает его, чтобы они могли общаться. Теперь я настроил PKCS # 12 с BouncyCastle для Клиента, и я установил RootCertificate для сервера (опять же с BouncyCastle, что, по моему мнению, просто PKCS # 12 с расширением, чтобы иметь возможность подписывать сертификаты) в кодексе это выглядит следующим образом:

Provider BC = new BouncyCastleProvider(); 
Security.addProvider(BC); 
//create KeyPair 
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC"); 
kpGen.initialize(2048, new SecureRandom()); 
pair = kpGen.generateKeyPair(); 
//building groundbase for certificate 
X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE); 
builder.addRDN(BCStyle.CN, commonName); 
builder.addRDN(BCStyle.OU, organizationalUnit); 
builder.addRDN(BCStyle.O, organization); 
builder.addRDN(BCStyle.L, city); 
builder.addRDN(BCStyle.ST, state); 
builder.addRDN(BCStyle.C, country); 
Date notBefore = new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24); //Yesterday 
Date notAfter = new Date(System.currentTimeMillis() + 1000L * 365L * 24L * 60L * 60L); //in a year 
BigInteger serial = BigInteger.valueOf(new SecureRandom().nextLong()); 
//creating a self-signed certificate from information in builder 
X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), 
serial, notBefore, notAfter, builder.build(), pair.getPublic()); 

//The next line will make the difference between a Certificate and a Ca Certificate 
certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(true)); 

ContentSigner sigGen = new JcaContentSignerBuilder(").setProvider(BC).build(pair.getPrivate()); 
X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen)); 

Теперь я создать CSR для клиента (Client хранилище ключей имеет только что создали PKCS # 12 в первой позиции):

String alias = keystore.aliases().nextElement(); 
X509Certificate cert = (X509Certificate) keystore.getCertificate(alias); 
X500Name x500name = new JcaX509CertificateHolder(cert).getSubject(); 
//builder for the PKCS10 
PKCS10CertificationRequestBuilder requestBuilder = new JcaPKCS10CertificationRequestBuilder(x500name, cert.getPublicKey()); 
//algorithm identifier 
DefaultSignatureAlgorithmIdentifierFinder sigAlgFinder = new DefaultSignatureAlgorithmIdentifierFinder(); 
DefaultDigestAlgorithmIdentifierFinder digAlgFinder = new DefaultDigestAlgorithmIdentifierFinder(); 
AlgorithmIdentifier sigAlgId = sigAlgFinder.find("SHA512WithRSA"); 
digAlgFinder.find(sigAlgId); 
//content Signer 
JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder("SHA512WithRSA"); 
//and build the Cert 
ContentSigner signer = contentSignerBuilder.build((PrivateKey) keystore.getKey(alias, password)); 
PKCS10CertificationRequest req = requestBuilder.build(signer); 
JcaPKCS10CertificationRequest req2 = new JcaPKCS10CertificationRequest(req.getEncoded()).setProvider("BC"); 

Я отправляю этот JcaPKCS10CertificationRequest, закодированный по сети. Сервер получает его и создает свой сертификат CA, а теперь должен подписать PKCS # 10, но я что-то пропустил, потому что он не включает цепочку. Созданный им сертификат содержит информацию об эмитенте и BasicConstraints, но путь сертификации включает только сертификат клиентов, а не сертификат сервера, поэтому он не заслуживает доверия, так как цепочка не работает.

Это то, что я делаю (Server Keystore имеет сертификат ЦС в положении 0, CSR является JcaPKCS10CertificationRequest):

String alias = keystore.aliases().nextElement(); 
// PKCS#12 Root Certificate 
X509Certificate cert = (X509Certificate) keystore.getCertificate(alias); 
// generated Serial 
BigInteger serial = BigInteger.valueOf(new SecureRandom().nextLong()); 
//identify algorithm 
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA512WithRSA"); 
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); 

JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); 
JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(cert, serial, cert.getNotBefore(), cert.getNotAfter(), 
      CSR.getSubject(), CSR.getPublicKey()); 
certGen.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(cert)); 

certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(false)); 
certGen.addExtension(Extension.subjectKeyIdentifier, true, extUtils.createSubjectKeyIdentifier(inputCSR.getPublicKey())); 
certGen.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.dataEncipherment | KeyUsage.nonRepudiation)); 
ContentSigner signer = new JcaContentSignerBuilder(sigAlgName).setProvider("BC").build((PrivateKey)keystore.getKey(alias, password)); 
X509CertificateHolder holder = certGen.build(signer); 
X509Certificate signedCert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(holder); 
signedCert.verify(cert.getPublicKey()); 
JcaPEMWriter pemWriter = new JcaPEMWriter(new FileWriter(new File("cer.cer"))); 
pemWriter.writeObject(signedCert); 
pemWriter.writeObject(cert); 
pemWriter.close(); 

Теперь, как я сказал, сгенерированный файл «cer.cer» не имеет цепи в Это. Как я могу добавить цепочку? Могу ли я затем отправить этот signedCert обратно клиенту и его можно использовать в ssl рукопожатии?

ответ

0

Чтобы добавить цепочку, это работает для меня

После X509CertificateHolder holder = certGen.build(signer);

byte[] certencoded = holder.toASN1Structure().getEncoded(); 
    ContentSigner signer = new JcaContentSignerBuilder("SHA1withRSA").build(caPrivateKkey); 
    CMSSignedDataGenerator generator = new CMSSignedDataGenerator(); 
    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); 

    byte certificateP7b[] = signedData.getEncoded(); 

С помощью этого кода вы получите сертификат с полной цепи в PCKS # 7 формате. Если вы предпочитаете работать с форматом X509

public static List<X509Certificate> p7BToX509(byte signedCert[]) throws CertificateException{ 
    ByteArrayInputStream is = new ByteArrayInputStream(signedCert); 
    CertificateFactory cf = CertificateFactory.getInstance("X.509"); 

    ArrayList<X509Certificate> certificates = new ArrayList<X509Certificate>(); 
    Iterator i = cf.generateCertificates(is).iterator(); 
    while (i.hasNext()){ 
     X509Certificate c = (X509Certificate)i.next(); 
     certificates.add(c); 

    } 
    return certificates; 

} 

Это общедоступный сертификат. В вашем клиенте у вас должен быть закрытый ключ. Это все элементы, необходимые для выполнения и ssl рукопожатие

Смежные вопросы