2012-03-30 11 views
6

का उपयोग कर X509 प्रमाण पत्र जेनरेट करना मैं ऐप इंजन पर चलाने के लिए JXTA पोर्ट करने का प्रयास कर रहा हूं। यह देखते हुए कि बाउंसीकास्टल "बीसी" प्रदाता अभी तक ऐप इंजन पर समर्थित नहीं है, मुझे सफेद-सूचीबद्ध कक्षाओं का उपयोग करके X509 प्रमाण पत्र उत्पन्न करने के लिए मौजूदा JXTA कोड को पोर्ट करना होगा। क्रिप्टो का मेरा ज्ञान न्यूनतम है और मुझे यकीन नहीं है कि जो भी मैं पूरा करने की कोशिश कर रहा हूं वह भी संभव है। विधि मेंबाउंसीकैसल X509v3CertificateBuilder

public static class IssuerInfo { 
    public X509Certificate cert; // subject Cert 
    public PrivateKey subjectPkey; // subject private key 
    public X509Certificate issuer; // issuer Cert 
    public PrivateKey issuerPkey; // issuer private key 
} 

:

PSEUtils.java

वहाँ एक सहायक वर्ग जो java.security.cert.X509Certificate शामिल है: यहाँ JXTA परियोजना से PSEUtils.java से मूल कोड है :

public static IssuerInfo genCert(X500Principal subject, KeyPair keypair, IssuerInfo issuerinfo) 

मैं के रूप में इस विषय में गुजर रही है:

012,351,641 (मूल कोड से) के रूप में
new X500Principal("CN="+useCN) 

कुंजीयुग्म:

KeyPairGenerator g = KeyPairGenerator.getInstance("RSA"); 
g.initialize(1024, UTILS.srng); 
KeyPair keypair = g.generateKeyPair(); 

और jxta कोडित IssuerInfo।

अब जब से मैं bouncycastle.jce पैकेज में नहीं खींच पा रहा हूं, मुझे X509 प्रिंसिपल और X509V3CertificateGenerator कोड को हटाना पड़ा है जो JXTA उपयोग करता है और इसे कार्यान्वित करने के लिए इसे बदलने का प्रयास करता है जो GAE प्रतिबंधों का अनुपालन करता है। org.bouncycastle.X509.X509v3CertificateBuilder का उपयोग कर जेनक्रर्ट विधि के लिए वर्तमान में मेरे पास क्या है।

SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(keypair.getPublic().getEncoded()); 

X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(
    new X500Name(issuer.getName()), 
    BigInteger.ONE, 
    today, until, 
    new X500Name(subject.getName()), 
    subPubKeyInfo); 

समस्या यह है कि मैं keypair.getPublic().getEncoded()SubjectPublicKeyInfo.getInstance() विधि के साथ काम करने के लिए नहीं मिल सकता है। कारखाने में अज्ञात वस्तु: फेंकता java.lang.IllegalArgumentException [बी

सार्वजनिक कुंजी दिखाई देता है निरीक्षण पर बसा होने के लिए:

Sun RSA public key, 1024 bits 
    modulus: 117521430893506212334140912845641570591161279468597426442875306202350445904550279678434051874985419676760802566018092318362676224355315431299979507080364677679613392086245588766565617009250512996843008784370448997729071786062596049780632058501646041736216482596596901215941577208285499619376322050871534546271 
    public exponent: 65537 

मैं इतना नीचे दिए गए लिंक जो इस कोड काम कर रहे दर्शाता है मिल गया है:

Sign CSR using Bouncy Castle

कन्वर्ट करने के लिए genCert नीचे है, लेकिन किसी कारण से, मैं इनकोडिंग सार्वजनिक कुंजी से SubjectPublicKeyInfo बनाने अतीत नहीं मिल सकता है मेरे प्रयास?

किसी भी मदद की बहुत सराहना की जाती है। link:

public static IssuerInfo genCert(X500Principal subject, KeyPair keypair, IssuerInfo issuerinfo) { 
    IssuerInfo info = new IssuerInfo(); 
    try { 
     // set up issuer 
     PrivateKey signer; 
     X500Principal issuer; 

     if (null == issuerinfo) { // self-signed root cert 
      signer = keypair.getPrivate(); 
      issuer = new X500Principal(subject.getEncoded()); 
     } else { // issuer signed service sert 
      signer = issuerinfo.subjectPkey; 
      X500Principal issuer_subject = issuerinfo.cert.getSubjectX500Principal(); 
      issuer = new X500Principal(issuer_subject.getEncoded()); 
     } 

     // set validity 10 years from today 
     Date today = new Date(); 
     Calendar cal = Calendar.getInstance(); 

     cal.setTime(today); 
     cal.add(Calendar.YEAR, 10); 
     Date until = cal.getTime(); 

     SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(keypair.getPublic().getEncoded()); 

    //**Can't get here so i'm not sure if the rest of this works?** 

     AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA"); 
     AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); 

     RSAPrivateCrtKeyParameters cps = (RSAPrivateCrtKeyParameters) keypair.getPrivate(); 
     ContentSigner sigGen = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(cps);    

    X509CertificateHolder certHolder = v3CertGen.build(sigGen); 

    CertificateFactory cf = CertificateFactory.getInstance("X.509"); 

    // Read user Certificate 
    InputStream is1 = new ByteArrayInputStream(certHolder.getEncoded()); 
    X509Certificate eeCert = (X509Certificate) cf.generateCertificate(is1); 
    is1.close(); 

उत्तर

5

मैं यहाँ प्रदान की रेने MAYRHOFER के कोड की मदद से यह पूरा करने में सक्षम था।

X509CertificateGenerator.java

मैं अपने कार्यान्वयन जो केवल एक स्थानीय परीक्षण वातावरण में परीक्षण किया जा चुका है प्रदान की है, लेकिन यह काम करने के लिए प्रकट होता है:

package net.jxta.impl.membership.pse; 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.math.BigInteger; 
import java.security.InvalidKeyException; 
import java.security.Key; 
import java.security.KeyFactory; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.NoSuchProviderException; 
import java.security.PrivateKey; 
import java.security.PublicKey; 
import java.security.SecureRandom; 
import java.security.Signature; 
import java.security.SignatureException; 
import java.security.UnrecoverableKeyException; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import java.security.interfaces.RSAPrivateCrtKey; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.RSAPrivateCrtKeySpec; 
import java.security.spec.RSAPublicKeySpec; 
import java.util.Calendar; 
import java.util.Date; 
import java.util.logging.Logger; 

import javax.security.auth.x500.X500Principal; 

import org.apache.commons.codec.binary.Hex; 

import org.bouncycastle.asn1.ASN1Encodable; 
import org.bouncycastle.asn1.ASN1EncodableVector; 
import org.bouncycastle.asn1.ASN1InputStream; 
import org.bouncycastle.asn1.ASN1Sequence; 
import org.bouncycastle.asn1.DERBMPString; 
import org.bouncycastle.asn1.DERBitString; 
import org.bouncycastle.asn1.DERInteger; 
import org.bouncycastle.asn1.DERNull; 
import org.bouncycastle.asn1.DERObjectIdentifier; 
import org.bouncycastle.asn1.DEROutputStream; 
import org.bouncycastle.asn1.DERSequence; 
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 
import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 
import org.bouncycastle.asn1.x509.DigestInfo; 
import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; 
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 
import org.bouncycastle.asn1.x509.TBSCertificateStructure; 
import org.bouncycastle.asn1.x509.Time; 
import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; 
import org.bouncycastle.asn1.x509.X509CertificateStructure; 
import org.bouncycastle.asn1.x509.X509Name; 
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; 
import org.bouncycastle.crypto.AsymmetricBlockCipher; 
import org.bouncycastle.crypto.AsymmetricCipherKeyPair; 
import org.bouncycastle.crypto.CryptoException; 
import org.bouncycastle.crypto.DataLengthException; 
import org.bouncycastle.crypto.digests.SHA1Digest; 
import org.bouncycastle.crypto.encodings.PKCS1Encoding; 
import org.bouncycastle.crypto.engines.RSAEngine; 
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator; 
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters; 
import org.bouncycastle.crypto.params.RSAKeyParameters; 
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; 
import org.bouncycastle.jce.PrincipalUtil; 
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; 
import org.bouncycastle.jce.provider.X509CertificateObject; 
import org.bouncycastle.x509.X509Util; 
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure; 

/** This class uses the Bouncycastle lightweight API to generate X.509 certificates programmatically. 
* It assumes a CA certificate and its private key to be available and can sign the new certificate with 
* this CA. Some of the code for this class was taken from 
* org.bouncycastle.x509.X509V3CertificateGenerator, but adapted to work with the lightweight API instead of 
* JCE (which is usually not available on MIDP2.0). 
* 
* @author Rene Mayrhofer 
*/ 
public class X509CertificateGenerator { 
    /** Our log4j logger. */ 
    private static Logger logger = Logger.getLogger(X509CertificateGenerator.class.getName()); 

    /** This holds the certificate of the CA used to sign the new certificate. The object is created in the constructor. */ 
    private X509Certificate caCert; 
    /** This holds the private key of the CA used to sign the new certificate. The object is created in the constructor. */ 
    private RSAPrivateCrtKeyParameters caPrivateKey; 

    private boolean useBCAPI; 
    private boolean useCACert; 

    public X509CertificateGenerator(String caFile, String caPassword, String caAlias, boolean useBCAPI) 
      throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, InvalidKeyException, NoSuchProviderException, SignatureException { 
     this.useBCAPI = useBCAPI; 
     this.useCACert = true; 
     logger.info("Loading CA certificate and private key from file '" + caFile + "', using alias '" + caAlias + "' with " 
       + (this.useBCAPI ? "Bouncycastle lightweight API" : "JCE API")); 
     KeyStore caKs = KeyStore.getInstance("PKCS12"); 
     caKs.load(new FileInputStream(new File(caFile)), caPassword.toCharArray()); 

     // load the key entry from the keystore 
     Key key = caKs.getKey(caAlias, caPassword.toCharArray()); 
     if (key == null) { 
      throw new RuntimeException("Got null key from keystore!"); 
     } 
     RSAPrivateCrtKey privKey = (RSAPrivateCrtKey) key; 
     caPrivateKey = new RSAPrivateCrtKeyParameters(privKey.getModulus(), privKey.getPublicExponent(), privKey.getPrivateExponent(), 
       privKey.getPrimeP(), privKey.getPrimeQ(), privKey.getPrimeExponentP(), privKey.getPrimeExponentQ(), privKey.getCrtCoefficient()); 
     // and get the certificate 
     caCert = (X509Certificate) caKs.getCertificate(caAlias); 
     if (caCert == null) { 
      throw new RuntimeException("Got null cert from keystore!"); 
     } 
     logger.info("Successfully loaded CA key and certificate. CA DN is '" + caCert.getSubjectDN().getName() + "'"); 
     caCert.verify(caCert.getPublicKey()); 
     logger.info("Successfully verified CA certificate with its own public key."); 
    } 
    public X509CertificateGenerator(boolean useBCAPI) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, InvalidKeyException, NoSuchProviderException, SignatureException { 
     this.useBCAPI = useBCAPI; 
     this.useCACert = false; 
    } 

    public X509Certificate createCertificate(String dn, int validityDays, X500Principal issuer, KeyPair keypairca) throws 
      IOException, InvalidKeyException, SecurityException, SignatureException, NoSuchAlgorithmException, DataLengthException, CryptoException, KeyStoreException, NoSuchProviderException, CertificateException, InvalidKeySpecException { 
     logger.info("Generating certificate for distinguished subject name '" + 
       dn + "', valid for " + validityDays + " days"); 

     RSAPrivateCrtKey pK = (RSAPrivateCrtKey) keypairca.getPrivate(); 
     caPrivateKey = new RSAPrivateCrtKeyParameters(pK.getModulus(), pK.getPublicExponent(), pK.getPrivateExponent(), 
       pK.getPrimeP(), pK.getPrimeQ(), pK.getPrimeExponentP(), pK.getPrimeExponentQ(), pK.getCrtCoefficient()); 

     SecureRandom sr = new SecureRandom(); 

     PublicKey pubKey; 
     PrivateKey privKey; 

     logger.info("Creating RSA keypair"); 
     // generate the keypair for the new certificate 
     if (useBCAPI) { 
      RSAKeyPairGenerator gen = new RSAKeyPairGenerator(); 
      gen.init(new RSAKeyGenerationParameters(BigInteger.valueOf(3), sr, 1024, 80)); 
      AsymmetricCipherKeyPair keypair = gen.generateKeyPair(); 
      logger.info("Generated keypair, extracting components and creating public structure for certificate"); 
      RSAKeyParameters publicKey = (RSAKeyParameters) keypair.getPublic(); 
      RSAPrivateCrtKeyParameters privateKey = (RSAPrivateCrtKeyParameters) keypair.getPrivate(); 
      // used to get proper encoding for the certificate 
      RSAPublicKeyStructure pkStruct = new RSAPublicKeyStructure(publicKey.getModulus(), publicKey.getExponent()); 
      logger.info("New public key is '" + new String(Hex.encodeHex(pkStruct.getEncoded())) + 
        ", exponent=" + publicKey.getExponent() + ", modulus=" + publicKey.getModulus()); 
      // JCE format needed for the certificate - because getEncoded() is necessary... 
      pubKey = KeyFactory.getInstance("RSA").generatePublic(
        new RSAPublicKeySpec(publicKey.getModulus(), publicKey.getExponent())); 
      // and this one for the KeyStore 
      privKey = KeyFactory.getInstance("RSA").generatePrivate(
        new RSAPrivateCrtKeySpec(publicKey.getModulus(), publicKey.getExponent(), 
          privateKey.getExponent(), privateKey.getP(), privateKey.getQ(), 
          privateKey.getDP(), privateKey.getDQ(), privateKey.getQInv())); 
     } 
     else { 
      // this is the JSSE way of key generation 
      KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); 
      keyGen.initialize(1024, sr); 
      KeyPair keypair = keyGen.generateKeyPair(); 
      privKey = keypair.getPrivate(); 
      pubKey = keypair.getPublic(); 
     } 

     Calendar expiry = Calendar.getInstance(); 
     expiry.add(Calendar.DAY_OF_YEAR, validityDays); 

     X509Name x509Name = new X509Name("CN=" + dn); 
     X509Name x509Issuer = new X509Name(issuer.getName()); 
     V3TBSCertificateGenerator certGen = new V3TBSCertificateGenerator(); 
     certGen.setSerialNumber(new DERInteger(BigInteger.valueOf(System.currentTimeMillis()))); 
     certGen.setIssuer(x509Issuer);//issuer.getName());//PrincipalUtil.getSubjectX509Principal(caCert)); 
     certGen.setSubject(x509Name); 
     DERObjectIdentifier sigOID = X509Util.getAlgorithmOID("SHA1WithRSAEncryption"); 
     AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(sigOID, new DERNull()); 
     certGen.setSignature(sigAlgId); 
     certGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
       new ByteArrayInputStream(pubKey.getEncoded())).readObject())); 
     certGen.setStartDate(new Time(new Date(System.currentTimeMillis()))); 
     certGen.setEndDate(new Time(expiry.getTime())); 

     logger.info("Certificate structure generated, creating SHA1 digest"); 
     // attention: hard coded to be SHA1+RSA! 
     SHA1Digest digester = new SHA1Digest(); 
     AsymmetricBlockCipher rsa = new PKCS1Encoding(new RSAEngine()); 
     TBSCertificateStructure tbsCert = certGen.generateTBSCertificate(); 

     ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 
     DEROutputStream   dOut = new DEROutputStream(bOut); 
     dOut.writeObject(tbsCert); 

     // and now sign 
     byte[] signature; 
     if (useBCAPI) { 
      byte[] certBlock = bOut.toByteArray(); 
      // first create digest 
      logger.info("Block to sign is '" + new String(Hex.encodeHex(certBlock)) + "'");  
      digester.update(certBlock, 0, certBlock.length); 
      byte[] hash = new byte[digester.getDigestSize()]; 
      digester.doFinal(hash, 0); 
      // and sign that 
      rsa.init(true, caPrivateKey); 
      DigestInfo dInfo = new DigestInfo(new AlgorithmIdentifier(X509ObjectIdentifiers.id_SHA1, null), hash); 
      byte[] digest = dInfo.getEncoded(ASN1Encodable.DER); 
      signature = rsa.processBlock(digest, 0, digest.length); 
     } 
     else { 
      // or the JCE way 
      PrivateKey caPrivKey = KeyFactory.getInstance("RSA").generatePrivate(
        new RSAPrivateCrtKeySpec(caPrivateKey.getModulus(), caPrivateKey.getPublicExponent(), 
          caPrivateKey.getExponent(), caPrivateKey.getP(), caPrivateKey.getQ(), 
          caPrivateKey.getDP(), caPrivateKey.getDQ(), caPrivateKey.getQInv())); 

      Signature sig = Signature.getInstance(sigOID.getId()); 
      sig.initSign(caPrivKey, sr); 
      sig.update(bOut.toByteArray()); 
      signature = sig.sign(); 
     } 
     logger.info("SHA1/RSA signature of digest is '" + new String(Hex.encodeHex(signature)) + "'"); 

     // and finally construct the certificate structure 
     ASN1EncodableVector v = new ASN1EncodableVector(); 

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

     X509CertificateObject clientCert = new X509CertificateObject(new X509CertificateStructure(new DERSequence(v))); 
     logger.info("Verifying certificate for correct signature with CA public key"); 

     if(useCACert) clientCert.verify(caCert.getPublicKey()); 

     return clientCert; 
    } 


} 

+0

आप इनमें से इस वर्ग के रूप में कई अपडेट कर लें कर सके बीसी में विधियों/कक्षाओं को अब हटा दिया गया है? – Reddy

+0

बीसी अब ऐप इंजन में समर्थित है इसलिए इसकी आवश्यकता नहीं है। –

+0

@ChukDiesel हम में से उन लोगों के बारे में ऐप इंजन का उपयोग नहीं कर रहे हैं? कृप्या? – Phil