2016-09-27 115 views
0

我有一些奇怪的要求,我必须忍受。我需要将我的加密系统通过一个TBS证书,他们将签名并发回一个我需要加入证书的签名字符串以制作签名证书。向证书添加签名

看看com.ibm.security.x509.X509CertImpl和SO上的各种BouncyCastle帖子,我找不到如何做到这一点。

问题:

这可能吗? 如果是这样,怎么样?

回答

0

我会参考BouncyCastle X509v3CertificateBuilder类(pkix jar)的源代码,并调整它以适应您的需求。请注意,此类使用V3TBSCertificateGenerator生成TBSCertificate。这是您可以编码的ASN.1对象。然后你可以得到由“密码系统”签名的DER编码。然后参考X509v3CertificateBuilder.build()方法,了解如何将TBS证书和签名放在最终的X.509证书中。

0

我已经放在一起的一个例子,显示了一种方法来做到这一点。大部分代码都是从bouncycastle pkix或lwcrypto库中窃取的,但是任何错误几乎都是我的。下面关注的最重要的方法是generateCert。其余的代码是用于驱动测试的测试工具。

该代码是专门编写只需要bounycastle bcpkix和lwcrypto罐子。如果使用bcprov jar而不是lwcrypto,它可能会缩短一些。

import org.bouncycastle.asn1.ASN1EncodableVector; 
import org.bouncycastle.asn1.DERBitString; 
import org.bouncycastle.asn1.DERSequence; 
import org.bouncycastle.asn1.x500.X500Name; 
import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 
import org.bouncycastle.asn1.x509.TBSCertificate; 
import org.bouncycastle.cert.X509CertificateHolder; 
import org.bouncycastle.cert.bc.BcX509v3CertificateBuilder; 
import org.bouncycastle.crypto.params.RSAKeyParameters; 
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; 
import org.bouncycastle.operator.ContentSigner; 
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; 
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; 
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; 

import javax.security.auth.x500.X500Principal; 
import java.io.ByteArrayInputStream; 
import java.math.BigInteger; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.PublicKey; 
import java.security.cert.CertificateFactory; 
import java.security.cert.X509Certificate; 
import java.security.interfaces.RSAPrivateCrtKey; 
import java.security.interfaces.RSAPublicKey; 
import java.util.Date; 

public class Main { 

    private static class TBSCertPlusSignature { 
     private final byte[] encodedTbsCert; 
     private final byte[] signature; 

     public TBSCertPlusSignature(byte[] encodedTbsCert, byte[] signature) { 
      this.encodedTbsCert = encodedTbsCert; 
      this.signature = signature; 
     } 

     public byte[] getEncodedTbsCert() { 
      return encodedTbsCert; 
     } 

     public byte[] getSignature() { 
      return signature; 
     } 
    } 

    private static TBSCertPlusSignature makeTestCert(KeyPair keyPair) throws Exception { 
     Date now = new Date(); 
     Date nowPlus1Hour = new Date(now.getTime() + 1000 * 60 * 60 * 1L); 
     byte[] encodedName = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US").getEncoded(); 
     X500Name issuer = X500Name.getInstance(encodedName); 
     X500Name subject = issuer; 
     RSAPublicKey rsaPub = (RSAPublicKey) keyPair.getPublic(); 
     RSAKeyParameters rsaPubParams = new RSAKeyParameters(false, rsaPub.getModulus(), rsaPub.getPublicExponent()); 
     BcX509v3CertificateBuilder certBuilder = new BcX509v3CertificateBuilder(
       issuer, 
       BigInteger.valueOf(100L), 
       now, 
       nowPlus1Hour, 
       subject, 
       rsaPubParams 
     ); 


     AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSA"); 
     AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); 
     RSAPrivateCrtKey rsaPriv = (RSAPrivateCrtKey) keyPair.getPrivate(); 
     RSAPrivateCrtKeyParameters rsaPrivParams = new RSAPrivateCrtKeyParameters(
       rsaPriv.getModulus(), 
       rsaPriv.getPublicExponent(), 
       rsaPriv.getPrivateExponent(), 
       rsaPriv.getPrimeP(), 
       rsaPriv.getPrimeQ(), 
       rsaPriv.getPrimeExponentP(), 
       rsaPriv.getPrimeExponentQ(), 
       rsaPriv.getCrtCoefficient() 
     ); 

     ContentSigner contentSigner = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(rsaPrivParams); 
     final X509CertificateHolder x509CertificateHolder = certBuilder.build(contentSigner); 
     byte[] tbsCertDER = x509CertificateHolder.toASN1Structure().getTBSCertificate().getEncoded(); 
     byte[] signature = x509CertificateHolder.getSignature(); 
     return new TBSCertPlusSignature(tbsCertDER, signature); 
    } 


    private static X509Certificate generateCert(byte[] tbsCertEncoded, byte[] signature) throws Exception { 
     // Given the der encoded TBS cert and signature, create the corresponding X509 certificate 

     TBSCertificate tbsCert = TBSCertificate.getInstance(tbsCertEncoded); 

     ASN1EncodableVector v = new ASN1EncodableVector(); 

     v.add(tbsCert); 
     v.add(tbsCert.getSignature()); 
     v.add(new DERBitString(signature)); 

     DERSequence derSequence = new DERSequence(v); 
     ByteArrayInputStream baos = new ByteArrayInputStream(derSequence.getEncoded()); 
     return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(baos); 
    } 


    public static void main(String[] args) throws Exception { 

     KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 
     kpg.initialize(1024); 
     KeyPair keyPair = kpg.generateKeyPair(); 

     TBSCertPlusSignature testData = makeTestCert(keyPair); 

     X509Certificate x509Cert = generateCert(testData.getEncodedTbsCert(), testData.getSignature()); 

     // Verify the signature 

     x509Cert.verify(keyPair.getPublic()); 

     // Print the cert 

     PublicKey publicKey = x509Cert.getPublicKey(); 
     System.out.println(x509Cert); 

    } 
}